JSFiddle - React, Tailwind, and code Playground

Local File Image Viewer with Web Worker, Offscreen Canvas, and Image Scaling

by skibulk

HTML

<input id="browse" name="files[]" type="file" multiple/>

CSS

canvas {
  display: block;
}

JavaScript

/* To-Do:
 */

console.clear();

// Canvas-supported image-format MIME types
var canvasImageTypes = ["image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg", "image/webp"]

// Image Queue and Worker Status
var queue = [];
var running = false;

// Initialize Web Worker
var myWorker = toWorker(imageProcessor);

// Handle Web Worker Output
myWorker.onmessage = function(event) {

	var bitmap = event.data;
  // console.log("Received Image Data at Root", bitmap);

  // Create Canvas element
  var myCanvas = document.createElement("canvas");
  myCanvas.width = bitmap.width;
  myCanvas.height = bitmap.height;

  // Add image to canvas and canvas to DOM
  var context = myCanvas.getContext("bitmaprenderer");
  context.transferFromImageBitmap(bitmap);
  document.body.appendChild(myCanvas);

	processQueue();
};

// Browse Button
var browse = document.getElementById("browse");

// Handle file selection
browse.onchange = function(event) {
	
  for ( i = 0; i < event.target.files.length; i++ )
  {
  	var file = event.target.files[i];
    
    if (canvasImageTypes.includes(file.type)) {
    
		  queue.push(file);
    }
  }

  if ( !running ) processQueue();
}

// Queue Manager
function processQueue() {

	if ( queue.length ) {
  
      running = true;
      var file = queue.shift();
      // console.log( file );
      myWorker.postMessage(file);
    
  } else {
  
	  running = false;
  }
}

// Web Worker - Read an image file, Draw it to an Offscreen Canvas, Resize, and transfer to parent context
function imageProcessor() {

  // Process image file
  onmessage = async function(event) {

    // console.log("imageReader Received a File", event);
		
    let image = await createImageBitmap( event.data );
    
    var offscreen = new OffscreenCanvas( image.width, image.height);
    var context = offscreen.getContext('2d');
    context.drawImage( image, 0, 0 );

    resample_single( offscreen, 200, 200, true );

    var bitmap = offscreen.transferToImageBitmap();
   ...