javascriptimage-processingcanvashtml5-canvasuint16

rendering to the canvas usiing raw UInt16Array values javascript


I'm trying to render an image from a Uint16Array in javascript. I am not getting any caught errors, but nothing is rendering to the canvas.


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;
}

pixelDataReffernce consoles out to::

  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...

EDIT_

it was that I wasn't using a 4 channel color array, but a binary channel for color. the solution was to increase the size of recorded color to 4 bytes long, and view it on the main thread as 1byte long. however: if i try to access the SharedMemory with
new Uint8ClampedArray(data.buffer), i get the following console warning.

Uncaught TypeError: Failed to construct 'ImageData': The provided ArrayBufferView value must not be shared.

so the next step around was to make temp array on the main thread;

    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);

but that's literally just rezipping information from sharedMememory to a new memory slot for every render... effectively drawing the same information to an array twice. is there a faster way for me to get the pixelData out of sharedMemory and onto the canvas?


Solution

  • If what you have are raw RGBA pixel data, then all you need is to create an ImageData from your Uint16Array and 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>

    Your code did not produce any error because you were not listening to it. If you add a listener to the error event of your imageObject, you'll see it failed to load what you fed it with, because an image is not just raw pixel data, it also has headers, at least to tell the size of the image.