Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scaling down image with Hermite-resize creates thin black line out of nowhere

I have to scale down images and turn them into jpegs in a browser. For this i have been using a javascript resize function called Hermite-resize

This works great. After re-sizing a few hundred images I have noticed something odd happens once every while. With some images a thin black line appears at the bottom of the scaled down jpeg image.

Normal image and one with unwanted black line

I thought this might be due to a transparent line being rendered in the scaled down version. After converting to jpeg, the line then becomes black since jpegs turn no background into a black background.

However if i put a white background behind the image before rendering it as a jpeg, then the problem still remains.

If anyone has an idea on what creates this, or how to fix it, i would much appreciate it.

A jsfiddle to clarify what i mean:

canvas.getContext("2d").fillStyle = '#FFF';
canvas.getContext("2d").fillRect(0, 0, W2, H2);
canvas.getContext("2d").putImageData(img2, 0, 0);
document.getElementById("imageid").src = canvas.toDataURL("image/jpeg");

http://jsfiddle.net/gt4r54zr/1/

I'm not sure if it's related but if i set the transparency to full (255) in the Hermite script, then the same black line appears as well:

data2[x2 + 3] = 255;// Original value: gx_a / weights_alpha;

http://jsfiddle.net/3osq1s1w/3/

like image 464
Kasper Avatar asked Jan 27 '26 08:01

Kasper


1 Answers

The function resample_hermite() calculates these ratios:

var ratio_w_half = Math.ceil(ratio_w/2);
var ratio_h_half = Math.ceil(ratio_h/2);

which are eventually used to determine the dimensions of the re-sized image. Note the Math.ceil, which rounds (ratio_h/2) to the next greatest integer. It appears the black line is being rendered in those cases where the mantissa (i.e., everything to the right the decimal point) of (ratio_h/2) is less than 0.5. In these cases, the calculated height of the image is one pixel too large, and there's no data to fill in these pixels.

Changing

var ratio_h_half = Math.ceil(ratio_h/2);

to

var ratio_h_half = Math.round(ratio_h/2);

seems to fix the problem in your example.

like image 120
rphv Avatar answered Jan 28 '26 22:01

rphv