- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个以下任务,我正在尝试以最有效的方式完成它:我有不同数量的不同大小的图片作为像素数组,我需要将它们逐个像素添加到 Canvas 中。每个像素的值都必须添加到 Canvas 的 ImageData 中,以便结果是两个或多个图像的混合。
我目前的解决方案是从图片需要融合图片大小的位置检索ImageData。然后,我将图片的 ImageData 添加到检索到的 ImageData 中,并将其复制回同一位置。
从某种意义上说,这是 Canvas globalCompositeOperation“更轻”的手动实现。
"use strict";
let canvas = document.getElementById("canvas");
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
let ctx = canvas.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0, 0, width, height);
let imageData = ctx.getImageData(0,0,width,height);
let data = imageData.data;
function random(min, max) {
let num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
}
function createColorArray(size, color) {
let arrayLength = (size*size)*4;
let array = new Uint8ClampedArray(arrayLength);
for (let i = 0; i < arrayLength; i+=4) {
switch (color) {
case 1:
array[i+0] = 255; // r
array[i+1] = 0; // g
array[i+2] = 0; // b
array[i+3] = 255; // a
break;
case 2:
array[i+0] = 0; // r
array[i+1] = 255; // g
array[i+2] = 0; // b
array[i+3] = 255; // a
break;
case 3:
array[i+0] = 0; // r
array[i+1] = 0; // g
array[i+2] = 255; // b
array[i+3] = 255; // a
}
}
return array;
}
function picture() {
this.size = random(10, 500);
this.x = random(0, width);
this.y = random(0, height);
this.color = random(1,3);
this.colorArray = createColorArray(this.size, this.color);
}
picture.prototype.updatePixels = function() {
let imageData = ctx.getImageData(this.x, this.y, this.size, this.size);
let data = imageData.data;
for (let i = 0; i < data.length; ++i) {
data[i]+=this.colorArray[i];
}
ctx.putImageData(imageData, this.x, this.y);
}
let pictures = [];
let numPictures = 50;
for (let i = 0; i < numPictures; ++i) {
let pic = new picture();
pictures.push(pic);
}
function drawPictures() {
for (let i = 0; i < pictures.length; ++i) {
pictures[i].updatePixels();
}
}
drawPictures();
<!DOCTYPE html>
<html>
<head>
<title>...</title>
<style type="text/css">
body {margin: 0px}
#canvas {position: absolute}
</style>
</head>
<body>
<div>
<canvas id="canvas"></canvas>
</div>
<script type="text/javascript" src="js\script.js"></script>
</body>
</html>
这个解决方案工作正常,但速度很慢。我不知道逐像素混合是否可以变得非常高效,但性能缓慢的一个原因可能是我需要获取 ImageData 并将其放回每次新图像混合到 Canvas 中。
因此,主要问题是我如何才能在开始时获取整个 Canvas ImageData 一次,然后根据需要混合到 Canvas 中的每张图片的位置和大小查找正确的像素进行更新,最后将更新的 ImageData 返回到 Canvas ?此外,非常感谢有关如何使混合更高效的任何其他想法。
最佳答案
填充数组的最快方法是使用 Array.fill
函数
const colors = new Uint32Array([0xFF0000FF,0xFF00FF00,0xFFFF00]); // red, green, blue
function createColorArray(size, color) {
const array32 = new Uint32Array(size*size);
array32.fill(colors[color]);
return array32;
}
|
快速固定添加如果您将 0xFF 添加到任何 channel ,并将 0 添加到其他 channel ,则可以使用 |和一个 32 位数组。对于 updatePixels
函数
var imageData = ctx.getImageData(this.x, this.y, this.size, this.size);
var data = new Uint32Array(imageData.data.buffer);
var i = 0;
var pic = this.colorArray; // use a local scope for faster access
do{
data[i] |= pic[i] ; // only works for 0 and FF chanel values
}while(++i < data.length);
ctx.putImageData(imageData, this.x, this.y);
按位或|
类似于算术加法,可用于使用 32 位字来增加值。这些值将作为按位运算的一部分被钳位。
// dark
var red = 0xFF000088;
var green = 0xFF008800;
var yellow = red | green; // 0xFF008888
只要您仅使用 1 或 2 个运算符,就有许多其他方法可以使用 32 位运算来提高性能。更多,您最好使用字节。
如果你知道每个 channel 不会溢出一点,你也可以添加
a = 0xFF101010; // very dark gray
b = 0xFF000080; // dark red
// non overflowing add
c = a + b; // result is 0xFF000090 correct
// as 0x90 + 0x80 will overflow = 0x110 the add will not work
c += b; // result overflows bit to green 0xFF000110 // incorrect
Uint8Array
V Uint8ClampedArray
Uint8Array
比 Uint8ClampedArray
稍快,因为 Uint8Array
跳过了钳位,因此如果不需要钳位,请使用它结果。此外,int typedArray
在分配给它们时不需要舍入值。
var data = Uint8Array(1);
data[0] = Math.random() * 255; // will floor for you
var data = Uint8Array(1);
data[0] = 256; // result is 0
data[0] = -1; // result is 255
var data = Uint8ClampedArray(1);
data[0] = 256; // result is 255
data[0] = -1; // result is 0
var imageDataSource = // some other source
var dataS = new Uint32Array(imageData.data.buffer);
var imageData = ctx.getImageData(this.x, this.y, this.size, this.size);
var data = new Uint32Array(imageData.data.buffer);
data.set(dataS); // copies all data
// or to copy a row of pixels
// from coords
var x = 10;
var y = 10;
var width = 20; // number of pixels to copy
// to coords
var xx = 30
var yy = 30
var start = y * this.size + x;
data.set(dataS.subArray(start, start + width), xx + yy * this.size);
如果不需要,不要继续获取像素数据。如果 putImageData
和 getImageData
之间没有变化,则无需再次获取数据。保留一个缓冲区比不断创建新缓冲区要好。这样也能缓解内存压力,减少GC的工作量。
您可以使用全局复合操作对像素数据执行各种操作。加、减、乘、除、反转这些速度要快得多,到目前为止,在您的代码中我看不出您需要访问像素数据的原因。
关于javascript - 手动混合图像数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46769789/
我知道您不应该将打印与 printf,cout 和 wprintf,wcout 混合使用,但是很难找到一个好的答案,为什么以及是否可以绕过它。问题是我使用了一个用 printf 打印的外部库,而我自己
我有以下问题: class A: animal = 'gerbil' def __init__(self): self.result = self.calculate_
我在屏幕上渲染了一堆形状(多边形),我没有使用深度测试。 我只是希望这些形状在绘制在空白区域时使用自己的颜色,并且在绘制到任何非空区域时使用红色像素,即在我的情况下绘制在另一个多边形上。 这里的问题实
我正在尝试在我的 Groovy/Grails 应用程序中混入一个类,我正在使用 the syntax defined in the docs ,但我不断收到错误消息。 我有一个如下所示的域类: cla
我已经找到了 5349574673 个关于 Alpha 混合的页面,但我仍然无法获得想要的结果。我正在尝试使用 opengl 使 gif/png 文件正确显示(具有透明度/半透明度)。 这是我的初始化
我正在尝试记录以下代码,但我似乎无法让 JSDoc 记录该类,甚至无法引用它的存在。 // SomeMixin.js export default superclass => class SomeMi
我有一个类型家族,我想使用 mixin 以模块化方式“丰富”它们。例如: trait Family { self => trait Dog { def dogname:String
我在 Storyboard中有 Collection View 。我在 Storyboard中有一部分单元格,还有我以编程方式创建的部分单元格。我应该在 sizeForItemAtIndexPath
我有一个字节数组,我想更改它的访问方式。这是数组: char bytes[100]; 我想要另一个数组来改变原始数组的访问方式。如果我们可以将引用放在数组中,它看起来像这样: char& bytes_
我需要从 c 文件调用 cpp 方法。我为此编写了这个界面.. cpp文件 extern "C" void C_Test(int p){ Class::CPP_Test(p); } c文件
我的网站有两份 CSS 表,一份是主 CSS,一份是移动 CSS。问题是在移动设备(iPhone、Android)上查看时,两个样式表会混淆。例如,在 iPhone 上查看网站时,会应用主样式表中的某
维护人员的说明:此问题涉及已过时的 bokeh.charts API,该 API 已于多年前删除。有关使用现代 Bokeh 创建各种条形图的信息,请参阅: https://docs.bokeh.org
在下图中,蓝色圆圈仅用于调试目的。我的目标是蓝色圆圈后面的每一层都应该是透明的。我只想保持蓝色圆圈外面的可见。 这是用 swift 编写的代码: let croissantView = UIV
我不是 SQL 专家。我正在使用 SQL Server 2005,我正在尝试弄清楚如何构造一个查询,以便它可以满足多种要求。我有两个表定义如下: Classroom - ID - Departme
原创: 我之前问过这个问题,但我最初的例子有点不完整,我想我现在可以更具体地说明我的问题。 对于上下文,我在旧的 Apple mac 计算机上使用 openGL 3.3 并尝试渲染四边形的重叠层。每个
是否可以将内联(类似 json)映射与同一对象的常规映射定义混合使用? 考虑以下示例: person: {age: 32, weight: 82} name: foo 生成的人应具有给定的年龄、体
假设我有一个 Parent 类,它有四个字段 A、B、C 和 D,这样 C 和 D 可以选择传递或使用默认实现进行初始化: open class Parent(val a: A, val b: B,
我正在使用 symphony (1.4) 框架在 PHP 中开发一个 Web 应用程序。该代码使用 SVN 进行版本控制。在此网络应用程序中,我们所有客户共享一个共同的基础,以及一些专门为每个客户创建
我想使用两个小部件(一次一个)作为我的应用程序的基础/背景,上面有一个 QML UI 和一个无边框窗口。它应该看起来像这样: 基于 OpenGL 的扫描组件 通过窗口句柄操作的 3D 可视化组件 多个
我们有一个混合的 AngularJS/Angular 8 应用程序,并且我们不断遇到来自不同版本框架的组件之间的变化检测非常慢的问题。到目前为止,我们只在 Angular 组件中使用 AngularJ
我是一名优秀的程序员,十分优秀!