For my 0.3 release of comicbook.js I've attempted to optimize the combination of closepixelate.js and video by writing the image to a canvas in memory then copying the image over to the main canvas when the write was finished. View the demo here.
Using the function renderToCanvas() allows me to buffer the write and return the result
renderToCanvas: function (self, renderOptions, width, height, renderFunction) {
var buffer = document.createElement('canvas');
buffer.width = width;
buffer.height = height;
renderFunction(buffer.getContext('2d'), renderOptions, self);
return buffer;
}
var cached = this.renderToCanvas(
self,
renderOptions,
this.c1.width,
this.c1.height,
function (ctx, renderOptions, self) {
var imgData = self.ctx1.getImageData(0, 0, self.c1.width, self.c1.height);//.data;
self.ctx1.clearRect( 0, 0, self.c1.width, self.c1.height);
for (var i=0, len = renderOptions.length; i < len; i++) {
var opts = renderOptions[i],
res = opts.resolution,
// option defaults
size = opts.size || res,
alpha = opts.alpha || 1,
offset = opts.offset || 0,
offsetX = 0,
offsetY = 0,
cols = self.c1.width / res + 1,
rows = self.c1.height / res + 1,
halfSize = size / 2,
diamondSize = size / Math.SQRT2,
halfDiamondSize = diamondSize / 2;
offsetX = offsetY = offset;
for ( var row = 0; row < rows; row++ ) {
var y = ( row - 0.5 ) * res + offsetY,
// normalize y so shapes around edges get color
pixelY = Math.max( Math.min( y, self.c1.height-1), 0);
for ( var col = 0; col < cols; col++ ) {
var x = ( col - 0.5 ) * res + offsetX,
// normalize y so shapes around edges get color
pixelX = Math.max( Math.min( x, self.c1.width-1), 0),
pixelIndex = ( pixelX + pixelY * self.c1.width ) * 4,
red = imgData.data[ pixelIndex + 0 ],
green = imgData.data[ pixelIndex + 1 ],
blue = imgData.data[ pixelIndex + 2 ],
pixelAlpha = alpha * (imgData.data[ pixelIndex + 3 ] / 255);
ctx.fillStyle = 'rgba(' + red +','+ green +','+ blue +','+ pixelAlpha + ')';
switch ( opts.shape ) {
case 'circle' :
ctx.beginPath();
ctx.arc ( x, y, halfSize, 0, self.PI2, true );
ctx.fill();
ctx.closePath();
break;
case 'diamond' :
ctx.save();
ctx.translate( x, y );
ctx.rotate( self.PI1_4 );
ctx.fillRect( -halfDiamondSize, -halfDiamondSize, diamondSize, diamondSize );
ctx.restore();
break;
default : // square
ctx.fillRect( x - halfSize, y - halfSize, size, size );
} // switch
} // col
} // row
} // options
}
this.ctx1.drawImage(cached, 0, 0);
This technique has definitely helped the performance. Another method of optimization that is probably more efficient is to eliminate the canvas draw functions altogether and create custom functions which modify the image data array directly.
I'm still stumped as to how to actually create the Halftone/Duotone effect which is pretty disappointing. Though the course is now over I'll continue working on this project on my own time.
No comments:
Post a Comment