Search code examples
javascripthtmlimagehtml5-canvas

Generating an RGB image using javascript instead of an RGBA


I'm currently using context.createImageData(width, height) to create an RGBA image with HTML5 canvas. However I don't need to manipulate the images alpha values, so the array that I'm creating is quite a bit larger than it needs to be. Is there no way to use a similar method that creates RGB image data?


Solution

  • You simply can't using canvas.

    Canvas will always give you a RGBA buffer as per specification (the only exception it produces RGB is when you use toDataURL to produce a JPEG).

    You can simply ignore the alpha channel and leave it with value 255, or create a custom Typed Array buffer with only RGB values which you manipulate and then copy over the data to canvas' pixel array.

    var myBuffer = new ArrayBuffer(3 * w * h);    /// calc buffer size in bytes
    var pixels = new Uint8ClampedArray(myBuffer); /// view for buffer
    

    Uint8ClampedArray is the same type of buffer view as the canvas is using.

    Then copy the values from pixels to the image data when the data is ready:

    var imageData = ctx.createImageData(w, h);   /// create a canvas buffer (RGBA)
    var data = imageData.data;                   /// view for the canvas buffer
    var len = data.length;                       /// length of buffer
    var i = 0;                                   /// cursor for RGBA buffer
    var t = 0;                                   /// cursor for RGB buffer
    
    for(; i < len; i += 4) {
        data[i]     = pixels[t];     /// copy RGB data to canvas from custom array
        data[i + 1] = pixels[t + 1];
        data[i + 2] = pixels[t + 2];
        data[i + 3] = 255;           /// remember this one with createImageBuffer
    
        t += 3;
    }
    
    ctx.putImageData(imageData, 0, 0); /// put data to canvas
    

    (the two buffers needs to match in width and height of course).

    If this approach is beneficial largely depends on if you do much processing of the image or not. If not then this will only use more memory and won't give much benefit in performance.

    Depending on how and what you will process there is also the possibility to use a Uint32Array with your custom buffer (in addition to the Uint8ClampedArray - you can have as many views as you want on a buffer) which is useful for pixel displacement and so forth.