I have an html file with a function that used in it but defined in another file. This is the main file that will use this function (composite()):
function recomputeImage()
{
var layers = document.getElementById('layers');
if ( layers.children.length == 0 ) return;
if ( layers.lastChild.image ) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.width = layers.lastChild.image.width;
canvas.height = layers.lastChild.image.height;
var image = new ImageData( layers.lastChild.image.data.slice(),
layers.lastChild.image.width,
layers.lastChild.image.height );
if ( layers.lastChild.imageOpac < 1 ) {
for ( var i=3; i<image.data.length; i+=4 ) {
image.data[i] *= layers.lastChild.imageOpac;
}
}
for ( var i=layers.children.length-2; i>=0; --i ) {
var c = layers.children[i];
if ( c.image ) {
composite( image, c.image, c.imageOpac, c.imagePos );
}
}
context.putImageData( image, 0, 0 );
}
}
My goal is to define this function in a way that do alpha blending (pixle color = fgColor * fgOpacity + (1 - fgOpacity) * bgColor). So I defined this function as below with assuming that each data attribute of image object contains a series of "rgba" data so I excluded the "Alpha" by the "continue" statement line as below:
function composite( bgImg, fgImg, fgOpac, fgPos )
{
var j = 0;
var count = 0;
for(var i = 0; i < fgImg.data.length; ++i, ++j)
{
if(i%4 == 3)
continue;
if(i % fgImg.width == 0)
{
if(count > 0)
j = bgImg.width * count;
++count;
}
bgImg.data[j] =
fgImg.data[i] * fgOpac + (1 - fgOpac) * bgImg.data[j];
}
}
I think the code should working but here it is the result: The foreground image is broken into seprate pieces. I also have problem in using the fgPos argument; it should be used in this code in a way that user can move the foreground image.
I want to drag images in my main file and each image capable of moving while alpha blending happens in each pixle between the images. Obviously I tried the above code (and some other code blocks), but I didn't get any result. The complete file link and again the composite function (the above code) is defined in another file.
The composite
function is at fault. Rewriting from scratch using the same arguments proves it:
function composite( bgImg, fgImg, fgOpac, fgPos ) {
let bgIndex = fgPos.x + fgPos.y * 4*bgImg.width;
let fgIndex = 0;
for( var y=0; y < fgImg.height; ++y, bgIndex += 4*bgImg.width) {
for( var x = 0; x < fgImg.width; ++x, fgIndex += 4) {
for( var color = 0; color<3; ++color) {
bgImg.data[bgIndex + 4*x + color] =
fgImg.data[fgIndex + color] * fgOpac + (1 - fgOpac) * bgImg.data[bgIndex + 4*x + color]
}
}
}
}
The rewrite was iterative right up until it worked when included in the HTML linked offsite. No claim of "good", "best" or "optimized" is made - it is missing a lot of code to detect invalid arguments or positioning of the foreground image either partially or completely outside the background Image. Feel free to rewrite composite
from its specification or modify the above so it makes perfect sense to you as a learning exercise. I suggest not trying to optimize it until after you have it working.