Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

html5 image cropping

I'm using context-blender to apply a multiply effect on the first 192 pixels of the html background-image with a fixed color to achieve a transparency effect on the header of the page.

On the html I have 2 canvas. One for the part of the image to apply the multiply effect and one for the color.

On the javascript, after setting the color of the color-canvas and the width of both canvas to the window.innerWidth I'm getting the background image with:

imageObj.src = $('html').css('background-image').replace(/^url|[\(\)]/g, '');

Now comes the problem. I want to draw a cropped image to the image to the image-canvas so I can apply the multiply effect. I'm trying to do the following:

imageObj.onload = function(){
    // getting the background-image height
    var imageHeight = window.innerWidth * imageObj.height / imageObj.width;

    // get the corresponding pixels of the source image that correspond to the first 192 pixels of the background-image
    var croppedHeight = 192 * imageObj.height / imageHeight;

    // draw the image to the canvas
    imageCanvas.drawImage(imageObj, 0, 0, imageObj.width, croppedHeight, 0, 0, window.innerWidth, 192);

    // apply the multiply effect
    colorCanvas.blendOnto( imageCanvas, 'multiply');
}

But I'm doing something wrong getting the cropped height.

Ex: For an 1536x1152 image and a 1293x679 browser container, the value I'm getting for the source cropped height is 230 but to get the correct crop I need to use something around 296.

Edit:

I'm using background-size: cover on the css to create the background-image

Edit2:

I created a fiddle to illustrate the problem. If you uncomment the line //cHeight *= magicConstant; the cropped image looks a lot better but things stop making sense. I removed the multiply effect on the fiddler but that's not required to reproduce the problem. I also noticed that the behavior changed if I remove the second canvas from the URL.

Btw, this behavior happened with google chrome, but I think the same thing happens on safari and firefox.

like image 539
dcarneiro Avatar asked Apr 12 '12 09:04

dcarneiro


1 Answers

OK, I've fixed it. Man was that hard! Mainly because you forgot to set the imageCanvas' canvas height. It also didn't help that the image has a white border. I spent a hell of a lot of time trying to figure out where the padding was coming from.

So to start, for the case of the fiddle, in function doBlending(), set imageCanvas.canvas.height = height;

Then the calculations in crop() need to cover 2 possibilities. Is the image being scaled for height and truncated on the left or scaled for width and truncated on the bottom? I'm not going to write both for you, but here's the one for the case where it is scaled for height:

function crop(imageObj, imageCanvas, colorCanvas) {
    // Assumes bg image is scaled for hight
    var scale = imageObj.height / window.innerHeight; 
    var targetHeight = imageCanvas.canvas.height;
    var targetWidth = window.innerWidth;

    imageCanvas.drawImage(imageObj, 
                          0, 0, targetWidth * scale, targetHeight * scale,
                          0, 0, targetWidth, targetHeight);
}

I really have no idea where you came up with the scaling factors in your example. The image is going to be scaled by multiplying both the x and y dimensions by some scale factor. That's how you preserve the aspect ratio. The scale factor will be the larger of the one to make the height of the image match the height of the window and the one to make the width of the image match the width of the window.

like image 198
Old Pro Avatar answered Oct 12 '22 22:10

Old Pro