Skip to content

Instantly share code, notes, and snippets.

@krhoyt
Last active October 15, 2023 11:54
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save krhoyt/2c3514f20a05e4916a1caade0782953f to your computer and use it in GitHub Desktop.
Save krhoyt/2c3514f20a05e4916a1caade0782953f to your computer and use it in GitHub Desktop.
Canvas ImageData to Web Worker
<html>
<head>
<title>Image Processing Worker</title>
<style>
body {
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
}
canvas {
border: solid 1px lightgrey;
}
img {
left: 0;
position: absolute;
top: 0;
visibility: hidden;
}
</style>
</head>
<body>
<canvas width="640" height="480"></canvas>
<img>
<script>
class Worked {
constructor() {
this.canvas = document.querySelector( 'canvas' );
this.canvas.addEventListener( 'dragover', ( evt ) => this.doCanvasOver( evt ) );
this.canvas.addEventListener( 'drop', ( evt ) => this.doCanvasDrop( evt ) );
this.context = this.canvas.getContext( '2d' );
this.image = document.querySelector( 'img' );
this.image.addEventListener( 'load', ( evt ) => this.doImageLoad( evt ) );
this.reader = new FileReader();
this.reader.addEventListener( 'load', ( evt ) => this.doFileLoad( evt ) );
this.worker = new Worker( 'script/worker.js' );
this.worker.addEventListener( 'message', ( evt ) => this.doWorkerMessage( evt ) );
}
doCanvasDrop( evt ) {
evt.preventDefault();
this.reader.readAsDataURL( evt.dataTransfer.files[0] );
}
doCanvasOver( evt ) {
evt.preventDefault();
}
doFileLoad( evt ) {
this.image.src = this.reader.result;
}
doImageLoad( evt ) {
this.context.drawImage( this.image, 0, 0, 640, 480 );
let pixels = this.context.getImageData( 0, 0, 640, 480 );
this.worker.postMessage( {
pixels: pixels.data.buffer,
width: this.canvas.width,
height: this.canvas.height,
channels: 4
}, [pixels.data.buffer] );
// this.worker.postMessage( pixels.data.buffer, [pixels.data.buffer] );
}
doWorkerMessage( evt ) {
let pixels = new ImageData( 640, 480 );
pixels.data.set( new Uint8ClampedArray( evt.data ) );
this.context.putImageData( pixels, 0, 0 );
}
}
let app = new Worked();
</script>
</body>
</html>
self.addEventListener( 'message', ( evt ) => {
let pixels = new ImageData( evt.data.width, evt.data.height );
pixels.data.set( new Uint8ClampedArray( evt.data.pixels ) );
for( let x = 0; x < pixels.data.length; x += evt.data.channels ) {
let average = (
pixels.data[x] +
pixels.data[x + 1] +
pixels.data[x + 2]
) / 3;
pixels.data[x] = average;
pixels.data[x + 1] = average;
pixels.data[x + 2] = average;
}
let bytes = new Uint8ClampedArray( output.pixels );
self.postMessage( {
type: 'end',
bytes: bytes
}, [bytes.buffer] );
// self.postMessage( pixels.data.buffer, [pixels.data.buffer] );
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment