Question

I'm using a canvas to resize client-side an image before uploading it on the server.

maxWidth = 500;
maxHeight = 500;
//manage resizing
if (image.width >= image.height) {
    var ratio = 1 / (image.width / maxWidth);
}
else {
    var ratio = 1 / (image.height / maxHeight);
}

...

canvas.width = image.width * ratio;
canvas.height = image.height * ratio;
var resCtx = canvas.getContext('2d');
resCtx.drawImage(image, 0, 0, image.width * ratio, image.height * ratio);

This works, since on the server is saved the resized image, but there are two points i would like to improve:

  • image weight in KB is important to me; i want a very light weight image; even if it is resized, the canvas' image is still too heavy; i can see that the image saved on the server has a resolution of 96 DPI and 32-bit of color-depth even if the original image has a resolution of 72 DPI and 24-bit of color-depth; why? Can i set the canvas' image resolution?

  • the resized image does not look very nice, because the resizing proces introduce distortion... I've tried the custom algorithm by GameAlchemist in this post: HTML5 Canvas Resize (Downscale) Image High Quality? getting a very nice result, but then the resized image was more heavy in KB than the original one! Is there a good algorithm in order to get quality resized images keeping them lightweight?

Was it helpful?

Solution

DPI does not matter at all with images. An image at 1k x 1k will be just the same if 892478427 DPI or as 1 DPI. DPI is arbitrary in this context so ignore that part (it is only used as information for DTP programs so they know the relative size compared to document size). Images are only measured in pixels.

Canvas is RGBA based (32-bits, 24-bit colors + 8 bit alpha channel) so it's optimal form for exporting images will be in this format (ie. PNG files). You can however export 24-bits images without the alpha channel by requesting JPEG format as export format.

Compression is basically signal processing. As in all forms of (lossy) compression you try to remove frequencies in the signal in order to reduce the size. The more high frequencies there is the harder it is to compress the image (or sound or anything else signal based).

In images high frequency manifests as small details (thin lines and so forth) and as noise. To reduce the size of a compressed image you need to remove high frequencies. You can do this by using interpolation as a low-pass filter. A blur is a form of low-pass filter as well and they work in the same way in principle.

So in order to reduce image size you can apply a slight blur on the image before compressing it.

The JPEG format support quality settings which can reduce the size as well although this using a different approach than blurring:

// 0.5 = quality, lower = lower quality. Range is [0.0, 1.0]
var dataUri = canvas.toDataURL('image/jpeg', 0.5);

To blur an image you can use a simple and fast method of scaling it to half the size and then back up (with smoothing enabled). This will use interpolation as a low-pass filter by averaging the pixels.

Or you can use a "real" blur algorithm such as Gaussian blur as well as box blur, but only with a small amount.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top