使用原始 UInt16Array 值 javascript 渲染到画布
Posted
技术标签:
【中文标题】使用原始 UInt16Array 值 javascript 渲染到画布【英文标题】:rendering to the canvas usiing raw UInt16Array values javascript 【发布时间】:2020-07-09 16:10:13 【问题描述】:我正在尝试从 javascript 中的 Uint16Array 渲染图像。 我没有收到任何捕获的错误,但没有任何内容呈现到画布上。
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const bufferMemoryAllocation = cellCount*2; //double the size 2bytes--16bits--per memory slot
const bitArray = new SharedArrayBuffer(bufferMemoryAllocation); // double the number of cells
const pixelData = new SharedArrayBuffer(bufferMemoryAllocation);
const pixelDataCanvas = new Uint16Array(pixelData);
const videoResolutions = [name: "test", height: 1000, width:1000,name:"1080", height: 1080, width:1920,name:"4k", height: 2160, width:3840];
canvas.height = videoResolutions[2].height;
canvas.width = videoResolutions[2].width;
const cellScale = 2;
const drawHeight = Math.floor(canvas.height/cellScale);
const drawWidth = Math.floor(canvas.width/cellScale);
const cellCount=drawHeight*drawWidth;
function renderToCanvas()
ctx.drawImage(renderToImage(pixelDataCanvas),0,0,drawWidth,drawHeight);
function renderToImage(pixelDataReffernce)
let imageObject = new Image(canvas.height,canvas.width);
let imageString = 'data:image/bmp;base64,'+btoa(pixelDataReffernce);
imageObject.src = imageString;
// console.log(imageObject);
return imageObject;
pixelDataReference 控制台输出到::
Uint16Array(2073600) [0, 0, 0, 0, 0, 0, 0, 0, 1024, 1024, 1024, 0, 0, 0, 0, 1024, 0, 0, 0, 1024, 1024, 1024, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 1024, 0, 1024, 1024, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0...
编辑_
我没有使用 4 通道颜色数组,而是使用二进制颜色通道。解决方案是将记录颜色的大小增加到 4 个字节长,并在主线程上查看为 1 个字节长。 但是:如果我尝试使用 访问 SharedMemory new Uint8ClampedArray(data.buffer),我收到以下控制台警告。
Uncaught TypeError: Failed to construct 'ImageData': The provided ArrayBufferView value must not be shared.
所以下一步是在主线程上创建临时数组;
const pixelTransViewer = new Uint8Array(pixelData);
const tA = new Uint8ClampedArray(data.buffer);
for(let i=0;i<tA.length;i++)
for(let j=0;j < 8;j++)
tA[i]=setBitState(tA[i],j,checkBit(pixelTransViewer[i],j));
const img = new ImageData(tA, span);
但这实际上只是将信息从 sharedMememory 重新压缩到每次渲染的新内存插槽...有效地将相同的信息绘制到数组中两次。 有没有更快的方法让我将 pixelData 从 sharedMemory 中取出并放到画布上?
【问题讨论】:
【参考方案1】:如果您拥有的是原始 RGBA 像素数据,那么您只需要从 Uint16Array 和 put it on your canvas 中输入 create an ImageData 和 put it on your canvas。
const img_width = 50;
const img_height = 50;
const data = new Uint16Array((img_width * img_height) * 2 );
// make some noise
crypto.getRandomValues(data);
const canvas = document.getElementById('canvas');
canvas.width = img_width;
canvas.height = img_height;
const ctx = canvas.getContext('2d');
const img = new ImageData(
new Uint8ClampedArray(data.buffer),
img_width,
img_height
);
ctx.putImageData( img, 0, 0 );
<canvas id="canvas"></canvas>
您的代码没有产生任何错误,因为您没有在听它。如果你为imageObject
的error
事件添加一个监听器,你会看到它无法加载你输入的内容,因为图像不仅仅是原始像素数据,它还有标题,至少可以告诉图片的大小。
【讨论】:
我已经尝试添加一个 addevent 监听器 - 但画布既没有注册任何错误,也没有 ctx 附加,但是在阅读了您的评论后,我更改了格式以捕获 8bit4channel 颜色数据,现在它可以很好地渲染到画布上……但是-缩放图像-我遇到的每个解决方案都违背了将图像渲染一次的目的。所以这就是我现在正在努力解决的问题 - 编辑我上面的帖子并进行更新。 “未捕获的 TypeError:无法构造 'ImageData':提供的 ArrayBufferView 值不得共享。” - 我需要创建一个新数组并将其复制过来 - 有没有办法直接使用 sharedData? 不,数据必须属于ImageData。只需将其复制到普通的 ArrayBuffer 即可。为什么你想要一个 SharedArrayBuffer 顺便说一句?为了避免 GC,只需存储该 ImageData 并每帧更新其 ArrayBuffer,无需重新分配任何新内容。 Ps:在以使现有答案无效的方式回答问题后编辑问题在 *** 中是不受欢迎的,并且被认为是苛刻的。更不用说在这样做时不接受它了......我们更希望您提出一个新的问题,而不是新的细节。 是的,很抱歉没有解释为什么我使用共享数组。你的方式很有效,带着一点爱。我正在与网络工作者并行运行计算(拆分工作,所以每个工作者都在一个部分上工作) - 换句话说,你是说没有办法直接从共享内存创建图像?,你需要分配它每次都到非共享内存?以上是关于使用原始 UInt16Array 值 javascript 渲染到画布的主要内容,如果未能解决你的问题,请参考以下文章