Resizing an image in an HTML5 canvas












300















I'm trying to create a thumbnail image on the client side using javascript and a canvas element, but when I shrink the image down, it looks terrible. It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. I know its possible to get this to look right, because this site can do it just fine using a canvas as well. I've tried using the same code they do as shown in the "[Source]" link, but it still looks terrible. Is there something I'm missing, some setting that needs to be set or something?



EDIT:



I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.



Here is the relevant code:



reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");

img.onload = function()
{
var ratio = 1;

if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;

canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);

canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};

img.src = reader.result;
}


EDIT2:



Seems I was mistaken, the linked website wasn't doing any better of a job of downsizing the image. I tried the other methods suggested and none of them look any better. This is what the different methods resulted in:



Photoshop:



alt text



Canvas:



alt text



Image with image-rendering: optimizeQuality set and scaled with width/height:



alt text



Image with image-rendering: optimizeQuality set and scaled with -moz-transform:



alt text



Canvas resize on pixastic:



alt text



I guess this means firefox isn't using bicubic sampling like its supposed to. I'll just have to wait until they actually add it.



EDIT3:



Original Image










share|improve this question

























  • Can you post the code you're using to resize the image?

    – Xavi
    Feb 20 '10 at 21:13











  • Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

    – leepowers
    Feb 20 '10 at 21:43











  • Can you post a copy of the original image?

    – Xavi
    Feb 23 '10 at 1:31











  • Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

    – defines
    Mar 5 '10 at 14:57






  • 27





    Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

    – Telanor
    Mar 8 '10 at 16:51
















300















I'm trying to create a thumbnail image on the client side using javascript and a canvas element, but when I shrink the image down, it looks terrible. It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. I know its possible to get this to look right, because this site can do it just fine using a canvas as well. I've tried using the same code they do as shown in the "[Source]" link, but it still looks terrible. Is there something I'm missing, some setting that needs to be set or something?



EDIT:



I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.



Here is the relevant code:



reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");

img.onload = function()
{
var ratio = 1;

if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;

canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);

canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};

img.src = reader.result;
}


EDIT2:



Seems I was mistaken, the linked website wasn't doing any better of a job of downsizing the image. I tried the other methods suggested and none of them look any better. This is what the different methods resulted in:



Photoshop:



alt text



Canvas:



alt text



Image with image-rendering: optimizeQuality set and scaled with width/height:



alt text



Image with image-rendering: optimizeQuality set and scaled with -moz-transform:



alt text



Canvas resize on pixastic:



alt text



I guess this means firefox isn't using bicubic sampling like its supposed to. I'll just have to wait until they actually add it.



EDIT3:



Original Image










share|improve this question

























  • Can you post the code you're using to resize the image?

    – Xavi
    Feb 20 '10 at 21:13











  • Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

    – leepowers
    Feb 20 '10 at 21:43











  • Can you post a copy of the original image?

    – Xavi
    Feb 23 '10 at 1:31











  • Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

    – defines
    Mar 5 '10 at 14:57






  • 27





    Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

    – Telanor
    Mar 8 '10 at 16:51














300












300








300


253






I'm trying to create a thumbnail image on the client side using javascript and a canvas element, but when I shrink the image down, it looks terrible. It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. I know its possible to get this to look right, because this site can do it just fine using a canvas as well. I've tried using the same code they do as shown in the "[Source]" link, but it still looks terrible. Is there something I'm missing, some setting that needs to be set or something?



EDIT:



I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.



Here is the relevant code:



reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");

img.onload = function()
{
var ratio = 1;

if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;

canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);

canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};

img.src = reader.result;
}


EDIT2:



Seems I was mistaken, the linked website wasn't doing any better of a job of downsizing the image. I tried the other methods suggested and none of them look any better. This is what the different methods resulted in:



Photoshop:



alt text



Canvas:



alt text



Image with image-rendering: optimizeQuality set and scaled with width/height:



alt text



Image with image-rendering: optimizeQuality set and scaled with -moz-transform:



alt text



Canvas resize on pixastic:



alt text



I guess this means firefox isn't using bicubic sampling like its supposed to. I'll just have to wait until they actually add it.



EDIT3:



Original Image










share|improve this question
















I'm trying to create a thumbnail image on the client side using javascript and a canvas element, but when I shrink the image down, it looks terrible. It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. I know its possible to get this to look right, because this site can do it just fine using a canvas as well. I've tried using the same code they do as shown in the "[Source]" link, but it still looks terrible. Is there something I'm missing, some setting that needs to be set or something?



EDIT:



I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.



Here is the relevant code:



reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");

img.onload = function()
{
var ratio = 1;

if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;

canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);

canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};

img.src = reader.result;
}


EDIT2:



Seems I was mistaken, the linked website wasn't doing any better of a job of downsizing the image. I tried the other methods suggested and none of them look any better. This is what the different methods resulted in:



Photoshop:



alt text



Canvas:



alt text



Image with image-rendering: optimizeQuality set and scaled with width/height:



alt text



Image with image-rendering: optimizeQuality set and scaled with -moz-transform:



alt text



Canvas resize on pixastic:



alt text



I guess this means firefox isn't using bicubic sampling like its supposed to. I'll just have to wait until they actually add it.



EDIT3:



Original Image







javascript html5 canvas image-resizing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 27 '18 at 16:36









kukuch

1916




1916










asked Feb 20 '10 at 20:58









TelanorTelanor

2,05962333




2,05962333













  • Can you post the code you're using to resize the image?

    – Xavi
    Feb 20 '10 at 21:13











  • Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

    – leepowers
    Feb 20 '10 at 21:43











  • Can you post a copy of the original image?

    – Xavi
    Feb 23 '10 at 1:31











  • Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

    – defines
    Mar 5 '10 at 14:57






  • 27





    Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

    – Telanor
    Mar 8 '10 at 16:51



















  • Can you post the code you're using to resize the image?

    – Xavi
    Feb 20 '10 at 21:13











  • Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

    – leepowers
    Feb 20 '10 at 21:43











  • Can you post a copy of the original image?

    – Xavi
    Feb 23 '10 at 1:31











  • Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

    – defines
    Mar 5 '10 at 14:57






  • 27





    Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

    – Telanor
    Mar 8 '10 at 16:51

















Can you post the code you're using to resize the image?

– Xavi
Feb 20 '10 at 21:13





Can you post the code you're using to resize the image?

– Xavi
Feb 20 '10 at 21:13













Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

– leepowers
Feb 20 '10 at 21:43





Are you trying to resize a GIF image or similar image with a limited palette? Even in photoshop these images don't scale down well unless you convert them to RGB.

– leepowers
Feb 20 '10 at 21:43













Can you post a copy of the original image?

– Xavi
Feb 23 '10 at 1:31





Can you post a copy of the original image?

– Xavi
Feb 23 '10 at 1:31













Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

– defines
Mar 5 '10 at 14:57





Resizing the image using javascript is a bit kludge - not only are you using client processing power to resize the image, you are doing it on every single page load. Why not just save a downscaled version from photoshop and serve it instead/in tandem with the original image?

– defines
Mar 5 '10 at 14:57




27




27





Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

– Telanor
Mar 8 '10 at 16:51





Because I'm making an image uploader with the capability to resize and crop the images before uploading them.

– Telanor
Mar 8 '10 at 16:51












18 Answers
18






active

oldest

votes


















381














So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:



// returns a function that calculates lanczos weight
function lanczosCreate(lobes) {
return function(x) {
if (x > lobes)
return 0;
x *= Math.PI;
if (Math.abs(x) < 1e-16)
return 1;
var xx = x / lobes;
return Math.sin(x) * Math.sin(xx) / x / xx;
};
}

// elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
function thumbnailer(elem, img, sx, lobes) {
this.canvas = elem;
elem.width = img.width;
elem.height = img.height;
elem.style.display = "none";
this.ctx = elem.getContext("2d");
this.ctx.drawImage(img, 0, 0);
this.img = img;
this.src = this.ctx.getImageData(0, 0, img.width, img.height);
this.dest = {
width : sx,
height : Math.round(img.height * sx / img.width),
};
this.dest.data = new Array(this.dest.width * this.dest.height * 3);
this.lanczos = lanczosCreate(lobes);
this.ratio = img.width / sx;
this.rcp_ratio = 2 / this.ratio;
this.range2 = Math.ceil(this.ratio * lobes / 2);
this.cacheLanc = {};
this.center = {};
this.icenter = {};
setTimeout(this.process1, 0, this, 0);
}

thumbnailer.prototype.process1 = function(self, u) {
self.center.x = (u + 0.5) * self.ratio;
self.icenter.x = Math.floor(self.center.x);
for (var v = 0; v < self.dest.height; v++) {
self.center.y = (v + 0.5) * self.ratio;
self.icenter.y = Math.floor(self.center.y);
var a, r, g, b;
a = r = g = b = 0;
for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
if (i < 0 || i >= self.src.width)
continue;
var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
if (!self.cacheLanc[f_x])
self.cacheLanc[f_x] = {};
for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
if (j < 0 || j >= self.src.height)
continue;
var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
if (self.cacheLanc[f_x][f_y] == undefined)
self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
+ Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
weight = self.cacheLanc[f_x][f_y];
if (weight > 0) {
var idx = (j * self.src.width + i) * 4;
a += weight;
r += weight * self.src.data[idx];
g += weight * self.src.data[idx + 1];
b += weight * self.src.data[idx + 2];
}
}
}
var idx = (v * self.dest.width + u) * 3;
self.dest.data[idx] = r / a;
self.dest.data[idx + 1] = g / a;
self.dest.data[idx + 2] = b / a;
}

if (++u < self.dest.width)
setTimeout(self.process1, 0, self, u);
else
setTimeout(self.process2, 0, self);
};
thumbnailer.prototype.process2 = function(self) {
self.canvas.width = self.dest.width;
self.canvas.height = self.dest.height;
self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
var idx, idx2;
for (var i = 0; i < self.dest.width; i++) {
for (var j = 0; j < self.dest.height; j++) {
idx = (j * self.dest.width + i) * 3;
idx2 = (j * self.dest.width + i) * 4;
self.src.data[idx2] = self.dest.data[idx];
self.src.data[idx2 + 1] = self.dest.data[idx + 1];
self.src.data[idx2 + 2] = self.dest.data[idx + 2];
}
}
self.ctx.putImageData(self.src, 0, 0);
self.canvas.style.display = "block";
};


...with which you can produce results like these!



img717.imageshack.us/img717/8910/lanczos358.png



so anyway, here is a 'fixed' version of your example:



img.onload = function() {
var canvas = document.createElement("canvas");
new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
// but feel free to raise it up to 8. Your client will appreciate
// that the program makes full use of his machine.
document.body.appendChild(canvas);
};


Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!



Umm, where's my sarcasm tag?



(since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)



actually due to limitation of javascript, multi-core is not supported.






share|improve this answer





















  • 2





    I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

    – Telanor
    Jul 11 '10 at 22:52






  • 3





    Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

    – syockit
    Jul 16 '10 at 16:33






  • 5





    You are awesome and deserve tons of awesomeage.

    – Rocklan
    Feb 2 '13 at 4:05






  • 5





    This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

    – mpen
    Feb 16 '13 at 20:25






  • 2





    How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

    – Blindman67
    Jan 3 '16 at 16:15



















36














Fast image resize/resample algorithm using Hermite filter with JavaScript. Support transparency, gives good quality. Preview:


enter image description here



Update: version 2.0 added on GitHub (faster, web workers + transferable objects). Finally i got it working!



Git: https://github.com/viliusle/Hermite-resize

Demo: http://viliusle.github.io/miniPaint/



/**
* Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
*
* @param {HtmlElement} canvas
* @param {int} width
* @param {int} height
* @param {boolean} resize_canvas if true, canvas will be resized. Optional.
*/
function resample_single(canvas, width, height, resize_canvas) {
var width_source = canvas.width;
var height_source = canvas.height;
width = Math.round(width);
height = Math.round(height);

var ratio_w = width_source / width;
var ratio_h = height_source / height;
var ratio_w_half = Math.ceil(ratio_w / 2);
var ratio_h_half = Math.ceil(ratio_h / 2);

var ctx = canvas.getContext("2d");
var img = ctx.getImageData(0, 0, width_source, height_source);
var img2 = ctx.createImageData(width, height);
var data = img.data;
var data2 = img2.data;

for (var j = 0; j < height; j++) {
for (var i = 0; i < width; i++) {
var x2 = (i + j * width) * 4;
var weight = 0;
var weights = 0;
var weights_alpha = 0;
var gx_r = 0;
var gx_g = 0;
var gx_b = 0;
var gx_a = 0;
var center_y = (j + 0.5) * ratio_h;
var yy_start = Math.floor(j * ratio_h);
var yy_stop = Math.ceil((j + 1) * ratio_h);
for (var yy = yy_start; yy < yy_stop; yy++) {
var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
var center_x = (i + 0.5) * ratio_w;
var w0 = dy * dy; //pre-calc part of w
var xx_start = Math.floor(i * ratio_w);
var xx_stop = Math.ceil((i + 1) * ratio_w);
for (var xx = xx_start; xx < xx_stop; xx++) {
var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
var w = Math.sqrt(w0 + dx * dx);
if (w >= 1) {
//pixel too far
continue;
}
//hermite filter
weight = 2 * w * w * w - 3 * w * w + 1;
var pos_x = 4 * (xx + yy * width_source);
//alpha
gx_a += weight * data[pos_x + 3];
weights_alpha += weight;
//colors
if (data[pos_x + 3] < 255)
weight = weight * data[pos_x + 3] / 250;
gx_r += weight * data[pos_x];
gx_g += weight * data[pos_x + 1];
gx_b += weight * data[pos_x + 2];
weights += weight;
}
}
data2[x2] = gx_r / weights;
data2[x2 + 1] = gx_g / weights;
data2[x2 + 2] = gx_b / weights;
data2[x2 + 3] = gx_a / weights_alpha;
}
}
//clear and resize canvas
if (resize_canvas === true) {
canvas.width = width;
canvas.height = height;
} else {
ctx.clearRect(0, 0, width_source, height_source);
}

//draw
ctx.putImageData(img2, 0, 0);
}





share|improve this answer


























  • Maybe you can include links to your miniPaint demo and Github repo?

    – syockit
    Sep 11 '13 at 13:45






  • 1





    Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

    – syockit
    Sep 11 '13 at 13:50











  • added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

    – ViliusL
    Sep 11 '13 at 18:47











  • Huge difference and decent performance. Thank you very much! before and after

    – KevBurnsJr
    Sep 12 '13 at 6:56








  • 2





    @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

    – syockit
    Nov 16 '13 at 9:06



















23














Try pica - that's a highly optimized resizer with selectable algorythms. See demo.



For example, original image from first post is resized in 120ms with Lanczos filter and 3px window or 60ms with Box filter and 0.5px window. For huge 17mb image 5000x3000px resize takes ~1s on desktop and 3s on mobile.



All resize principles were described very well in this thread, and pica does not add rocket science. But it's optimized very well for modern JIT-s, and is ready to use out of box (via npm or bower). Also, it use webworkers when available to avoid interface freezes.



I also plan to add unsharp mask support soon, because it's very useful after downscale.






share|improve this answer































    14














    I know this is an old thread but it might be useful for some people such as myself that months after are hitting this issue for the first time.



    Here is some code that resizes the image every time you reload the image. I am aware this is not optimal at all, but I provide it as a proof of concept.



    Also, sorry for using jQuery for simple selectors but I just feel too comfortable with the syntax.






    $(document).on('ready', createImage);
    $(window).on('resize', createImage);

    var createImage = function(){
    var canvas = document.getElementById('myCanvas');
    canvas.width = window.innerWidth || $(window).width();
    canvas.height = window.innerHeight || $(window).height();
    var ctx = canvas.getContext('2d');
    img = new Image();
    img.addEventListener('load', function () {
    ctx.drawImage(this, 0, 0, w, h);
    });
    img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
    };

    html, body{
    height: 100%;
    width: 100%;
    margin: 0;
    padding: 0;
    background: #000;
    }
    canvas{
    position: absolute;
    left: 0;
    top: 0;
    z-index: 0;
    }

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>Canvas Resize</title>
    </head>
    <body>
    <canvas id="myCanvas"></canvas>
    </body>
    </html>





    My createImage function is called once when the document is loaded and after that it is called every time the window receives a resize event.



    I tested it in Chrome 6 and Firefox 3.6, both on the Mac. This "technique" eats processor as it if was ice cream in the summer, but it does the trick.






    share|improve this answer

































      9














      I've put up some algorithms to do image interpolation on html canvas pixel arrays that might be useful here:



      https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2



      These can be copy/pasted and can be used inside of web workers to resize images (or any other operation that requires interpolation - I'm using them to defish images at the moment).



      I haven't added the lanczos stuff above, so feel free to add that as a comparison if you'd like.






      share|improve this answer

































        6














        If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. Here's a quick example:



        .small-image {
        width: 100px;
        height: 100px;
        }


        Note that the height and width can also be set using JavaScript. Here's quick code sample:



        var img = document.getElement("my-image");
        img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
        img.style.height = 100 + "px"; // otherwise you'll confuse IE


        Also, to ensure that the resized image looks good, add the following css rules to image selector:





        • -ms-interpolation-mode: bicubic: introduce in IE7


        • image-rendering: optimizeQuality: introduced in FireFox 3.6


        As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome.



        If setting the css width and height doesn't work, you may want to play with a css transform:




        • -moz-transform: scale(sx[, sy])

        • -webkit-transform:scale(sx[, sy])


        If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size.



        See this question for more details.



        Hope this helps!






        share|improve this answer





















        • 5





          Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

          – Nestor
          Mar 21 '11 at 1:23






        • 1





          Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

          – syockit
          Jul 7 '13 at 12:52



















        6














        This is a javascript function adapted from @Telanor's code. When passing a image base64 as first argument to the function, it returns the base64 of the resized image. maxWidth and maxHeight are optional.



        function thumbnail(base64, maxWidth, maxHeight) {

        // Max size for thumbnail
        if(typeof(maxWidth) === 'undefined') var maxWidth = 500;
        if(typeof(maxHeight) === 'undefined') var maxHeight = 500;

        // Create and initialize two canvas
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        var canvasCopy = document.createElement("canvas");
        var copyContext = canvasCopy.getContext("2d");

        // Create original image
        var img = new Image();
        img.src = base64;

        // Determine new ratio based on max size
        var ratio = 1;
        if(img.width > maxWidth)
        ratio = maxWidth / img.width;
        else if(img.height > maxHeight)
        ratio = maxHeight / img.height;

        // Draw original image in second canvas
        canvasCopy.width = img.width;
        canvasCopy.height = img.height;
        copyContext.drawImage(img, 0, 0);

        // Copy and resize second canvas to first canvas
        canvas.width = img.width * ratio;
        canvas.height = img.height * ratio;
        ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

        return canvas.toDataURL();

        }





        share|improve this answer
























        • your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

          – confile
          Sep 23 '13 at 12:58



















        6














        I'd highly suggest you check out this link and make sure it is set to true.




        Controlling image scaling behavior



        Introduced in Gecko 1.9.2 (Firefox 3.6
        / Thunderbird 3.1 / Fennec 1.0)



        Gecko 1.9.2 introduced the
        mozImageSmoothingEnabled property to
        the canvas element; if this Boolean
        value is false, images won't be
        smoothed when scaled. This property is
        true by default. view plainprint?




        1. cx.mozImageSmoothingEnabled = false;







        share|improve this answer


























        • Yup, its set to true

          – Telanor
          Jul 14 '10 at 4:58



















        4














        For resizing to image with width less that original, i use:



            function resize2(i) {
        var cc = document.createElement("canvas");
        cc.width = i.width / 2;
        cc.height = i.height / 2;
        var ctx = cc.getContext("2d");
        ctx.drawImage(i, 0, 0, cc.width, cc.height);
        return cc;
        }
        var cc = img;
        while (cc.width > 64 * 2) {
        cc = resize2(cc);
        }
        // .. than drawImage(cc, .... )


        and it works =).






        share|improve this answer































          4














          i got this image by right clicking the canvas element in firefox and saving as.



          alt text



          var img = new Image();
          img.onload = function () {
          console.debug(this.width,this.height);
          var canvas = document.createElement('canvas'), ctx;
          canvas.width = 188;
          canvas.height = 150;
          document.body.appendChild(canvas);
          ctx = canvas.getContext('2d');
          ctx.drawImage(img,0,0,188,150);
          };
          img.src = 'original.jpg';


          so anyway, here is a 'fixed' version of your example:



          var img = new Image();
          // added cause it wasnt defined
          var canvas = document.createElement("canvas");
          document.body.appendChild(canvas);

          var ctx = canvas.getContext("2d");
          var canvasCopy = document.createElement("canvas");
          // adding it to the body

          document.body.appendChild(canvasCopy);

          var copyContext = canvasCopy.getContext("2d");

          img.onload = function()
          {
          var ratio = 1;

          // defining cause it wasnt
          var maxWidth = 188,
          maxHeight = 150;

          if(img.width > maxWidth)
          ratio = maxWidth / img.width;
          else if(img.height > maxHeight)
          ratio = maxHeight / img.height;

          canvasCopy.width = img.width;
          canvasCopy.height = img.height;
          copyContext.drawImage(img, 0, 0);

          canvas.width = img.width * ratio;
          canvas.height = img.height * ratio;
          // the line to change
          // ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
          // the method signature you are using is for slicing
          ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
          };

          // changed for example
          img.src = 'original.jpg';





          share|improve this answer


























          • I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

            – Telanor
            Mar 14 '10 at 21:11



















          3














          The problem with some of this solutions is that they access directly the pixel data and loop through it to perform the downsampling. Depending on the size of the image this can be very resource intensive, and it would be better to use the browser's internal algorithms.



          The drawImage() function is using a linear-interpolation, nearest-neighbor resampling method. That works well when you are not resizing down more than half the original size.



          If you loop to only resize max one half at a time, the results would be quite good, and much faster than accessing pixel data.



          This function downsample to half at a time until reaching the desired size:



            function resize_image( src, dst, type, quality ) {
          var tmp = new Image(),
          canvas, context, cW, cH;

          type = type || 'image/jpeg';
          quality = quality || 0.92;

          cW = src.naturalWidth;
          cH = src.naturalHeight;

          tmp.src = src.src;
          tmp.onload = function() {

          canvas = document.createElement( 'canvas' );

          cW /= 2;
          cH /= 2;

          if ( cW < src.width ) cW = src.width;
          if ( cH < src.height ) cH = src.height;

          canvas.width = cW;
          canvas.height = cH;
          context = canvas.getContext( '2d' );
          context.drawImage( tmp, 0, 0, cW, cH );

          dst.src = canvas.toDataURL( type, quality );

          if ( cW <= src.width || cH <= src.height )
          return;

          tmp.src = dst.src;
          }

          }
          // The images sent as parameters can be in the DOM or be image objects
          resize_image( $( '#original' )[0], $( '#smaller' )[0] );


          Credits to this post






          share|improve this answer

































            2














            So something interesting that I found a while ago while working with canvas that might be helpful:



            To resize the canvas control on its own, you need to use the height="" and width="" attributes (or canvas.width/canvas.height elements). If you use CSS to resize the canvas, it will actually stretch (i.e.: resize) the content of the canvas to fit the full canvas (rather than simply increasing or decreasing the area of the canvas.



            It'd be worth a shot to try drawing the image into a canvas control with the height and width attributes set to the size of the image and then using CSS to resize the canvas to the size you're looking for. Perhaps this would use a different resizing algorithm.



            It should also be noted that canvas has different effects in different browsers (and even different versions of different browsers). The algorithms and techniques used in the browsers is likely to change over time (especially with Firefox 4 and Chrome 6 coming out so soon, which will place heavy emphasis on canvas rendering performance).



            In addition, you may want to give SVG a shot, too, as it likely uses a different algorithm as well.



            Best of luck!






            share|improve this answer



















            • 1





              Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

              – Telanor
              Jul 6 '10 at 20:42











            • Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

              – Nestor
              Mar 21 '11 at 1:20



















            2














            I have a feeling the module I wrote will produce similar results to photoshop, as it preserves color data by averaging them, not applying an algorithm. It's kind of slow, but to me it is the best, because it preserves all the color data.



            https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js



            It doesn't take the nearest neighbor and drop other pixels, or sample a group and take a random average. It takes the exact proportion each source pixel should output into the destination pixel. The average pixel color in the source will be the average pixel color in the destination, which these other formulas, I think they will not be.



            an example of how to use is at the bottom of
            https://github.com/danschumann/limby-resize



            UPDATE OCT 2018: These days my example is more academic than anything else. Webgl is pretty much 100%, so you'd be better off resizing with that to produce similar results, but faster. PICA.js does this, I believe. –






            share|improve this answer

































              1














              I converted @syockit's answer as well as the step-down approach into a reusable Angular service for anyone who's interested: https://gist.github.com/fisch0920/37bac5e741eaec60e983



              I included both solutions because they both have their own pros / cons. The lanczos convolution approach is higher quality at the cost of being slower, whereas the step-wise downscaling approach produces reasonably antialiased results and is significantly faster.



              Example usage:



              angular.module('demo').controller('ExampleCtrl', function (imageService) {
              // EXAMPLE USAGE
              // NOTE: it's bad practice to access the DOM inside a controller,
              // but this is just to show the example usage.

              // resize by lanczos-sinc filter
              imageService.resize($('#myimg')[0], 256, 256)
              .then(function (resizedImage) {
              // do something with resized image
              })

              // resize by stepping down image size in increments of 2x
              imageService.resizeStep($('#myimg')[0], 256, 256)
              .then(function (resizedImage) {
              // do something with resized image
              })
              })





              share|improve this answer

































                1














                Fast and simple Javascript image resizer:



                https://github.com/calvintwr/Hermite-resize



                Use:



                h.resize({
                source: document.getElementById('image'), // any canvas or image elements, jQuery or native
                width: 400,
                height: 600,
                output: 'image', // [optional] `image` or `canvas`. If not entered output is same as input element.
                quality: 0.7, // [optional] applicable for `image` output only
                }, function(output) {
                //your callback
                });


                History



                This is really after many rounds of research, reading and trying.



                The resizer algorithm uses @ViliusL's Hermite script (Hermite resizer is really the fastest and gives reasonably good output). Extended with features you need.



                Forks 1 worker to do the resizing so that it doesn't freeze your browser when resizing, unlike all other JS resizers out there.






                share|improve this answer

































                  0














                  Thanks @syockit for an awesome answer. however, I had to reformat a little as follows to make it work. Perhaps due to DOM scanning issues:



                  $(document).ready(function () {

                  $('img').on("load", clickA);
                  function clickA() {
                  var img = this;
                  var canvas = document.createElement("canvas");
                  new thumbnailer(canvas, img, 50, 3);
                  document.body.appendChild(canvas);
                  }

                  function thumbnailer(elem, img, sx, lobes) {
                  this.canvas = elem;
                  elem.width = img.width;
                  elem.height = img.height;
                  elem.style.display = "none";
                  this.ctx = elem.getContext("2d");
                  this.ctx.drawImage(img, 0, 0);
                  this.img = img;
                  this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                  this.dest = {
                  width: sx,
                  height: Math.round(img.height * sx / img.width)
                  };
                  this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                  this.lanczos = lanczosCreate(lobes);
                  this.ratio = img.width / sx;
                  this.rcp_ratio = 2 / this.ratio;
                  this.range2 = Math.ceil(this.ratio * lobes / 2);
                  this.cacheLanc = {};
                  this.center = {};
                  this.icenter = {};
                  setTimeout(process1, 0, this, 0);
                  }

                  //returns a function that calculates lanczos weight
                  function lanczosCreate(lobes) {
                  return function (x) {
                  if (x > lobes)
                  return 0;
                  x *= Math.PI;
                  if (Math.abs(x) < 1e-16)
                  return 1
                  var xx = x / lobes;
                  return Math.sin(x) * Math.sin(xx) / x / xx;
                  }
                  }

                  process1 = function (self, u) {
                  self.center.x = (u + 0.5) * self.ratio;
                  self.icenter.x = Math.floor(self.center.x);
                  for (var v = 0; v < self.dest.height; v++) {
                  self.center.y = (v + 0.5) * self.ratio;
                  self.icenter.y = Math.floor(self.center.y);
                  var a, r, g, b;
                  a = r = g = b = 0;
                  for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                  if (i < 0 || i >= self.src.width)
                  continue;
                  var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                  if (!self.cacheLanc[f_x])
                  self.cacheLanc[f_x] = {};
                  for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                  if (j < 0 || j >= self.src.height)
                  continue;
                  var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                  if (self.cacheLanc[f_x][f_y] == undefined)
                  self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                  weight = self.cacheLanc[f_x][f_y];
                  if (weight > 0) {
                  var idx = (j * self.src.width + i) * 4;
                  a += weight;
                  r += weight * self.src.data[idx];
                  g += weight * self.src.data[idx + 1];
                  b += weight * self.src.data[idx + 2];
                  }
                  }
                  }
                  var idx = (v * self.dest.width + u) * 3;
                  self.dest.data[idx] = r / a;
                  self.dest.data[idx + 1] = g / a;
                  self.dest.data[idx + 2] = b / a;
                  }

                  if (++u < self.dest.width)
                  setTimeout(process1, 0, self, u);
                  else
                  setTimeout(process2, 0, self);
                  };

                  process2 = function (self) {
                  self.canvas.width = self.dest.width;
                  self.canvas.height = self.dest.height;
                  self.ctx.drawImage(self.img, 0, 0);
                  self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                  var idx, idx2;
                  for (var i = 0; i < self.dest.width; i++) {
                  for (var j = 0; j < self.dest.height; j++) {
                  idx = (j * self.dest.width + i) * 3;
                  idx2 = (j * self.dest.width + i) * 4;
                  self.src.data[idx2] = self.dest.data[idx];
                  self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                  self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                  }
                  }
                  self.ctx.putImageData(self.src, 0, 0);
                  self.canvas.style.display = "block";
                  }
                  });





                  share|improve this answer

































                    -1














                    I just ran a page of side by sides comparisons and unless something has changed recently, I could see no better downsizing (scaling) using canvas vs. simple css. I tested in FF6 Mac OSX 10.7. Still slightly soft vs. the original.



                    I did however stumble upon something that did make a huge difference and that was using image filters in browsers that support canvas. You can actually manipulate images much like you can in Photoshop with blur, sharpen, saturation, ripple, grayscale, etc.



                    I then found an awesome jQuery plug-in which makes application of these filters a snap:
                    http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234



                    I simply apply the sharpen filter right after resizing the image which should give you the desired effect. I didn't even have to use a canvas element.






                    share|improve this answer































                      -1














                      Looking for another great simple solution?



                      var img=document.createElement('img');
                      img.src=canvas.toDataURL();
                      $(img).css("background", backgroundColor);
                      $(img).width(settings.width);
                      $(img).height(settings.height);


                      This solution will use the resize algorith of browser! :)






                      share|improve this answer
























                      • The question is about downsampling the image, not just resizing it.

                        – Jesús Carrera
                        Aug 27 '14 at 13:49











                      • [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                        – ale500
                        Sep 3 '14 at 10:03










                      protected by NullPoiиteя Jun 23 '13 at 10:13



                      Thank you for your interest in this question.
                      Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                      Would you like to answer one of these unanswered questions instead?














                      18 Answers
                      18






                      active

                      oldest

                      votes








                      18 Answers
                      18






                      active

                      oldest

                      votes









                      active

                      oldest

                      votes






                      active

                      oldest

                      votes









                      381














                      So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:



                      // returns a function that calculates lanczos weight
                      function lanczosCreate(lobes) {
                      return function(x) {
                      if (x > lobes)
                      return 0;
                      x *= Math.PI;
                      if (Math.abs(x) < 1e-16)
                      return 1;
                      var xx = x / lobes;
                      return Math.sin(x) * Math.sin(xx) / x / xx;
                      };
                      }

                      // elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
                      function thumbnailer(elem, img, sx, lobes) {
                      this.canvas = elem;
                      elem.width = img.width;
                      elem.height = img.height;
                      elem.style.display = "none";
                      this.ctx = elem.getContext("2d");
                      this.ctx.drawImage(img, 0, 0);
                      this.img = img;
                      this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                      this.dest = {
                      width : sx,
                      height : Math.round(img.height * sx / img.width),
                      };
                      this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                      this.lanczos = lanczosCreate(lobes);
                      this.ratio = img.width / sx;
                      this.rcp_ratio = 2 / this.ratio;
                      this.range2 = Math.ceil(this.ratio * lobes / 2);
                      this.cacheLanc = {};
                      this.center = {};
                      this.icenter = {};
                      setTimeout(this.process1, 0, this, 0);
                      }

                      thumbnailer.prototype.process1 = function(self, u) {
                      self.center.x = (u + 0.5) * self.ratio;
                      self.icenter.x = Math.floor(self.center.x);
                      for (var v = 0; v < self.dest.height; v++) {
                      self.center.y = (v + 0.5) * self.ratio;
                      self.icenter.y = Math.floor(self.center.y);
                      var a, r, g, b;
                      a = r = g = b = 0;
                      for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                      if (i < 0 || i >= self.src.width)
                      continue;
                      var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                      if (!self.cacheLanc[f_x])
                      self.cacheLanc[f_x] = {};
                      for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                      if (j < 0 || j >= self.src.height)
                      continue;
                      var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                      if (self.cacheLanc[f_x][f_y] == undefined)
                      self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
                      + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                      weight = self.cacheLanc[f_x][f_y];
                      if (weight > 0) {
                      var idx = (j * self.src.width + i) * 4;
                      a += weight;
                      r += weight * self.src.data[idx];
                      g += weight * self.src.data[idx + 1];
                      b += weight * self.src.data[idx + 2];
                      }
                      }
                      }
                      var idx = (v * self.dest.width + u) * 3;
                      self.dest.data[idx] = r / a;
                      self.dest.data[idx + 1] = g / a;
                      self.dest.data[idx + 2] = b / a;
                      }

                      if (++u < self.dest.width)
                      setTimeout(self.process1, 0, self, u);
                      else
                      setTimeout(self.process2, 0, self);
                      };
                      thumbnailer.prototype.process2 = function(self) {
                      self.canvas.width = self.dest.width;
                      self.canvas.height = self.dest.height;
                      self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
                      self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                      var idx, idx2;
                      for (var i = 0; i < self.dest.width; i++) {
                      for (var j = 0; j < self.dest.height; j++) {
                      idx = (j * self.dest.width + i) * 3;
                      idx2 = (j * self.dest.width + i) * 4;
                      self.src.data[idx2] = self.dest.data[idx];
                      self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                      self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                      }
                      }
                      self.ctx.putImageData(self.src, 0, 0);
                      self.canvas.style.display = "block";
                      };


                      ...with which you can produce results like these!



                      img717.imageshack.us/img717/8910/lanczos358.png



                      so anyway, here is a 'fixed' version of your example:



                      img.onload = function() {
                      var canvas = document.createElement("canvas");
                      new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
                      // but feel free to raise it up to 8. Your client will appreciate
                      // that the program makes full use of his machine.
                      document.body.appendChild(canvas);
                      };


                      Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!



                      Umm, where's my sarcasm tag?



                      (since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)



                      actually due to limitation of javascript, multi-core is not supported.






                      share|improve this answer





















                      • 2





                        I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                        – Telanor
                        Jul 11 '10 at 22:52






                      • 3





                        Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                        – syockit
                        Jul 16 '10 at 16:33






                      • 5





                        You are awesome and deserve tons of awesomeage.

                        – Rocklan
                        Feb 2 '13 at 4:05






                      • 5





                        This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                        – mpen
                        Feb 16 '13 at 20:25






                      • 2





                        How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                        – Blindman67
                        Jan 3 '16 at 16:15
















                      381














                      So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:



                      // returns a function that calculates lanczos weight
                      function lanczosCreate(lobes) {
                      return function(x) {
                      if (x > lobes)
                      return 0;
                      x *= Math.PI;
                      if (Math.abs(x) < 1e-16)
                      return 1;
                      var xx = x / lobes;
                      return Math.sin(x) * Math.sin(xx) / x / xx;
                      };
                      }

                      // elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
                      function thumbnailer(elem, img, sx, lobes) {
                      this.canvas = elem;
                      elem.width = img.width;
                      elem.height = img.height;
                      elem.style.display = "none";
                      this.ctx = elem.getContext("2d");
                      this.ctx.drawImage(img, 0, 0);
                      this.img = img;
                      this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                      this.dest = {
                      width : sx,
                      height : Math.round(img.height * sx / img.width),
                      };
                      this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                      this.lanczos = lanczosCreate(lobes);
                      this.ratio = img.width / sx;
                      this.rcp_ratio = 2 / this.ratio;
                      this.range2 = Math.ceil(this.ratio * lobes / 2);
                      this.cacheLanc = {};
                      this.center = {};
                      this.icenter = {};
                      setTimeout(this.process1, 0, this, 0);
                      }

                      thumbnailer.prototype.process1 = function(self, u) {
                      self.center.x = (u + 0.5) * self.ratio;
                      self.icenter.x = Math.floor(self.center.x);
                      for (var v = 0; v < self.dest.height; v++) {
                      self.center.y = (v + 0.5) * self.ratio;
                      self.icenter.y = Math.floor(self.center.y);
                      var a, r, g, b;
                      a = r = g = b = 0;
                      for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                      if (i < 0 || i >= self.src.width)
                      continue;
                      var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                      if (!self.cacheLanc[f_x])
                      self.cacheLanc[f_x] = {};
                      for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                      if (j < 0 || j >= self.src.height)
                      continue;
                      var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                      if (self.cacheLanc[f_x][f_y] == undefined)
                      self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
                      + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                      weight = self.cacheLanc[f_x][f_y];
                      if (weight > 0) {
                      var idx = (j * self.src.width + i) * 4;
                      a += weight;
                      r += weight * self.src.data[idx];
                      g += weight * self.src.data[idx + 1];
                      b += weight * self.src.data[idx + 2];
                      }
                      }
                      }
                      var idx = (v * self.dest.width + u) * 3;
                      self.dest.data[idx] = r / a;
                      self.dest.data[idx + 1] = g / a;
                      self.dest.data[idx + 2] = b / a;
                      }

                      if (++u < self.dest.width)
                      setTimeout(self.process1, 0, self, u);
                      else
                      setTimeout(self.process2, 0, self);
                      };
                      thumbnailer.prototype.process2 = function(self) {
                      self.canvas.width = self.dest.width;
                      self.canvas.height = self.dest.height;
                      self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
                      self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                      var idx, idx2;
                      for (var i = 0; i < self.dest.width; i++) {
                      for (var j = 0; j < self.dest.height; j++) {
                      idx = (j * self.dest.width + i) * 3;
                      idx2 = (j * self.dest.width + i) * 4;
                      self.src.data[idx2] = self.dest.data[idx];
                      self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                      self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                      }
                      }
                      self.ctx.putImageData(self.src, 0, 0);
                      self.canvas.style.display = "block";
                      };


                      ...with which you can produce results like these!



                      img717.imageshack.us/img717/8910/lanczos358.png



                      so anyway, here is a 'fixed' version of your example:



                      img.onload = function() {
                      var canvas = document.createElement("canvas");
                      new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
                      // but feel free to raise it up to 8. Your client will appreciate
                      // that the program makes full use of his machine.
                      document.body.appendChild(canvas);
                      };


                      Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!



                      Umm, where's my sarcasm tag?



                      (since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)



                      actually due to limitation of javascript, multi-core is not supported.






                      share|improve this answer





















                      • 2





                        I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                        – Telanor
                        Jul 11 '10 at 22:52






                      • 3





                        Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                        – syockit
                        Jul 16 '10 at 16:33






                      • 5





                        You are awesome and deserve tons of awesomeage.

                        – Rocklan
                        Feb 2 '13 at 4:05






                      • 5





                        This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                        – mpen
                        Feb 16 '13 at 20:25






                      • 2





                        How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                        – Blindman67
                        Jan 3 '16 at 16:15














                      381












                      381








                      381







                      So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:



                      // returns a function that calculates lanczos weight
                      function lanczosCreate(lobes) {
                      return function(x) {
                      if (x > lobes)
                      return 0;
                      x *= Math.PI;
                      if (Math.abs(x) < 1e-16)
                      return 1;
                      var xx = x / lobes;
                      return Math.sin(x) * Math.sin(xx) / x / xx;
                      };
                      }

                      // elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
                      function thumbnailer(elem, img, sx, lobes) {
                      this.canvas = elem;
                      elem.width = img.width;
                      elem.height = img.height;
                      elem.style.display = "none";
                      this.ctx = elem.getContext("2d");
                      this.ctx.drawImage(img, 0, 0);
                      this.img = img;
                      this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                      this.dest = {
                      width : sx,
                      height : Math.round(img.height * sx / img.width),
                      };
                      this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                      this.lanczos = lanczosCreate(lobes);
                      this.ratio = img.width / sx;
                      this.rcp_ratio = 2 / this.ratio;
                      this.range2 = Math.ceil(this.ratio * lobes / 2);
                      this.cacheLanc = {};
                      this.center = {};
                      this.icenter = {};
                      setTimeout(this.process1, 0, this, 0);
                      }

                      thumbnailer.prototype.process1 = function(self, u) {
                      self.center.x = (u + 0.5) * self.ratio;
                      self.icenter.x = Math.floor(self.center.x);
                      for (var v = 0; v < self.dest.height; v++) {
                      self.center.y = (v + 0.5) * self.ratio;
                      self.icenter.y = Math.floor(self.center.y);
                      var a, r, g, b;
                      a = r = g = b = 0;
                      for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                      if (i < 0 || i >= self.src.width)
                      continue;
                      var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                      if (!self.cacheLanc[f_x])
                      self.cacheLanc[f_x] = {};
                      for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                      if (j < 0 || j >= self.src.height)
                      continue;
                      var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                      if (self.cacheLanc[f_x][f_y] == undefined)
                      self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
                      + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                      weight = self.cacheLanc[f_x][f_y];
                      if (weight > 0) {
                      var idx = (j * self.src.width + i) * 4;
                      a += weight;
                      r += weight * self.src.data[idx];
                      g += weight * self.src.data[idx + 1];
                      b += weight * self.src.data[idx + 2];
                      }
                      }
                      }
                      var idx = (v * self.dest.width + u) * 3;
                      self.dest.data[idx] = r / a;
                      self.dest.data[idx + 1] = g / a;
                      self.dest.data[idx + 2] = b / a;
                      }

                      if (++u < self.dest.width)
                      setTimeout(self.process1, 0, self, u);
                      else
                      setTimeout(self.process2, 0, self);
                      };
                      thumbnailer.prototype.process2 = function(self) {
                      self.canvas.width = self.dest.width;
                      self.canvas.height = self.dest.height;
                      self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
                      self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                      var idx, idx2;
                      for (var i = 0; i < self.dest.width; i++) {
                      for (var j = 0; j < self.dest.height; j++) {
                      idx = (j * self.dest.width + i) * 3;
                      idx2 = (j * self.dest.width + i) * 4;
                      self.src.data[idx2] = self.dest.data[idx];
                      self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                      self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                      }
                      }
                      self.ctx.putImageData(self.src, 0, 0);
                      self.canvas.style.display = "block";
                      };


                      ...with which you can produce results like these!



                      img717.imageshack.us/img717/8910/lanczos358.png



                      so anyway, here is a 'fixed' version of your example:



                      img.onload = function() {
                      var canvas = document.createElement("canvas");
                      new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
                      // but feel free to raise it up to 8. Your client will appreciate
                      // that the program makes full use of his machine.
                      document.body.appendChild(canvas);
                      };


                      Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!



                      Umm, where's my sarcasm tag?



                      (since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)



                      actually due to limitation of javascript, multi-core is not supported.






                      share|improve this answer















                      So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:



                      // returns a function that calculates lanczos weight
                      function lanczosCreate(lobes) {
                      return function(x) {
                      if (x > lobes)
                      return 0;
                      x *= Math.PI;
                      if (Math.abs(x) < 1e-16)
                      return 1;
                      var xx = x / lobes;
                      return Math.sin(x) * Math.sin(xx) / x / xx;
                      };
                      }

                      // elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
                      function thumbnailer(elem, img, sx, lobes) {
                      this.canvas = elem;
                      elem.width = img.width;
                      elem.height = img.height;
                      elem.style.display = "none";
                      this.ctx = elem.getContext("2d");
                      this.ctx.drawImage(img, 0, 0);
                      this.img = img;
                      this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                      this.dest = {
                      width : sx,
                      height : Math.round(img.height * sx / img.width),
                      };
                      this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                      this.lanczos = lanczosCreate(lobes);
                      this.ratio = img.width / sx;
                      this.rcp_ratio = 2 / this.ratio;
                      this.range2 = Math.ceil(this.ratio * lobes / 2);
                      this.cacheLanc = {};
                      this.center = {};
                      this.icenter = {};
                      setTimeout(this.process1, 0, this, 0);
                      }

                      thumbnailer.prototype.process1 = function(self, u) {
                      self.center.x = (u + 0.5) * self.ratio;
                      self.icenter.x = Math.floor(self.center.x);
                      for (var v = 0; v < self.dest.height; v++) {
                      self.center.y = (v + 0.5) * self.ratio;
                      self.icenter.y = Math.floor(self.center.y);
                      var a, r, g, b;
                      a = r = g = b = 0;
                      for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                      if (i < 0 || i >= self.src.width)
                      continue;
                      var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                      if (!self.cacheLanc[f_x])
                      self.cacheLanc[f_x] = {};
                      for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                      if (j < 0 || j >= self.src.height)
                      continue;
                      var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                      if (self.cacheLanc[f_x][f_y] == undefined)
                      self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
                      + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                      weight = self.cacheLanc[f_x][f_y];
                      if (weight > 0) {
                      var idx = (j * self.src.width + i) * 4;
                      a += weight;
                      r += weight * self.src.data[idx];
                      g += weight * self.src.data[idx + 1];
                      b += weight * self.src.data[idx + 2];
                      }
                      }
                      }
                      var idx = (v * self.dest.width + u) * 3;
                      self.dest.data[idx] = r / a;
                      self.dest.data[idx + 1] = g / a;
                      self.dest.data[idx + 2] = b / a;
                      }

                      if (++u < self.dest.width)
                      setTimeout(self.process1, 0, self, u);
                      else
                      setTimeout(self.process2, 0, self);
                      };
                      thumbnailer.prototype.process2 = function(self) {
                      self.canvas.width = self.dest.width;
                      self.canvas.height = self.dest.height;
                      self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
                      self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                      var idx, idx2;
                      for (var i = 0; i < self.dest.width; i++) {
                      for (var j = 0; j < self.dest.height; j++) {
                      idx = (j * self.dest.width + i) * 3;
                      idx2 = (j * self.dest.width + i) * 4;
                      self.src.data[idx2] = self.dest.data[idx];
                      self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                      self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                      }
                      }
                      self.ctx.putImageData(self.src, 0, 0);
                      self.canvas.style.display = "block";
                      };


                      ...with which you can produce results like these!



                      img717.imageshack.us/img717/8910/lanczos358.png



                      so anyway, here is a 'fixed' version of your example:



                      img.onload = function() {
                      var canvas = document.createElement("canvas");
                      new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
                      // but feel free to raise it up to 8. Your client will appreciate
                      // that the program makes full use of his machine.
                      document.body.appendChild(canvas);
                      };


                      Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!



                      Umm, where's my sarcasm tag?



                      (since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)



                      actually due to limitation of javascript, multi-core is not supported.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Mar 17 '15 at 15:43









                      Mikk

                      1125




                      1125










                      answered Jul 11 '10 at 14:57









                      syockitsyockit

                      5,18411830




                      5,18411830








                      • 2





                        I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                        – Telanor
                        Jul 11 '10 at 22:52






                      • 3





                        Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                        – syockit
                        Jul 16 '10 at 16:33






                      • 5





                        You are awesome and deserve tons of awesomeage.

                        – Rocklan
                        Feb 2 '13 at 4:05






                      • 5





                        This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                        – mpen
                        Feb 16 '13 at 20:25






                      • 2





                        How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                        – Blindman67
                        Jan 3 '16 at 16:15














                      • 2





                        I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                        – Telanor
                        Jul 11 '10 at 22:52






                      • 3





                        Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                        – syockit
                        Jul 16 '10 at 16:33






                      • 5





                        You are awesome and deserve tons of awesomeage.

                        – Rocklan
                        Feb 2 '13 at 4:05






                      • 5





                        This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                        – mpen
                        Feb 16 '13 at 20:25






                      • 2





                        How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                        – Blindman67
                        Jan 3 '16 at 16:15








                      2




                      2





                      I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                      – Telanor
                      Jul 11 '10 at 22:52





                      I had actually tried implementing it myself, doing as you did, copying code from an open source image editor. Since I wasn't able to find any solid documentation on the algorithm I had a hard time optimizing it. In the end, mine was kind of slow (took a few seconds to resize the image). When I get the chance, I'll try yours out and see if its any faster. And I think webworkers make multi-core javascript possible now. I was going to try using them to speed it up, but I was having trouble figuring out how to make this into a multithreaded algorithm

                      – Telanor
                      Jul 11 '10 at 22:52




                      3




                      3





                      Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                      – syockit
                      Jul 16 '10 at 16:33





                      Sorry, forgot that! I've edited the reply. It's not going to be fast anyways, bicubic should be faster. Not to mention the algorithm I used is not the usual 2-way resizing (which is line by line, horizontal then vertical), so it's a looot slower.

                      – syockit
                      Jul 16 '10 at 16:33




                      5




                      5





                      You are awesome and deserve tons of awesomeage.

                      – Rocklan
                      Feb 2 '13 at 4:05





                      You are awesome and deserve tons of awesomeage.

                      – Rocklan
                      Feb 2 '13 at 4:05




                      5




                      5





                      This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                      – mpen
                      Feb 16 '13 at 20:25





                      This produces decent results, but takes 7.4 seconds for a 1.8 MP image in the latest version of Chrome...

                      – mpen
                      Feb 16 '13 at 20:25




                      2




                      2





                      How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                      – Blindman67
                      Jan 3 '16 at 16:15





                      How methods like this manage to such high score?? The solution shown completely fails to account for the logarithmic scale used to store colour information. A RGB of 127,127,127 is one quarter the brightness of 255, 255, 255 not half. The down sampling in the solution results in a darkened image. Shame this is closed as there is a very simple and quick method to down size that produces even better results than the Photoshop (OP must have had the preferences set wrong) sample given

                      – Blindman67
                      Jan 3 '16 at 16:15













                      36














                      Fast image resize/resample algorithm using Hermite filter with JavaScript. Support transparency, gives good quality. Preview:


                      enter image description here



                      Update: version 2.0 added on GitHub (faster, web workers + transferable objects). Finally i got it working!



                      Git: https://github.com/viliusle/Hermite-resize

                      Demo: http://viliusle.github.io/miniPaint/



                      /**
                      * Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
                      *
                      * @param {HtmlElement} canvas
                      * @param {int} width
                      * @param {int} height
                      * @param {boolean} resize_canvas if true, canvas will be resized. Optional.
                      */
                      function resample_single(canvas, width, height, resize_canvas) {
                      var width_source = canvas.width;
                      var height_source = canvas.height;
                      width = Math.round(width);
                      height = Math.round(height);

                      var ratio_w = width_source / width;
                      var ratio_h = height_source / height;
                      var ratio_w_half = Math.ceil(ratio_w / 2);
                      var ratio_h_half = Math.ceil(ratio_h / 2);

                      var ctx = canvas.getContext("2d");
                      var img = ctx.getImageData(0, 0, width_source, height_source);
                      var img2 = ctx.createImageData(width, height);
                      var data = img.data;
                      var data2 = img2.data;

                      for (var j = 0; j < height; j++) {
                      for (var i = 0; i < width; i++) {
                      var x2 = (i + j * width) * 4;
                      var weight = 0;
                      var weights = 0;
                      var weights_alpha = 0;
                      var gx_r = 0;
                      var gx_g = 0;
                      var gx_b = 0;
                      var gx_a = 0;
                      var center_y = (j + 0.5) * ratio_h;
                      var yy_start = Math.floor(j * ratio_h);
                      var yy_stop = Math.ceil((j + 1) * ratio_h);
                      for (var yy = yy_start; yy < yy_stop; yy++) {
                      var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
                      var center_x = (i + 0.5) * ratio_w;
                      var w0 = dy * dy; //pre-calc part of w
                      var xx_start = Math.floor(i * ratio_w);
                      var xx_stop = Math.ceil((i + 1) * ratio_w);
                      for (var xx = xx_start; xx < xx_stop; xx++) {
                      var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
                      var w = Math.sqrt(w0 + dx * dx);
                      if (w >= 1) {
                      //pixel too far
                      continue;
                      }
                      //hermite filter
                      weight = 2 * w * w * w - 3 * w * w + 1;
                      var pos_x = 4 * (xx + yy * width_source);
                      //alpha
                      gx_a += weight * data[pos_x + 3];
                      weights_alpha += weight;
                      //colors
                      if (data[pos_x + 3] < 255)
                      weight = weight * data[pos_x + 3] / 250;
                      gx_r += weight * data[pos_x];
                      gx_g += weight * data[pos_x + 1];
                      gx_b += weight * data[pos_x + 2];
                      weights += weight;
                      }
                      }
                      data2[x2] = gx_r / weights;
                      data2[x2 + 1] = gx_g / weights;
                      data2[x2 + 2] = gx_b / weights;
                      data2[x2 + 3] = gx_a / weights_alpha;
                      }
                      }
                      //clear and resize canvas
                      if (resize_canvas === true) {
                      canvas.width = width;
                      canvas.height = height;
                      } else {
                      ctx.clearRect(0, 0, width_source, height_source);
                      }

                      //draw
                      ctx.putImageData(img2, 0, 0);
                      }





                      share|improve this answer


























                      • Maybe you can include links to your miniPaint demo and Github repo?

                        – syockit
                        Sep 11 '13 at 13:45






                      • 1





                        Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                        – syockit
                        Sep 11 '13 at 13:50











                      • added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                        – ViliusL
                        Sep 11 '13 at 18:47











                      • Huge difference and decent performance. Thank you very much! before and after

                        – KevBurnsJr
                        Sep 12 '13 at 6:56








                      • 2





                        @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                        – syockit
                        Nov 16 '13 at 9:06
















                      36














                      Fast image resize/resample algorithm using Hermite filter with JavaScript. Support transparency, gives good quality. Preview:


                      enter image description here



                      Update: version 2.0 added on GitHub (faster, web workers + transferable objects). Finally i got it working!



                      Git: https://github.com/viliusle/Hermite-resize

                      Demo: http://viliusle.github.io/miniPaint/



                      /**
                      * Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
                      *
                      * @param {HtmlElement} canvas
                      * @param {int} width
                      * @param {int} height
                      * @param {boolean} resize_canvas if true, canvas will be resized. Optional.
                      */
                      function resample_single(canvas, width, height, resize_canvas) {
                      var width_source = canvas.width;
                      var height_source = canvas.height;
                      width = Math.round(width);
                      height = Math.round(height);

                      var ratio_w = width_source / width;
                      var ratio_h = height_source / height;
                      var ratio_w_half = Math.ceil(ratio_w / 2);
                      var ratio_h_half = Math.ceil(ratio_h / 2);

                      var ctx = canvas.getContext("2d");
                      var img = ctx.getImageData(0, 0, width_source, height_source);
                      var img2 = ctx.createImageData(width, height);
                      var data = img.data;
                      var data2 = img2.data;

                      for (var j = 0; j < height; j++) {
                      for (var i = 0; i < width; i++) {
                      var x2 = (i + j * width) * 4;
                      var weight = 0;
                      var weights = 0;
                      var weights_alpha = 0;
                      var gx_r = 0;
                      var gx_g = 0;
                      var gx_b = 0;
                      var gx_a = 0;
                      var center_y = (j + 0.5) * ratio_h;
                      var yy_start = Math.floor(j * ratio_h);
                      var yy_stop = Math.ceil((j + 1) * ratio_h);
                      for (var yy = yy_start; yy < yy_stop; yy++) {
                      var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
                      var center_x = (i + 0.5) * ratio_w;
                      var w0 = dy * dy; //pre-calc part of w
                      var xx_start = Math.floor(i * ratio_w);
                      var xx_stop = Math.ceil((i + 1) * ratio_w);
                      for (var xx = xx_start; xx < xx_stop; xx++) {
                      var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
                      var w = Math.sqrt(w0 + dx * dx);
                      if (w >= 1) {
                      //pixel too far
                      continue;
                      }
                      //hermite filter
                      weight = 2 * w * w * w - 3 * w * w + 1;
                      var pos_x = 4 * (xx + yy * width_source);
                      //alpha
                      gx_a += weight * data[pos_x + 3];
                      weights_alpha += weight;
                      //colors
                      if (data[pos_x + 3] < 255)
                      weight = weight * data[pos_x + 3] / 250;
                      gx_r += weight * data[pos_x];
                      gx_g += weight * data[pos_x + 1];
                      gx_b += weight * data[pos_x + 2];
                      weights += weight;
                      }
                      }
                      data2[x2] = gx_r / weights;
                      data2[x2 + 1] = gx_g / weights;
                      data2[x2 + 2] = gx_b / weights;
                      data2[x2 + 3] = gx_a / weights_alpha;
                      }
                      }
                      //clear and resize canvas
                      if (resize_canvas === true) {
                      canvas.width = width;
                      canvas.height = height;
                      } else {
                      ctx.clearRect(0, 0, width_source, height_source);
                      }

                      //draw
                      ctx.putImageData(img2, 0, 0);
                      }





                      share|improve this answer


























                      • Maybe you can include links to your miniPaint demo and Github repo?

                        – syockit
                        Sep 11 '13 at 13:45






                      • 1





                        Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                        – syockit
                        Sep 11 '13 at 13:50











                      • added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                        – ViliusL
                        Sep 11 '13 at 18:47











                      • Huge difference and decent performance. Thank you very much! before and after

                        – KevBurnsJr
                        Sep 12 '13 at 6:56








                      • 2





                        @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                        – syockit
                        Nov 16 '13 at 9:06














                      36












                      36








                      36







                      Fast image resize/resample algorithm using Hermite filter with JavaScript. Support transparency, gives good quality. Preview:


                      enter image description here



                      Update: version 2.0 added on GitHub (faster, web workers + transferable objects). Finally i got it working!



                      Git: https://github.com/viliusle/Hermite-resize

                      Demo: http://viliusle.github.io/miniPaint/



                      /**
                      * Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
                      *
                      * @param {HtmlElement} canvas
                      * @param {int} width
                      * @param {int} height
                      * @param {boolean} resize_canvas if true, canvas will be resized. Optional.
                      */
                      function resample_single(canvas, width, height, resize_canvas) {
                      var width_source = canvas.width;
                      var height_source = canvas.height;
                      width = Math.round(width);
                      height = Math.round(height);

                      var ratio_w = width_source / width;
                      var ratio_h = height_source / height;
                      var ratio_w_half = Math.ceil(ratio_w / 2);
                      var ratio_h_half = Math.ceil(ratio_h / 2);

                      var ctx = canvas.getContext("2d");
                      var img = ctx.getImageData(0, 0, width_source, height_source);
                      var img2 = ctx.createImageData(width, height);
                      var data = img.data;
                      var data2 = img2.data;

                      for (var j = 0; j < height; j++) {
                      for (var i = 0; i < width; i++) {
                      var x2 = (i + j * width) * 4;
                      var weight = 0;
                      var weights = 0;
                      var weights_alpha = 0;
                      var gx_r = 0;
                      var gx_g = 0;
                      var gx_b = 0;
                      var gx_a = 0;
                      var center_y = (j + 0.5) * ratio_h;
                      var yy_start = Math.floor(j * ratio_h);
                      var yy_stop = Math.ceil((j + 1) * ratio_h);
                      for (var yy = yy_start; yy < yy_stop; yy++) {
                      var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
                      var center_x = (i + 0.5) * ratio_w;
                      var w0 = dy * dy; //pre-calc part of w
                      var xx_start = Math.floor(i * ratio_w);
                      var xx_stop = Math.ceil((i + 1) * ratio_w);
                      for (var xx = xx_start; xx < xx_stop; xx++) {
                      var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
                      var w = Math.sqrt(w0 + dx * dx);
                      if (w >= 1) {
                      //pixel too far
                      continue;
                      }
                      //hermite filter
                      weight = 2 * w * w * w - 3 * w * w + 1;
                      var pos_x = 4 * (xx + yy * width_source);
                      //alpha
                      gx_a += weight * data[pos_x + 3];
                      weights_alpha += weight;
                      //colors
                      if (data[pos_x + 3] < 255)
                      weight = weight * data[pos_x + 3] / 250;
                      gx_r += weight * data[pos_x];
                      gx_g += weight * data[pos_x + 1];
                      gx_b += weight * data[pos_x + 2];
                      weights += weight;
                      }
                      }
                      data2[x2] = gx_r / weights;
                      data2[x2 + 1] = gx_g / weights;
                      data2[x2 + 2] = gx_b / weights;
                      data2[x2 + 3] = gx_a / weights_alpha;
                      }
                      }
                      //clear and resize canvas
                      if (resize_canvas === true) {
                      canvas.width = width;
                      canvas.height = height;
                      } else {
                      ctx.clearRect(0, 0, width_source, height_source);
                      }

                      //draw
                      ctx.putImageData(img2, 0, 0);
                      }





                      share|improve this answer















                      Fast image resize/resample algorithm using Hermite filter with JavaScript. Support transparency, gives good quality. Preview:


                      enter image description here



                      Update: version 2.0 added on GitHub (faster, web workers + transferable objects). Finally i got it working!



                      Git: https://github.com/viliusle/Hermite-resize

                      Demo: http://viliusle.github.io/miniPaint/



                      /**
                      * Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
                      *
                      * @param {HtmlElement} canvas
                      * @param {int} width
                      * @param {int} height
                      * @param {boolean} resize_canvas if true, canvas will be resized. Optional.
                      */
                      function resample_single(canvas, width, height, resize_canvas) {
                      var width_source = canvas.width;
                      var height_source = canvas.height;
                      width = Math.round(width);
                      height = Math.round(height);

                      var ratio_w = width_source / width;
                      var ratio_h = height_source / height;
                      var ratio_w_half = Math.ceil(ratio_w / 2);
                      var ratio_h_half = Math.ceil(ratio_h / 2);

                      var ctx = canvas.getContext("2d");
                      var img = ctx.getImageData(0, 0, width_source, height_source);
                      var img2 = ctx.createImageData(width, height);
                      var data = img.data;
                      var data2 = img2.data;

                      for (var j = 0; j < height; j++) {
                      for (var i = 0; i < width; i++) {
                      var x2 = (i + j * width) * 4;
                      var weight = 0;
                      var weights = 0;
                      var weights_alpha = 0;
                      var gx_r = 0;
                      var gx_g = 0;
                      var gx_b = 0;
                      var gx_a = 0;
                      var center_y = (j + 0.5) * ratio_h;
                      var yy_start = Math.floor(j * ratio_h);
                      var yy_stop = Math.ceil((j + 1) * ratio_h);
                      for (var yy = yy_start; yy < yy_stop; yy++) {
                      var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
                      var center_x = (i + 0.5) * ratio_w;
                      var w0 = dy * dy; //pre-calc part of w
                      var xx_start = Math.floor(i * ratio_w);
                      var xx_stop = Math.ceil((i + 1) * ratio_w);
                      for (var xx = xx_start; xx < xx_stop; xx++) {
                      var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
                      var w = Math.sqrt(w0 + dx * dx);
                      if (w >= 1) {
                      //pixel too far
                      continue;
                      }
                      //hermite filter
                      weight = 2 * w * w * w - 3 * w * w + 1;
                      var pos_x = 4 * (xx + yy * width_source);
                      //alpha
                      gx_a += weight * data[pos_x + 3];
                      weights_alpha += weight;
                      //colors
                      if (data[pos_x + 3] < 255)
                      weight = weight * data[pos_x + 3] / 250;
                      gx_r += weight * data[pos_x];
                      gx_g += weight * data[pos_x + 1];
                      gx_b += weight * data[pos_x + 2];
                      weights += weight;
                      }
                      }
                      data2[x2] = gx_r / weights;
                      data2[x2 + 1] = gx_g / weights;
                      data2[x2 + 2] = gx_b / weights;
                      data2[x2 + 3] = gx_a / weights_alpha;
                      }
                      }
                      //clear and resize canvas
                      if (resize_canvas === true) {
                      canvas.width = width;
                      canvas.height = height;
                      } else {
                      ctx.clearRect(0, 0, width_source, height_source);
                      }

                      //draw
                      ctx.putImageData(img2, 0, 0);
                      }






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Sep 12 '17 at 11:50









                      Adrian Mitev

                      3,83132451




                      3,83132451










                      answered Aug 19 '13 at 18:33









                      ViliusLViliusL

                      3,2481525




                      3,2481525













                      • Maybe you can include links to your miniPaint demo and Github repo?

                        – syockit
                        Sep 11 '13 at 13:45






                      • 1





                        Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                        – syockit
                        Sep 11 '13 at 13:50











                      • added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                        – ViliusL
                        Sep 11 '13 at 18:47











                      • Huge difference and decent performance. Thank you very much! before and after

                        – KevBurnsJr
                        Sep 12 '13 at 6:56








                      • 2





                        @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                        – syockit
                        Nov 16 '13 at 9:06



















                      • Maybe you can include links to your miniPaint demo and Github repo?

                        – syockit
                        Sep 11 '13 at 13:45






                      • 1





                        Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                        – syockit
                        Sep 11 '13 at 13:50











                      • added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                        – ViliusL
                        Sep 11 '13 at 18:47











                      • Huge difference and decent performance. Thank you very much! before and after

                        – KevBurnsJr
                        Sep 12 '13 at 6:56








                      • 2





                        @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                        – syockit
                        Nov 16 '13 at 9:06

















                      Maybe you can include links to your miniPaint demo and Github repo?

                      – syockit
                      Sep 11 '13 at 13:45





                      Maybe you can include links to your miniPaint demo and Github repo?

                      – syockit
                      Sep 11 '13 at 13:45




                      1




                      1





                      Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                      – syockit
                      Sep 11 '13 at 13:50





                      Will you also share the webworkers version as well? Probably due to setup overhead, it's slower for small images, but it could be useful for larger source images.

                      – syockit
                      Sep 11 '13 at 13:50













                      added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                      – ViliusL
                      Sep 11 '13 at 18:47





                      added demo, git links, also multi-core version. Btw i did not spend too much time on optimizing multicore version... Single version i believe is optimized well.

                      – ViliusL
                      Sep 11 '13 at 18:47













                      Huge difference and decent performance. Thank you very much! before and after

                      – KevBurnsJr
                      Sep 12 '13 at 6:56







                      Huge difference and decent performance. Thank you very much! before and after

                      – KevBurnsJr
                      Sep 12 '13 at 6:56






                      2




                      2





                      @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                      – syockit
                      Nov 16 '13 at 9:06





                      @ViliusL Ah now I remembered why web workers didn't work so well. They didn't have shared memory before, and still doesn't have it now! Maybe someday when they manage to sort it out, your code will come to use (that, or maybe people use PNaCl instead)

                      – syockit
                      Nov 16 '13 at 9:06











                      23














                      Try pica - that's a highly optimized resizer with selectable algorythms. See demo.



                      For example, original image from first post is resized in 120ms with Lanczos filter and 3px window or 60ms with Box filter and 0.5px window. For huge 17mb image 5000x3000px resize takes ~1s on desktop and 3s on mobile.



                      All resize principles were described very well in this thread, and pica does not add rocket science. But it's optimized very well for modern JIT-s, and is ready to use out of box (via npm or bower). Also, it use webworkers when available to avoid interface freezes.



                      I also plan to add unsharp mask support soon, because it's very useful after downscale.






                      share|improve this answer




























                        23














                        Try pica - that's a highly optimized resizer with selectable algorythms. See demo.



                        For example, original image from first post is resized in 120ms with Lanczos filter and 3px window or 60ms with Box filter and 0.5px window. For huge 17mb image 5000x3000px resize takes ~1s on desktop and 3s on mobile.



                        All resize principles were described very well in this thread, and pica does not add rocket science. But it's optimized very well for modern JIT-s, and is ready to use out of box (via npm or bower). Also, it use webworkers when available to avoid interface freezes.



                        I also plan to add unsharp mask support soon, because it's very useful after downscale.






                        share|improve this answer


























                          23












                          23








                          23







                          Try pica - that's a highly optimized resizer with selectable algorythms. See demo.



                          For example, original image from first post is resized in 120ms with Lanczos filter and 3px window or 60ms with Box filter and 0.5px window. For huge 17mb image 5000x3000px resize takes ~1s on desktop and 3s on mobile.



                          All resize principles were described very well in this thread, and pica does not add rocket science. But it's optimized very well for modern JIT-s, and is ready to use out of box (via npm or bower). Also, it use webworkers when available to avoid interface freezes.



                          I also plan to add unsharp mask support soon, because it's very useful after downscale.






                          share|improve this answer













                          Try pica - that's a highly optimized resizer with selectable algorythms. See demo.



                          For example, original image from first post is resized in 120ms with Lanczos filter and 3px window or 60ms with Box filter and 0.5px window. For huge 17mb image 5000x3000px resize takes ~1s on desktop and 3s on mobile.



                          All resize principles were described very well in this thread, and pica does not add rocket science. But it's optimized very well for modern JIT-s, and is ready to use out of box (via npm or bower). Also, it use webworkers when available to avoid interface freezes.



                          I also plan to add unsharp mask support soon, because it's very useful after downscale.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Sep 24 '14 at 11:04









                          VitalyVitaly

                          1,7981714




                          1,7981714























                              14














                              I know this is an old thread but it might be useful for some people such as myself that months after are hitting this issue for the first time.



                              Here is some code that resizes the image every time you reload the image. I am aware this is not optimal at all, but I provide it as a proof of concept.



                              Also, sorry for using jQuery for simple selectors but I just feel too comfortable with the syntax.






                              $(document).on('ready', createImage);
                              $(window).on('resize', createImage);

                              var createImage = function(){
                              var canvas = document.getElementById('myCanvas');
                              canvas.width = window.innerWidth || $(window).width();
                              canvas.height = window.innerHeight || $(window).height();
                              var ctx = canvas.getContext('2d');
                              img = new Image();
                              img.addEventListener('load', function () {
                              ctx.drawImage(this, 0, 0, w, h);
                              });
                              img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                              };

                              html, body{
                              height: 100%;
                              width: 100%;
                              margin: 0;
                              padding: 0;
                              background: #000;
                              }
                              canvas{
                              position: absolute;
                              left: 0;
                              top: 0;
                              z-index: 0;
                              }

                              <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                              <html>
                              <head>
                              <meta charset="utf-8" />
                              <title>Canvas Resize</title>
                              </head>
                              <body>
                              <canvas id="myCanvas"></canvas>
                              </body>
                              </html>





                              My createImage function is called once when the document is loaded and after that it is called every time the window receives a resize event.



                              I tested it in Chrome 6 and Firefox 3.6, both on the Mac. This "technique" eats processor as it if was ice cream in the summer, but it does the trick.






                              share|improve this answer






























                                14














                                I know this is an old thread but it might be useful for some people such as myself that months after are hitting this issue for the first time.



                                Here is some code that resizes the image every time you reload the image. I am aware this is not optimal at all, but I provide it as a proof of concept.



                                Also, sorry for using jQuery for simple selectors but I just feel too comfortable with the syntax.






                                $(document).on('ready', createImage);
                                $(window).on('resize', createImage);

                                var createImage = function(){
                                var canvas = document.getElementById('myCanvas');
                                canvas.width = window.innerWidth || $(window).width();
                                canvas.height = window.innerHeight || $(window).height();
                                var ctx = canvas.getContext('2d');
                                img = new Image();
                                img.addEventListener('load', function () {
                                ctx.drawImage(this, 0, 0, w, h);
                                });
                                img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                                };

                                html, body{
                                height: 100%;
                                width: 100%;
                                margin: 0;
                                padding: 0;
                                background: #000;
                                }
                                canvas{
                                position: absolute;
                                left: 0;
                                top: 0;
                                z-index: 0;
                                }

                                <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                                <html>
                                <head>
                                <meta charset="utf-8" />
                                <title>Canvas Resize</title>
                                </head>
                                <body>
                                <canvas id="myCanvas"></canvas>
                                </body>
                                </html>





                                My createImage function is called once when the document is loaded and after that it is called every time the window receives a resize event.



                                I tested it in Chrome 6 and Firefox 3.6, both on the Mac. This "technique" eats processor as it if was ice cream in the summer, but it does the trick.






                                share|improve this answer




























                                  14












                                  14








                                  14







                                  I know this is an old thread but it might be useful for some people such as myself that months after are hitting this issue for the first time.



                                  Here is some code that resizes the image every time you reload the image. I am aware this is not optimal at all, but I provide it as a proof of concept.



                                  Also, sorry for using jQuery for simple selectors but I just feel too comfortable with the syntax.






                                  $(document).on('ready', createImage);
                                  $(window).on('resize', createImage);

                                  var createImage = function(){
                                  var canvas = document.getElementById('myCanvas');
                                  canvas.width = window.innerWidth || $(window).width();
                                  canvas.height = window.innerHeight || $(window).height();
                                  var ctx = canvas.getContext('2d');
                                  img = new Image();
                                  img.addEventListener('load', function () {
                                  ctx.drawImage(this, 0, 0, w, h);
                                  });
                                  img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                                  };

                                  html, body{
                                  height: 100%;
                                  width: 100%;
                                  margin: 0;
                                  padding: 0;
                                  background: #000;
                                  }
                                  canvas{
                                  position: absolute;
                                  left: 0;
                                  top: 0;
                                  z-index: 0;
                                  }

                                  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                                  <html>
                                  <head>
                                  <meta charset="utf-8" />
                                  <title>Canvas Resize</title>
                                  </head>
                                  <body>
                                  <canvas id="myCanvas"></canvas>
                                  </body>
                                  </html>





                                  My createImage function is called once when the document is loaded and after that it is called every time the window receives a resize event.



                                  I tested it in Chrome 6 and Firefox 3.6, both on the Mac. This "technique" eats processor as it if was ice cream in the summer, but it does the trick.






                                  share|improve this answer















                                  I know this is an old thread but it might be useful for some people such as myself that months after are hitting this issue for the first time.



                                  Here is some code that resizes the image every time you reload the image. I am aware this is not optimal at all, but I provide it as a proof of concept.



                                  Also, sorry for using jQuery for simple selectors but I just feel too comfortable with the syntax.






                                  $(document).on('ready', createImage);
                                  $(window).on('resize', createImage);

                                  var createImage = function(){
                                  var canvas = document.getElementById('myCanvas');
                                  canvas.width = window.innerWidth || $(window).width();
                                  canvas.height = window.innerHeight || $(window).height();
                                  var ctx = canvas.getContext('2d');
                                  img = new Image();
                                  img.addEventListener('load', function () {
                                  ctx.drawImage(this, 0, 0, w, h);
                                  });
                                  img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                                  };

                                  html, body{
                                  height: 100%;
                                  width: 100%;
                                  margin: 0;
                                  padding: 0;
                                  background: #000;
                                  }
                                  canvas{
                                  position: absolute;
                                  left: 0;
                                  top: 0;
                                  z-index: 0;
                                  }

                                  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                                  <html>
                                  <head>
                                  <meta charset="utf-8" />
                                  <title>Canvas Resize</title>
                                  </head>
                                  <body>
                                  <canvas id="myCanvas"></canvas>
                                  </body>
                                  </html>





                                  My createImage function is called once when the document is loaded and after that it is called every time the window receives a resize event.



                                  I tested it in Chrome 6 and Firefox 3.6, both on the Mac. This "technique" eats processor as it if was ice cream in the summer, but it does the trick.






                                  $(document).on('ready', createImage);
                                  $(window).on('resize', createImage);

                                  var createImage = function(){
                                  var canvas = document.getElementById('myCanvas');
                                  canvas.width = window.innerWidth || $(window).width();
                                  canvas.height = window.innerHeight || $(window).height();
                                  var ctx = canvas.getContext('2d');
                                  img = new Image();
                                  img.addEventListener('load', function () {
                                  ctx.drawImage(this, 0, 0, w, h);
                                  });
                                  img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                                  };

                                  html, body{
                                  height: 100%;
                                  width: 100%;
                                  margin: 0;
                                  padding: 0;
                                  background: #000;
                                  }
                                  canvas{
                                  position: absolute;
                                  left: 0;
                                  top: 0;
                                  z-index: 0;
                                  }

                                  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                                  <html>
                                  <head>
                                  <meta charset="utf-8" />
                                  <title>Canvas Resize</title>
                                  </head>
                                  <body>
                                  <canvas id="myCanvas"></canvas>
                                  </body>
                                  </html>





                                  $(document).on('ready', createImage);
                                  $(window).on('resize', createImage);

                                  var createImage = function(){
                                  var canvas = document.getElementById('myCanvas');
                                  canvas.width = window.innerWidth || $(window).width();
                                  canvas.height = window.innerHeight || $(window).height();
                                  var ctx = canvas.getContext('2d');
                                  img = new Image();
                                  img.addEventListener('load', function () {
                                  ctx.drawImage(this, 0, 0, w, h);
                                  });
                                  img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
                                  };

                                  html, body{
                                  height: 100%;
                                  width: 100%;
                                  margin: 0;
                                  padding: 0;
                                  background: #000;
                                  }
                                  canvas{
                                  position: absolute;
                                  left: 0;
                                  top: 0;
                                  z-index: 0;
                                  }

                                  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                                  <html>
                                  <head>
                                  <meta charset="utf-8" />
                                  <title>Canvas Resize</title>
                                  </head>
                                  <body>
                                  <canvas id="myCanvas"></canvas>
                                  </body>
                                  </html>






                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Aug 7 '16 at 7:07









                                  Al Foиce ѫ

                                  3,16462440




                                  3,16462440










                                  answered Oct 13 '10 at 21:49









                                  cesarsalazarcesarsalazar

                                  658613




                                  658613























                                      9














                                      I've put up some algorithms to do image interpolation on html canvas pixel arrays that might be useful here:



                                      https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2



                                      These can be copy/pasted and can be used inside of web workers to resize images (or any other operation that requires interpolation - I'm using them to defish images at the moment).



                                      I haven't added the lanczos stuff above, so feel free to add that as a comparison if you'd like.






                                      share|improve this answer






























                                        9














                                        I've put up some algorithms to do image interpolation on html canvas pixel arrays that might be useful here:



                                        https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2



                                        These can be copy/pasted and can be used inside of web workers to resize images (or any other operation that requires interpolation - I'm using them to defish images at the moment).



                                        I haven't added the lanczos stuff above, so feel free to add that as a comparison if you'd like.






                                        share|improve this answer




























                                          9












                                          9








                                          9







                                          I've put up some algorithms to do image interpolation on html canvas pixel arrays that might be useful here:



                                          https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2



                                          These can be copy/pasted and can be used inside of web workers to resize images (or any other operation that requires interpolation - I'm using them to defish images at the moment).



                                          I haven't added the lanczos stuff above, so feel free to add that as a comparison if you'd like.






                                          share|improve this answer















                                          I've put up some algorithms to do image interpolation on html canvas pixel arrays that might be useful here:



                                          https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2



                                          These can be copy/pasted and can be used inside of web workers to resize images (or any other operation that requires interpolation - I'm using them to defish images at the moment).



                                          I haven't added the lanczos stuff above, so feel free to add that as a comparison if you'd like.







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited Nov 27 '18 at 17:33









                                          kukuch

                                          1916




                                          1916










                                          answered Oct 26 '11 at 20:29









                                          DanielDaniel

                                          4,87923026




                                          4,87923026























                                              6














                                              If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. Here's a quick example:



                                              .small-image {
                                              width: 100px;
                                              height: 100px;
                                              }


                                              Note that the height and width can also be set using JavaScript. Here's quick code sample:



                                              var img = document.getElement("my-image");
                                              img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
                                              img.style.height = 100 + "px"; // otherwise you'll confuse IE


                                              Also, to ensure that the resized image looks good, add the following css rules to image selector:





                                              • -ms-interpolation-mode: bicubic: introduce in IE7


                                              • image-rendering: optimizeQuality: introduced in FireFox 3.6


                                              As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome.



                                              If setting the css width and height doesn't work, you may want to play with a css transform:




                                              • -moz-transform: scale(sx[, sy])

                                              • -webkit-transform:scale(sx[, sy])


                                              If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size.



                                              See this question for more details.



                                              Hope this helps!






                                              share|improve this answer





















                                              • 5





                                                Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                                – Nestor
                                                Mar 21 '11 at 1:23






                                              • 1





                                                Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                                – syockit
                                                Jul 7 '13 at 12:52
















                                              6














                                              If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. Here's a quick example:



                                              .small-image {
                                              width: 100px;
                                              height: 100px;
                                              }


                                              Note that the height and width can also be set using JavaScript. Here's quick code sample:



                                              var img = document.getElement("my-image");
                                              img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
                                              img.style.height = 100 + "px"; // otherwise you'll confuse IE


                                              Also, to ensure that the resized image looks good, add the following css rules to image selector:





                                              • -ms-interpolation-mode: bicubic: introduce in IE7


                                              • image-rendering: optimizeQuality: introduced in FireFox 3.6


                                              As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome.



                                              If setting the css width and height doesn't work, you may want to play with a css transform:




                                              • -moz-transform: scale(sx[, sy])

                                              • -webkit-transform:scale(sx[, sy])


                                              If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size.



                                              See this question for more details.



                                              Hope this helps!






                                              share|improve this answer





















                                              • 5





                                                Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                                – Nestor
                                                Mar 21 '11 at 1:23






                                              • 1





                                                Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                                – syockit
                                                Jul 7 '13 at 12:52














                                              6












                                              6








                                              6







                                              If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. Here's a quick example:



                                              .small-image {
                                              width: 100px;
                                              height: 100px;
                                              }


                                              Note that the height and width can also be set using JavaScript. Here's quick code sample:



                                              var img = document.getElement("my-image");
                                              img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
                                              img.style.height = 100 + "px"; // otherwise you'll confuse IE


                                              Also, to ensure that the resized image looks good, add the following css rules to image selector:





                                              • -ms-interpolation-mode: bicubic: introduce in IE7


                                              • image-rendering: optimizeQuality: introduced in FireFox 3.6


                                              As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome.



                                              If setting the css width and height doesn't work, you may want to play with a css transform:




                                              • -moz-transform: scale(sx[, sy])

                                              • -webkit-transform:scale(sx[, sy])


                                              If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size.



                                              See this question for more details.



                                              Hope this helps!






                                              share|improve this answer















                                              If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. Here's a quick example:



                                              .small-image {
                                              width: 100px;
                                              height: 100px;
                                              }


                                              Note that the height and width can also be set using JavaScript. Here's quick code sample:



                                              var img = document.getElement("my-image");
                                              img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
                                              img.style.height = 100 + "px"; // otherwise you'll confuse IE


                                              Also, to ensure that the resized image looks good, add the following css rules to image selector:





                                              • -ms-interpolation-mode: bicubic: introduce in IE7


                                              • image-rendering: optimizeQuality: introduced in FireFox 3.6


                                              As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome.



                                              If setting the css width and height doesn't work, you may want to play with a css transform:




                                              • -moz-transform: scale(sx[, sy])

                                              • -webkit-transform:scale(sx[, sy])


                                              If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size.



                                              See this question for more details.



                                              Hope this helps!







                                              share|improve this answer














                                              share|improve this answer



                                              share|improve this answer








                                              edited May 23 '17 at 12:02









                                              Community

                                              11




                                              11










                                              answered Feb 22 '10 at 15:34









                                              XaviXavi

                                              16k116360




                                              16k116360








                                              • 5





                                                Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                                – Nestor
                                                Mar 21 '11 at 1:23






                                              • 1





                                                Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                                – syockit
                                                Jul 7 '13 at 12:52














                                              • 5





                                                Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                                – Nestor
                                                Mar 21 '11 at 1:23






                                              • 1





                                                Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                                – syockit
                                                Jul 7 '13 at 12:52








                                              5




                                              5





                                              Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                              – Nestor
                                              Mar 21 '11 at 1:23





                                              Neither resizing the canvas nor drawing the image at a smaller size resolves the problem (in Chrome), sadly.

                                              – Nestor
                                              Mar 21 '11 at 1:23




                                              1




                                              1





                                              Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                              – syockit
                                              Jul 7 '13 at 12:52





                                              Chrome 27 produces nice resized image, but you can't copy the result to a canvas; attempting to do so will copy the original image instead.

                                              – syockit
                                              Jul 7 '13 at 12:52











                                              6














                                              This is a javascript function adapted from @Telanor's code. When passing a image base64 as first argument to the function, it returns the base64 of the resized image. maxWidth and maxHeight are optional.



                                              function thumbnail(base64, maxWidth, maxHeight) {

                                              // Max size for thumbnail
                                              if(typeof(maxWidth) === 'undefined') var maxWidth = 500;
                                              if(typeof(maxHeight) === 'undefined') var maxHeight = 500;

                                              // Create and initialize two canvas
                                              var canvas = document.createElement("canvas");
                                              var ctx = canvas.getContext("2d");
                                              var canvasCopy = document.createElement("canvas");
                                              var copyContext = canvasCopy.getContext("2d");

                                              // Create original image
                                              var img = new Image();
                                              img.src = base64;

                                              // Determine new ratio based on max size
                                              var ratio = 1;
                                              if(img.width > maxWidth)
                                              ratio = maxWidth / img.width;
                                              else if(img.height > maxHeight)
                                              ratio = maxHeight / img.height;

                                              // Draw original image in second canvas
                                              canvasCopy.width = img.width;
                                              canvasCopy.height = img.height;
                                              copyContext.drawImage(img, 0, 0);

                                              // Copy and resize second canvas to first canvas
                                              canvas.width = img.width * ratio;
                                              canvas.height = img.height * ratio;
                                              ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

                                              return canvas.toDataURL();

                                              }





                                              share|improve this answer
























                                              • your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                                – confile
                                                Sep 23 '13 at 12:58
















                                              6














                                              This is a javascript function adapted from @Telanor's code. When passing a image base64 as first argument to the function, it returns the base64 of the resized image. maxWidth and maxHeight are optional.



                                              function thumbnail(base64, maxWidth, maxHeight) {

                                              // Max size for thumbnail
                                              if(typeof(maxWidth) === 'undefined') var maxWidth = 500;
                                              if(typeof(maxHeight) === 'undefined') var maxHeight = 500;

                                              // Create and initialize two canvas
                                              var canvas = document.createElement("canvas");
                                              var ctx = canvas.getContext("2d");
                                              var canvasCopy = document.createElement("canvas");
                                              var copyContext = canvasCopy.getContext("2d");

                                              // Create original image
                                              var img = new Image();
                                              img.src = base64;

                                              // Determine new ratio based on max size
                                              var ratio = 1;
                                              if(img.width > maxWidth)
                                              ratio = maxWidth / img.width;
                                              else if(img.height > maxHeight)
                                              ratio = maxHeight / img.height;

                                              // Draw original image in second canvas
                                              canvasCopy.width = img.width;
                                              canvasCopy.height = img.height;
                                              copyContext.drawImage(img, 0, 0);

                                              // Copy and resize second canvas to first canvas
                                              canvas.width = img.width * ratio;
                                              canvas.height = img.height * ratio;
                                              ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

                                              return canvas.toDataURL();

                                              }





                                              share|improve this answer
























                                              • your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                                – confile
                                                Sep 23 '13 at 12:58














                                              6












                                              6








                                              6







                                              This is a javascript function adapted from @Telanor's code. When passing a image base64 as first argument to the function, it returns the base64 of the resized image. maxWidth and maxHeight are optional.



                                              function thumbnail(base64, maxWidth, maxHeight) {

                                              // Max size for thumbnail
                                              if(typeof(maxWidth) === 'undefined') var maxWidth = 500;
                                              if(typeof(maxHeight) === 'undefined') var maxHeight = 500;

                                              // Create and initialize two canvas
                                              var canvas = document.createElement("canvas");
                                              var ctx = canvas.getContext("2d");
                                              var canvasCopy = document.createElement("canvas");
                                              var copyContext = canvasCopy.getContext("2d");

                                              // Create original image
                                              var img = new Image();
                                              img.src = base64;

                                              // Determine new ratio based on max size
                                              var ratio = 1;
                                              if(img.width > maxWidth)
                                              ratio = maxWidth / img.width;
                                              else if(img.height > maxHeight)
                                              ratio = maxHeight / img.height;

                                              // Draw original image in second canvas
                                              canvasCopy.width = img.width;
                                              canvasCopy.height = img.height;
                                              copyContext.drawImage(img, 0, 0);

                                              // Copy and resize second canvas to first canvas
                                              canvas.width = img.width * ratio;
                                              canvas.height = img.height * ratio;
                                              ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

                                              return canvas.toDataURL();

                                              }





                                              share|improve this answer













                                              This is a javascript function adapted from @Telanor's code. When passing a image base64 as first argument to the function, it returns the base64 of the resized image. maxWidth and maxHeight are optional.



                                              function thumbnail(base64, maxWidth, maxHeight) {

                                              // Max size for thumbnail
                                              if(typeof(maxWidth) === 'undefined') var maxWidth = 500;
                                              if(typeof(maxHeight) === 'undefined') var maxHeight = 500;

                                              // Create and initialize two canvas
                                              var canvas = document.createElement("canvas");
                                              var ctx = canvas.getContext("2d");
                                              var canvasCopy = document.createElement("canvas");
                                              var copyContext = canvasCopy.getContext("2d");

                                              // Create original image
                                              var img = new Image();
                                              img.src = base64;

                                              // Determine new ratio based on max size
                                              var ratio = 1;
                                              if(img.width > maxWidth)
                                              ratio = maxWidth / img.width;
                                              else if(img.height > maxHeight)
                                              ratio = maxHeight / img.height;

                                              // Draw original image in second canvas
                                              canvasCopy.width = img.width;
                                              canvasCopy.height = img.height;
                                              copyContext.drawImage(img, 0, 0);

                                              // Copy and resize second canvas to first canvas
                                              canvas.width = img.width * ratio;
                                              canvas.height = img.height * ratio;
                                              ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

                                              return canvas.toDataURL();

                                              }






                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              answered Feb 13 '13 at 3:12









                                              Christophe MaroisChristophe Marois

                                              3,77411620




                                              3,77411620













                                              • your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                                – confile
                                                Sep 23 '13 at 12:58



















                                              • your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                                – confile
                                                Sep 23 '13 at 12:58

















                                              your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                              – confile
                                              Sep 23 '13 at 12:58





                                              your approach is very fast but it produces a fuzzy image as you can see here: stackoverflow.com/questions/18922880/…

                                              – confile
                                              Sep 23 '13 at 12:58











                                              6














                                              I'd highly suggest you check out this link and make sure it is set to true.




                                              Controlling image scaling behavior



                                              Introduced in Gecko 1.9.2 (Firefox 3.6
                                              / Thunderbird 3.1 / Fennec 1.0)



                                              Gecko 1.9.2 introduced the
                                              mozImageSmoothingEnabled property to
                                              the canvas element; if this Boolean
                                              value is false, images won't be
                                              smoothed when scaled. This property is
                                              true by default. view plainprint?




                                              1. cx.mozImageSmoothingEnabled = false;







                                              share|improve this answer


























                                              • Yup, its set to true

                                                – Telanor
                                                Jul 14 '10 at 4:58
















                                              6














                                              I'd highly suggest you check out this link and make sure it is set to true.




                                              Controlling image scaling behavior



                                              Introduced in Gecko 1.9.2 (Firefox 3.6
                                              / Thunderbird 3.1 / Fennec 1.0)



                                              Gecko 1.9.2 introduced the
                                              mozImageSmoothingEnabled property to
                                              the canvas element; if this Boolean
                                              value is false, images won't be
                                              smoothed when scaled. This property is
                                              true by default. view plainprint?




                                              1. cx.mozImageSmoothingEnabled = false;







                                              share|improve this answer


























                                              • Yup, its set to true

                                                – Telanor
                                                Jul 14 '10 at 4:58














                                              6












                                              6








                                              6







                                              I'd highly suggest you check out this link and make sure it is set to true.




                                              Controlling image scaling behavior



                                              Introduced in Gecko 1.9.2 (Firefox 3.6
                                              / Thunderbird 3.1 / Fennec 1.0)



                                              Gecko 1.9.2 introduced the
                                              mozImageSmoothingEnabled property to
                                              the canvas element; if this Boolean
                                              value is false, images won't be
                                              smoothed when scaled. This property is
                                              true by default. view plainprint?




                                              1. cx.mozImageSmoothingEnabled = false;







                                              share|improve this answer















                                              I'd highly suggest you check out this link and make sure it is set to true.




                                              Controlling image scaling behavior



                                              Introduced in Gecko 1.9.2 (Firefox 3.6
                                              / Thunderbird 3.1 / Fennec 1.0)



                                              Gecko 1.9.2 introduced the
                                              mozImageSmoothingEnabled property to
                                              the canvas element; if this Boolean
                                              value is false, images won't be
                                              smoothed when scaled. This property is
                                              true by default. view plainprint?




                                              1. cx.mozImageSmoothingEnabled = false;








                                              share|improve this answer














                                              share|improve this answer



                                              share|improve this answer








                                              edited Nov 27 '18 at 18:55









                                              kukuch

                                              1916




                                              1916










                                              answered Jul 13 '10 at 17:02









                                              Evan CarrollEvan Carroll

                                              36.2k24147248




                                              36.2k24147248













                                              • Yup, its set to true

                                                – Telanor
                                                Jul 14 '10 at 4:58



















                                              • Yup, its set to true

                                                – Telanor
                                                Jul 14 '10 at 4:58

















                                              Yup, its set to true

                                              – Telanor
                                              Jul 14 '10 at 4:58





                                              Yup, its set to true

                                              – Telanor
                                              Jul 14 '10 at 4:58











                                              4














                                              For resizing to image with width less that original, i use:



                                                  function resize2(i) {
                                              var cc = document.createElement("canvas");
                                              cc.width = i.width / 2;
                                              cc.height = i.height / 2;
                                              var ctx = cc.getContext("2d");
                                              ctx.drawImage(i, 0, 0, cc.width, cc.height);
                                              return cc;
                                              }
                                              var cc = img;
                                              while (cc.width > 64 * 2) {
                                              cc = resize2(cc);
                                              }
                                              // .. than drawImage(cc, .... )


                                              and it works =).






                                              share|improve this answer




























                                                4














                                                For resizing to image with width less that original, i use:



                                                    function resize2(i) {
                                                var cc = document.createElement("canvas");
                                                cc.width = i.width / 2;
                                                cc.height = i.height / 2;
                                                var ctx = cc.getContext("2d");
                                                ctx.drawImage(i, 0, 0, cc.width, cc.height);
                                                return cc;
                                                }
                                                var cc = img;
                                                while (cc.width > 64 * 2) {
                                                cc = resize2(cc);
                                                }
                                                // .. than drawImage(cc, .... )


                                                and it works =).






                                                share|improve this answer


























                                                  4












                                                  4








                                                  4







                                                  For resizing to image with width less that original, i use:



                                                      function resize2(i) {
                                                  var cc = document.createElement("canvas");
                                                  cc.width = i.width / 2;
                                                  cc.height = i.height / 2;
                                                  var ctx = cc.getContext("2d");
                                                  ctx.drawImage(i, 0, 0, cc.width, cc.height);
                                                  return cc;
                                                  }
                                                  var cc = img;
                                                  while (cc.width > 64 * 2) {
                                                  cc = resize2(cc);
                                                  }
                                                  // .. than drawImage(cc, .... )


                                                  and it works =).






                                                  share|improve this answer













                                                  For resizing to image with width less that original, i use:



                                                      function resize2(i) {
                                                  var cc = document.createElement("canvas");
                                                  cc.width = i.width / 2;
                                                  cc.height = i.height / 2;
                                                  var ctx = cc.getContext("2d");
                                                  ctx.drawImage(i, 0, 0, cc.width, cc.height);
                                                  return cc;
                                                  }
                                                  var cc = img;
                                                  while (cc.width > 64 * 2) {
                                                  cc = resize2(cc);
                                                  }
                                                  // .. than drawImage(cc, .... )


                                                  and it works =).







                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered Mar 23 '11 at 18:27









                                                  YaffleYaffle

                                                  22923




                                                  22923























                                                      4














                                                      i got this image by right clicking the canvas element in firefox and saving as.



                                                      alt text



                                                      var img = new Image();
                                                      img.onload = function () {
                                                      console.debug(this.width,this.height);
                                                      var canvas = document.createElement('canvas'), ctx;
                                                      canvas.width = 188;
                                                      canvas.height = 150;
                                                      document.body.appendChild(canvas);
                                                      ctx = canvas.getContext('2d');
                                                      ctx.drawImage(img,0,0,188,150);
                                                      };
                                                      img.src = 'original.jpg';


                                                      so anyway, here is a 'fixed' version of your example:



                                                      var img = new Image();
                                                      // added cause it wasnt defined
                                                      var canvas = document.createElement("canvas");
                                                      document.body.appendChild(canvas);

                                                      var ctx = canvas.getContext("2d");
                                                      var canvasCopy = document.createElement("canvas");
                                                      // adding it to the body

                                                      document.body.appendChild(canvasCopy);

                                                      var copyContext = canvasCopy.getContext("2d");

                                                      img.onload = function()
                                                      {
                                                      var ratio = 1;

                                                      // defining cause it wasnt
                                                      var maxWidth = 188,
                                                      maxHeight = 150;

                                                      if(img.width > maxWidth)
                                                      ratio = maxWidth / img.width;
                                                      else if(img.height > maxHeight)
                                                      ratio = maxHeight / img.height;

                                                      canvasCopy.width = img.width;
                                                      canvasCopy.height = img.height;
                                                      copyContext.drawImage(img, 0, 0);

                                                      canvas.width = img.width * ratio;
                                                      canvas.height = img.height * ratio;
                                                      // the line to change
                                                      // ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
                                                      // the method signature you are using is for slicing
                                                      ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
                                                      };

                                                      // changed for example
                                                      img.src = 'original.jpg';





                                                      share|improve this answer


























                                                      • I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                        – Telanor
                                                        Mar 14 '10 at 21:11
















                                                      4














                                                      i got this image by right clicking the canvas element in firefox and saving as.



                                                      alt text



                                                      var img = new Image();
                                                      img.onload = function () {
                                                      console.debug(this.width,this.height);
                                                      var canvas = document.createElement('canvas'), ctx;
                                                      canvas.width = 188;
                                                      canvas.height = 150;
                                                      document.body.appendChild(canvas);
                                                      ctx = canvas.getContext('2d');
                                                      ctx.drawImage(img,0,0,188,150);
                                                      };
                                                      img.src = 'original.jpg';


                                                      so anyway, here is a 'fixed' version of your example:



                                                      var img = new Image();
                                                      // added cause it wasnt defined
                                                      var canvas = document.createElement("canvas");
                                                      document.body.appendChild(canvas);

                                                      var ctx = canvas.getContext("2d");
                                                      var canvasCopy = document.createElement("canvas");
                                                      // adding it to the body

                                                      document.body.appendChild(canvasCopy);

                                                      var copyContext = canvasCopy.getContext("2d");

                                                      img.onload = function()
                                                      {
                                                      var ratio = 1;

                                                      // defining cause it wasnt
                                                      var maxWidth = 188,
                                                      maxHeight = 150;

                                                      if(img.width > maxWidth)
                                                      ratio = maxWidth / img.width;
                                                      else if(img.height > maxHeight)
                                                      ratio = maxHeight / img.height;

                                                      canvasCopy.width = img.width;
                                                      canvasCopy.height = img.height;
                                                      copyContext.drawImage(img, 0, 0);

                                                      canvas.width = img.width * ratio;
                                                      canvas.height = img.height * ratio;
                                                      // the line to change
                                                      // ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
                                                      // the method signature you are using is for slicing
                                                      ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
                                                      };

                                                      // changed for example
                                                      img.src = 'original.jpg';





                                                      share|improve this answer


























                                                      • I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                        – Telanor
                                                        Mar 14 '10 at 21:11














                                                      4












                                                      4








                                                      4







                                                      i got this image by right clicking the canvas element in firefox and saving as.



                                                      alt text



                                                      var img = new Image();
                                                      img.onload = function () {
                                                      console.debug(this.width,this.height);
                                                      var canvas = document.createElement('canvas'), ctx;
                                                      canvas.width = 188;
                                                      canvas.height = 150;
                                                      document.body.appendChild(canvas);
                                                      ctx = canvas.getContext('2d');
                                                      ctx.drawImage(img,0,0,188,150);
                                                      };
                                                      img.src = 'original.jpg';


                                                      so anyway, here is a 'fixed' version of your example:



                                                      var img = new Image();
                                                      // added cause it wasnt defined
                                                      var canvas = document.createElement("canvas");
                                                      document.body.appendChild(canvas);

                                                      var ctx = canvas.getContext("2d");
                                                      var canvasCopy = document.createElement("canvas");
                                                      // adding it to the body

                                                      document.body.appendChild(canvasCopy);

                                                      var copyContext = canvasCopy.getContext("2d");

                                                      img.onload = function()
                                                      {
                                                      var ratio = 1;

                                                      // defining cause it wasnt
                                                      var maxWidth = 188,
                                                      maxHeight = 150;

                                                      if(img.width > maxWidth)
                                                      ratio = maxWidth / img.width;
                                                      else if(img.height > maxHeight)
                                                      ratio = maxHeight / img.height;

                                                      canvasCopy.width = img.width;
                                                      canvasCopy.height = img.height;
                                                      copyContext.drawImage(img, 0, 0);

                                                      canvas.width = img.width * ratio;
                                                      canvas.height = img.height * ratio;
                                                      // the line to change
                                                      // ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
                                                      // the method signature you are using is for slicing
                                                      ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
                                                      };

                                                      // changed for example
                                                      img.src = 'original.jpg';





                                                      share|improve this answer















                                                      i got this image by right clicking the canvas element in firefox and saving as.



                                                      alt text



                                                      var img = new Image();
                                                      img.onload = function () {
                                                      console.debug(this.width,this.height);
                                                      var canvas = document.createElement('canvas'), ctx;
                                                      canvas.width = 188;
                                                      canvas.height = 150;
                                                      document.body.appendChild(canvas);
                                                      ctx = canvas.getContext('2d');
                                                      ctx.drawImage(img,0,0,188,150);
                                                      };
                                                      img.src = 'original.jpg';


                                                      so anyway, here is a 'fixed' version of your example:



                                                      var img = new Image();
                                                      // added cause it wasnt defined
                                                      var canvas = document.createElement("canvas");
                                                      document.body.appendChild(canvas);

                                                      var ctx = canvas.getContext("2d");
                                                      var canvasCopy = document.createElement("canvas");
                                                      // adding it to the body

                                                      document.body.appendChild(canvasCopy);

                                                      var copyContext = canvasCopy.getContext("2d");

                                                      img.onload = function()
                                                      {
                                                      var ratio = 1;

                                                      // defining cause it wasnt
                                                      var maxWidth = 188,
                                                      maxHeight = 150;

                                                      if(img.width > maxWidth)
                                                      ratio = maxWidth / img.width;
                                                      else if(img.height > maxHeight)
                                                      ratio = maxHeight / img.height;

                                                      canvasCopy.width = img.width;
                                                      canvasCopy.height = img.height;
                                                      copyContext.drawImage(img, 0, 0);

                                                      canvas.width = img.width * ratio;
                                                      canvas.height = img.height * ratio;
                                                      // the line to change
                                                      // ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
                                                      // the method signature you are using is for slicing
                                                      ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
                                                      };

                                                      // changed for example
                                                      img.src = 'original.jpg';






                                                      share|improve this answer














                                                      share|improve this answer



                                                      share|improve this answer








                                                      edited Nov 25 '14 at 3:24







                                                      user1693593

















                                                      answered Mar 9 '10 at 21:12









                                                      robertrobert

                                                      2,74111420




                                                      2,74111420













                                                      • I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                        – Telanor
                                                        Mar 14 '10 at 21:11



















                                                      • I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                        – Telanor
                                                        Mar 14 '10 at 21:11

















                                                      I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                      – Telanor
                                                      Mar 14 '10 at 21:11





                                                      I've tried doing what you did and its not coming out nice like yours. Unless I missed something, the only change you made was to use the scaling method signature instead of the slicing one, right? For some reason its not working for me.

                                                      – Telanor
                                                      Mar 14 '10 at 21:11











                                                      3














                                                      The problem with some of this solutions is that they access directly the pixel data and loop through it to perform the downsampling. Depending on the size of the image this can be very resource intensive, and it would be better to use the browser's internal algorithms.



                                                      The drawImage() function is using a linear-interpolation, nearest-neighbor resampling method. That works well when you are not resizing down more than half the original size.



                                                      If you loop to only resize max one half at a time, the results would be quite good, and much faster than accessing pixel data.



                                                      This function downsample to half at a time until reaching the desired size:



                                                        function resize_image( src, dst, type, quality ) {
                                                      var tmp = new Image(),
                                                      canvas, context, cW, cH;

                                                      type = type || 'image/jpeg';
                                                      quality = quality || 0.92;

                                                      cW = src.naturalWidth;
                                                      cH = src.naturalHeight;

                                                      tmp.src = src.src;
                                                      tmp.onload = function() {

                                                      canvas = document.createElement( 'canvas' );

                                                      cW /= 2;
                                                      cH /= 2;

                                                      if ( cW < src.width ) cW = src.width;
                                                      if ( cH < src.height ) cH = src.height;

                                                      canvas.width = cW;
                                                      canvas.height = cH;
                                                      context = canvas.getContext( '2d' );
                                                      context.drawImage( tmp, 0, 0, cW, cH );

                                                      dst.src = canvas.toDataURL( type, quality );

                                                      if ( cW <= src.width || cH <= src.height )
                                                      return;

                                                      tmp.src = dst.src;
                                                      }

                                                      }
                                                      // The images sent as parameters can be in the DOM or be image objects
                                                      resize_image( $( '#original' )[0], $( '#smaller' )[0] );


                                                      Credits to this post






                                                      share|improve this answer






























                                                        3














                                                        The problem with some of this solutions is that they access directly the pixel data and loop through it to perform the downsampling. Depending on the size of the image this can be very resource intensive, and it would be better to use the browser's internal algorithms.



                                                        The drawImage() function is using a linear-interpolation, nearest-neighbor resampling method. That works well when you are not resizing down more than half the original size.



                                                        If you loop to only resize max one half at a time, the results would be quite good, and much faster than accessing pixel data.



                                                        This function downsample to half at a time until reaching the desired size:



                                                          function resize_image( src, dst, type, quality ) {
                                                        var tmp = new Image(),
                                                        canvas, context, cW, cH;

                                                        type = type || 'image/jpeg';
                                                        quality = quality || 0.92;

                                                        cW = src.naturalWidth;
                                                        cH = src.naturalHeight;

                                                        tmp.src = src.src;
                                                        tmp.onload = function() {

                                                        canvas = document.createElement( 'canvas' );

                                                        cW /= 2;
                                                        cH /= 2;

                                                        if ( cW < src.width ) cW = src.width;
                                                        if ( cH < src.height ) cH = src.height;

                                                        canvas.width = cW;
                                                        canvas.height = cH;
                                                        context = canvas.getContext( '2d' );
                                                        context.drawImage( tmp, 0, 0, cW, cH );

                                                        dst.src = canvas.toDataURL( type, quality );

                                                        if ( cW <= src.width || cH <= src.height )
                                                        return;

                                                        tmp.src = dst.src;
                                                        }

                                                        }
                                                        // The images sent as parameters can be in the DOM or be image objects
                                                        resize_image( $( '#original' )[0], $( '#smaller' )[0] );


                                                        Credits to this post






                                                        share|improve this answer




























                                                          3












                                                          3








                                                          3







                                                          The problem with some of this solutions is that they access directly the pixel data and loop through it to perform the downsampling. Depending on the size of the image this can be very resource intensive, and it would be better to use the browser's internal algorithms.



                                                          The drawImage() function is using a linear-interpolation, nearest-neighbor resampling method. That works well when you are not resizing down more than half the original size.



                                                          If you loop to only resize max one half at a time, the results would be quite good, and much faster than accessing pixel data.



                                                          This function downsample to half at a time until reaching the desired size:



                                                            function resize_image( src, dst, type, quality ) {
                                                          var tmp = new Image(),
                                                          canvas, context, cW, cH;

                                                          type = type || 'image/jpeg';
                                                          quality = quality || 0.92;

                                                          cW = src.naturalWidth;
                                                          cH = src.naturalHeight;

                                                          tmp.src = src.src;
                                                          tmp.onload = function() {

                                                          canvas = document.createElement( 'canvas' );

                                                          cW /= 2;
                                                          cH /= 2;

                                                          if ( cW < src.width ) cW = src.width;
                                                          if ( cH < src.height ) cH = src.height;

                                                          canvas.width = cW;
                                                          canvas.height = cH;
                                                          context = canvas.getContext( '2d' );
                                                          context.drawImage( tmp, 0, 0, cW, cH );

                                                          dst.src = canvas.toDataURL( type, quality );

                                                          if ( cW <= src.width || cH <= src.height )
                                                          return;

                                                          tmp.src = dst.src;
                                                          }

                                                          }
                                                          // The images sent as parameters can be in the DOM or be image objects
                                                          resize_image( $( '#original' )[0], $( '#smaller' )[0] );


                                                          Credits to this post






                                                          share|improve this answer















                                                          The problem with some of this solutions is that they access directly the pixel data and loop through it to perform the downsampling. Depending on the size of the image this can be very resource intensive, and it would be better to use the browser's internal algorithms.



                                                          The drawImage() function is using a linear-interpolation, nearest-neighbor resampling method. That works well when you are not resizing down more than half the original size.



                                                          If you loop to only resize max one half at a time, the results would be quite good, and much faster than accessing pixel data.



                                                          This function downsample to half at a time until reaching the desired size:



                                                            function resize_image( src, dst, type, quality ) {
                                                          var tmp = new Image(),
                                                          canvas, context, cW, cH;

                                                          type = type || 'image/jpeg';
                                                          quality = quality || 0.92;

                                                          cW = src.naturalWidth;
                                                          cH = src.naturalHeight;

                                                          tmp.src = src.src;
                                                          tmp.onload = function() {

                                                          canvas = document.createElement( 'canvas' );

                                                          cW /= 2;
                                                          cH /= 2;

                                                          if ( cW < src.width ) cW = src.width;
                                                          if ( cH < src.height ) cH = src.height;

                                                          canvas.width = cW;
                                                          canvas.height = cH;
                                                          context = canvas.getContext( '2d' );
                                                          context.drawImage( tmp, 0, 0, cW, cH );

                                                          dst.src = canvas.toDataURL( type, quality );

                                                          if ( cW <= src.width || cH <= src.height )
                                                          return;

                                                          tmp.src = dst.src;
                                                          }

                                                          }
                                                          // The images sent as parameters can be in the DOM or be image objects
                                                          resize_image( $( '#original' )[0], $( '#smaller' )[0] );


                                                          Credits to this post







                                                          share|improve this answer














                                                          share|improve this answer



                                                          share|improve this answer








                                                          edited Dec 4 '18 at 10:11









                                                          kukuch

                                                          1916




                                                          1916










                                                          answered Aug 27 '14 at 14:06









                                                          Jesús CarreraJesús Carrera

                                                          8,90734951




                                                          8,90734951























                                                              2














                                                              So something interesting that I found a while ago while working with canvas that might be helpful:



                                                              To resize the canvas control on its own, you need to use the height="" and width="" attributes (or canvas.width/canvas.height elements). If you use CSS to resize the canvas, it will actually stretch (i.e.: resize) the content of the canvas to fit the full canvas (rather than simply increasing or decreasing the area of the canvas.



                                                              It'd be worth a shot to try drawing the image into a canvas control with the height and width attributes set to the size of the image and then using CSS to resize the canvas to the size you're looking for. Perhaps this would use a different resizing algorithm.



                                                              It should also be noted that canvas has different effects in different browsers (and even different versions of different browsers). The algorithms and techniques used in the browsers is likely to change over time (especially with Firefox 4 and Chrome 6 coming out so soon, which will place heavy emphasis on canvas rendering performance).



                                                              In addition, you may want to give SVG a shot, too, as it likely uses a different algorithm as well.



                                                              Best of luck!






                                                              share|improve this answer



















                                                              • 1





                                                                Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                                – Telanor
                                                                Jul 6 '10 at 20:42











                                                              • Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                                – Nestor
                                                                Mar 21 '11 at 1:20
















                                                              2














                                                              So something interesting that I found a while ago while working with canvas that might be helpful:



                                                              To resize the canvas control on its own, you need to use the height="" and width="" attributes (or canvas.width/canvas.height elements). If you use CSS to resize the canvas, it will actually stretch (i.e.: resize) the content of the canvas to fit the full canvas (rather than simply increasing or decreasing the area of the canvas.



                                                              It'd be worth a shot to try drawing the image into a canvas control with the height and width attributes set to the size of the image and then using CSS to resize the canvas to the size you're looking for. Perhaps this would use a different resizing algorithm.



                                                              It should also be noted that canvas has different effects in different browsers (and even different versions of different browsers). The algorithms and techniques used in the browsers is likely to change over time (especially with Firefox 4 and Chrome 6 coming out so soon, which will place heavy emphasis on canvas rendering performance).



                                                              In addition, you may want to give SVG a shot, too, as it likely uses a different algorithm as well.



                                                              Best of luck!






                                                              share|improve this answer



















                                                              • 1





                                                                Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                                – Telanor
                                                                Jul 6 '10 at 20:42











                                                              • Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                                – Nestor
                                                                Mar 21 '11 at 1:20














                                                              2












                                                              2








                                                              2







                                                              So something interesting that I found a while ago while working with canvas that might be helpful:



                                                              To resize the canvas control on its own, you need to use the height="" and width="" attributes (or canvas.width/canvas.height elements). If you use CSS to resize the canvas, it will actually stretch (i.e.: resize) the content of the canvas to fit the full canvas (rather than simply increasing or decreasing the area of the canvas.



                                                              It'd be worth a shot to try drawing the image into a canvas control with the height and width attributes set to the size of the image and then using CSS to resize the canvas to the size you're looking for. Perhaps this would use a different resizing algorithm.



                                                              It should also be noted that canvas has different effects in different browsers (and even different versions of different browsers). The algorithms and techniques used in the browsers is likely to change over time (especially with Firefox 4 and Chrome 6 coming out so soon, which will place heavy emphasis on canvas rendering performance).



                                                              In addition, you may want to give SVG a shot, too, as it likely uses a different algorithm as well.



                                                              Best of luck!






                                                              share|improve this answer













                                                              So something interesting that I found a while ago while working with canvas that might be helpful:



                                                              To resize the canvas control on its own, you need to use the height="" and width="" attributes (or canvas.width/canvas.height elements). If you use CSS to resize the canvas, it will actually stretch (i.e.: resize) the content of the canvas to fit the full canvas (rather than simply increasing or decreasing the area of the canvas.



                                                              It'd be worth a shot to try drawing the image into a canvas control with the height and width attributes set to the size of the image and then using CSS to resize the canvas to the size you're looking for. Perhaps this would use a different resizing algorithm.



                                                              It should also be noted that canvas has different effects in different browsers (and even different versions of different browsers). The algorithms and techniques used in the browsers is likely to change over time (especially with Firefox 4 and Chrome 6 coming out so soon, which will place heavy emphasis on canvas rendering performance).



                                                              In addition, you may want to give SVG a shot, too, as it likely uses a different algorithm as well.



                                                              Best of luck!







                                                              share|improve this answer












                                                              share|improve this answer



                                                              share|improve this answer










                                                              answered Jul 6 '10 at 7:39









                                                              mattbastamattbasta

                                                              10.3k73763




                                                              10.3k73763








                                                              • 1





                                                                Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                                – Telanor
                                                                Jul 6 '10 at 20:42











                                                              • Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                                – Nestor
                                                                Mar 21 '11 at 1:20














                                                              • 1





                                                                Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                                – Telanor
                                                                Jul 6 '10 at 20:42











                                                              • Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                                – Nestor
                                                                Mar 21 '11 at 1:20








                                                              1




                                                              1





                                                              Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                              – Telanor
                                                              Jul 6 '10 at 20:42





                                                              Setting the width or height of a canvas via the HTML attributes causes the canvas to be cleared, so there cant be any resizing done with that method. Also, SVG is meant for dealing with mathematical images. I need to be able to draw PNGs and such, so that wont help me out there.

                                                              – Telanor
                                                              Jul 6 '10 at 20:42













                                                              Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                              – Nestor
                                                              Mar 21 '11 at 1:20





                                                              Setting the height & width of the canvas and resizing using CSS doesn't help, I've found (in Chrome). Even doing the resize using -webkit-transform rather than CSS width/height doesn't get the interpolation going.

                                                              – Nestor
                                                              Mar 21 '11 at 1:20











                                                              2














                                                              I have a feeling the module I wrote will produce similar results to photoshop, as it preserves color data by averaging them, not applying an algorithm. It's kind of slow, but to me it is the best, because it preserves all the color data.



                                                              https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js



                                                              It doesn't take the nearest neighbor and drop other pixels, or sample a group and take a random average. It takes the exact proportion each source pixel should output into the destination pixel. The average pixel color in the source will be the average pixel color in the destination, which these other formulas, I think they will not be.



                                                              an example of how to use is at the bottom of
                                                              https://github.com/danschumann/limby-resize



                                                              UPDATE OCT 2018: These days my example is more academic than anything else. Webgl is pretty much 100%, so you'd be better off resizing with that to produce similar results, but faster. PICA.js does this, I believe. –






                                                              share|improve this answer






























                                                                2














                                                                I have a feeling the module I wrote will produce similar results to photoshop, as it preserves color data by averaging them, not applying an algorithm. It's kind of slow, but to me it is the best, because it preserves all the color data.



                                                                https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js



                                                                It doesn't take the nearest neighbor and drop other pixels, or sample a group and take a random average. It takes the exact proportion each source pixel should output into the destination pixel. The average pixel color in the source will be the average pixel color in the destination, which these other formulas, I think they will not be.



                                                                an example of how to use is at the bottom of
                                                                https://github.com/danschumann/limby-resize



                                                                UPDATE OCT 2018: These days my example is more academic than anything else. Webgl is pretty much 100%, so you'd be better off resizing with that to produce similar results, but faster. PICA.js does this, I believe. –






                                                                share|improve this answer




























                                                                  2












                                                                  2








                                                                  2







                                                                  I have a feeling the module I wrote will produce similar results to photoshop, as it preserves color data by averaging them, not applying an algorithm. It's kind of slow, but to me it is the best, because it preserves all the color data.



                                                                  https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js



                                                                  It doesn't take the nearest neighbor and drop other pixels, or sample a group and take a random average. It takes the exact proportion each source pixel should output into the destination pixel. The average pixel color in the source will be the average pixel color in the destination, which these other formulas, I think they will not be.



                                                                  an example of how to use is at the bottom of
                                                                  https://github.com/danschumann/limby-resize



                                                                  UPDATE OCT 2018: These days my example is more academic than anything else. Webgl is pretty much 100%, so you'd be better off resizing with that to produce similar results, but faster. PICA.js does this, I believe. –






                                                                  share|improve this answer















                                                                  I have a feeling the module I wrote will produce similar results to photoshop, as it preserves color data by averaging them, not applying an algorithm. It's kind of slow, but to me it is the best, because it preserves all the color data.



                                                                  https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js



                                                                  It doesn't take the nearest neighbor and drop other pixels, or sample a group and take a random average. It takes the exact proportion each source pixel should output into the destination pixel. The average pixel color in the source will be the average pixel color in the destination, which these other formulas, I think they will not be.



                                                                  an example of how to use is at the bottom of
                                                                  https://github.com/danschumann/limby-resize



                                                                  UPDATE OCT 2018: These days my example is more academic than anything else. Webgl is pretty much 100%, so you'd be better off resizing with that to produce similar results, but faster. PICA.js does this, I believe. –







                                                                  share|improve this answer














                                                                  share|improve this answer



                                                                  share|improve this answer








                                                                  edited Oct 18 '18 at 0:07

























                                                                  answered Jul 30 '14 at 20:03









                                                                  FunkodebatFunkodebat

                                                                  3,47432448




                                                                  3,47432448























                                                                      1














                                                                      I converted @syockit's answer as well as the step-down approach into a reusable Angular service for anyone who's interested: https://gist.github.com/fisch0920/37bac5e741eaec60e983



                                                                      I included both solutions because they both have their own pros / cons. The lanczos convolution approach is higher quality at the cost of being slower, whereas the step-wise downscaling approach produces reasonably antialiased results and is significantly faster.



                                                                      Example usage:



                                                                      angular.module('demo').controller('ExampleCtrl', function (imageService) {
                                                                      // EXAMPLE USAGE
                                                                      // NOTE: it's bad practice to access the DOM inside a controller,
                                                                      // but this is just to show the example usage.

                                                                      // resize by lanczos-sinc filter
                                                                      imageService.resize($('#myimg')[0], 256, 256)
                                                                      .then(function (resizedImage) {
                                                                      // do something with resized image
                                                                      })

                                                                      // resize by stepping down image size in increments of 2x
                                                                      imageService.resizeStep($('#myimg')[0], 256, 256)
                                                                      .then(function (resizedImage) {
                                                                      // do something with resized image
                                                                      })
                                                                      })





                                                                      share|improve this answer






























                                                                        1














                                                                        I converted @syockit's answer as well as the step-down approach into a reusable Angular service for anyone who's interested: https://gist.github.com/fisch0920/37bac5e741eaec60e983



                                                                        I included both solutions because they both have their own pros / cons. The lanczos convolution approach is higher quality at the cost of being slower, whereas the step-wise downscaling approach produces reasonably antialiased results and is significantly faster.



                                                                        Example usage:



                                                                        angular.module('demo').controller('ExampleCtrl', function (imageService) {
                                                                        // EXAMPLE USAGE
                                                                        // NOTE: it's bad practice to access the DOM inside a controller,
                                                                        // but this is just to show the example usage.

                                                                        // resize by lanczos-sinc filter
                                                                        imageService.resize($('#myimg')[0], 256, 256)
                                                                        .then(function (resizedImage) {
                                                                        // do something with resized image
                                                                        })

                                                                        // resize by stepping down image size in increments of 2x
                                                                        imageService.resizeStep($('#myimg')[0], 256, 256)
                                                                        .then(function (resizedImage) {
                                                                        // do something with resized image
                                                                        })
                                                                        })





                                                                        share|improve this answer




























                                                                          1












                                                                          1








                                                                          1







                                                                          I converted @syockit's answer as well as the step-down approach into a reusable Angular service for anyone who's interested: https://gist.github.com/fisch0920/37bac5e741eaec60e983



                                                                          I included both solutions because they both have their own pros / cons. The lanczos convolution approach is higher quality at the cost of being slower, whereas the step-wise downscaling approach produces reasonably antialiased results and is significantly faster.



                                                                          Example usage:



                                                                          angular.module('demo').controller('ExampleCtrl', function (imageService) {
                                                                          // EXAMPLE USAGE
                                                                          // NOTE: it's bad practice to access the DOM inside a controller,
                                                                          // but this is just to show the example usage.

                                                                          // resize by lanczos-sinc filter
                                                                          imageService.resize($('#myimg')[0], 256, 256)
                                                                          .then(function (resizedImage) {
                                                                          // do something with resized image
                                                                          })

                                                                          // resize by stepping down image size in increments of 2x
                                                                          imageService.resizeStep($('#myimg')[0], 256, 256)
                                                                          .then(function (resizedImage) {
                                                                          // do something with resized image
                                                                          })
                                                                          })





                                                                          share|improve this answer















                                                                          I converted @syockit's answer as well as the step-down approach into a reusable Angular service for anyone who's interested: https://gist.github.com/fisch0920/37bac5e741eaec60e983



                                                                          I included both solutions because they both have their own pros / cons. The lanczos convolution approach is higher quality at the cost of being slower, whereas the step-wise downscaling approach produces reasonably antialiased results and is significantly faster.



                                                                          Example usage:



                                                                          angular.module('demo').controller('ExampleCtrl', function (imageService) {
                                                                          // EXAMPLE USAGE
                                                                          // NOTE: it's bad practice to access the DOM inside a controller,
                                                                          // but this is just to show the example usage.

                                                                          // resize by lanczos-sinc filter
                                                                          imageService.resize($('#myimg')[0], 256, 256)
                                                                          .then(function (resizedImage) {
                                                                          // do something with resized image
                                                                          })

                                                                          // resize by stepping down image size in increments of 2x
                                                                          imageService.resizeStep($('#myimg')[0], 256, 256)
                                                                          .then(function (resizedImage) {
                                                                          // do something with resized image
                                                                          })
                                                                          })






                                                                          share|improve this answer














                                                                          share|improve this answer



                                                                          share|improve this answer








                                                                          edited Sep 16 '14 at 23:39

























                                                                          answered Sep 16 '14 at 23:17









                                                                          fisch2fisch2

                                                                          1,09611318




                                                                          1,09611318























                                                                              1














                                                                              Fast and simple Javascript image resizer:



                                                                              https://github.com/calvintwr/Hermite-resize



                                                                              Use:



                                                                              h.resize({
                                                                              source: document.getElementById('image'), // any canvas or image elements, jQuery or native
                                                                              width: 400,
                                                                              height: 600,
                                                                              output: 'image', // [optional] `image` or `canvas`. If not entered output is same as input element.
                                                                              quality: 0.7, // [optional] applicable for `image` output only
                                                                              }, function(output) {
                                                                              //your callback
                                                                              });


                                                                              History



                                                                              This is really after many rounds of research, reading and trying.



                                                                              The resizer algorithm uses @ViliusL's Hermite script (Hermite resizer is really the fastest and gives reasonably good output). Extended with features you need.



                                                                              Forks 1 worker to do the resizing so that it doesn't freeze your browser when resizing, unlike all other JS resizers out there.






                                                                              share|improve this answer






























                                                                                1














                                                                                Fast and simple Javascript image resizer:



                                                                                https://github.com/calvintwr/Hermite-resize



                                                                                Use:



                                                                                h.resize({
                                                                                source: document.getElementById('image'), // any canvas or image elements, jQuery or native
                                                                                width: 400,
                                                                                height: 600,
                                                                                output: 'image', // [optional] `image` or `canvas`. If not entered output is same as input element.
                                                                                quality: 0.7, // [optional] applicable for `image` output only
                                                                                }, function(output) {
                                                                                //your callback
                                                                                });


                                                                                History



                                                                                This is really after many rounds of research, reading and trying.



                                                                                The resizer algorithm uses @ViliusL's Hermite script (Hermite resizer is really the fastest and gives reasonably good output). Extended with features you need.



                                                                                Forks 1 worker to do the resizing so that it doesn't freeze your browser when resizing, unlike all other JS resizers out there.






                                                                                share|improve this answer




























                                                                                  1












                                                                                  1








                                                                                  1







                                                                                  Fast and simple Javascript image resizer:



                                                                                  https://github.com/calvintwr/Hermite-resize



                                                                                  Use:



                                                                                  h.resize({
                                                                                  source: document.getElementById('image'), // any canvas or image elements, jQuery or native
                                                                                  width: 400,
                                                                                  height: 600,
                                                                                  output: 'image', // [optional] `image` or `canvas`. If not entered output is same as input element.
                                                                                  quality: 0.7, // [optional] applicable for `image` output only
                                                                                  }, function(output) {
                                                                                  //your callback
                                                                                  });


                                                                                  History



                                                                                  This is really after many rounds of research, reading and trying.



                                                                                  The resizer algorithm uses @ViliusL's Hermite script (Hermite resizer is really the fastest and gives reasonably good output). Extended with features you need.



                                                                                  Forks 1 worker to do the resizing so that it doesn't freeze your browser when resizing, unlike all other JS resizers out there.






                                                                                  share|improve this answer















                                                                                  Fast and simple Javascript image resizer:



                                                                                  https://github.com/calvintwr/Hermite-resize



                                                                                  Use:



                                                                                  h.resize({
                                                                                  source: document.getElementById('image'), // any canvas or image elements, jQuery or native
                                                                                  width: 400,
                                                                                  height: 600,
                                                                                  output: 'image', // [optional] `image` or `canvas`. If not entered output is same as input element.
                                                                                  quality: 0.7, // [optional] applicable for `image` output only
                                                                                  }, function(output) {
                                                                                  //your callback
                                                                                  });


                                                                                  History



                                                                                  This is really after many rounds of research, reading and trying.



                                                                                  The resizer algorithm uses @ViliusL's Hermite script (Hermite resizer is really the fastest and gives reasonably good output). Extended with features you need.



                                                                                  Forks 1 worker to do the resizing so that it doesn't freeze your browser when resizing, unlike all other JS resizers out there.







                                                                                  share|improve this answer














                                                                                  share|improve this answer



                                                                                  share|improve this answer








                                                                                  edited Dec 13 '15 at 7:38

























                                                                                  answered Dec 10 '15 at 17:16









                                                                                  CalvintwrCalvintwr

                                                                                  4,89122029




                                                                                  4,89122029























                                                                                      0














                                                                                      Thanks @syockit for an awesome answer. however, I had to reformat a little as follows to make it work. Perhaps due to DOM scanning issues:



                                                                                      $(document).ready(function () {

                                                                                      $('img').on("load", clickA);
                                                                                      function clickA() {
                                                                                      var img = this;
                                                                                      var canvas = document.createElement("canvas");
                                                                                      new thumbnailer(canvas, img, 50, 3);
                                                                                      document.body.appendChild(canvas);
                                                                                      }

                                                                                      function thumbnailer(elem, img, sx, lobes) {
                                                                                      this.canvas = elem;
                                                                                      elem.width = img.width;
                                                                                      elem.height = img.height;
                                                                                      elem.style.display = "none";
                                                                                      this.ctx = elem.getContext("2d");
                                                                                      this.ctx.drawImage(img, 0, 0);
                                                                                      this.img = img;
                                                                                      this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                                                                                      this.dest = {
                                                                                      width: sx,
                                                                                      height: Math.round(img.height * sx / img.width)
                                                                                      };
                                                                                      this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                                                                                      this.lanczos = lanczosCreate(lobes);
                                                                                      this.ratio = img.width / sx;
                                                                                      this.rcp_ratio = 2 / this.ratio;
                                                                                      this.range2 = Math.ceil(this.ratio * lobes / 2);
                                                                                      this.cacheLanc = {};
                                                                                      this.center = {};
                                                                                      this.icenter = {};
                                                                                      setTimeout(process1, 0, this, 0);
                                                                                      }

                                                                                      //returns a function that calculates lanczos weight
                                                                                      function lanczosCreate(lobes) {
                                                                                      return function (x) {
                                                                                      if (x > lobes)
                                                                                      return 0;
                                                                                      x *= Math.PI;
                                                                                      if (Math.abs(x) < 1e-16)
                                                                                      return 1
                                                                                      var xx = x / lobes;
                                                                                      return Math.sin(x) * Math.sin(xx) / x / xx;
                                                                                      }
                                                                                      }

                                                                                      process1 = function (self, u) {
                                                                                      self.center.x = (u + 0.5) * self.ratio;
                                                                                      self.icenter.x = Math.floor(self.center.x);
                                                                                      for (var v = 0; v < self.dest.height; v++) {
                                                                                      self.center.y = (v + 0.5) * self.ratio;
                                                                                      self.icenter.y = Math.floor(self.center.y);
                                                                                      var a, r, g, b;
                                                                                      a = r = g = b = 0;
                                                                                      for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                                                                                      if (i < 0 || i >= self.src.width)
                                                                                      continue;
                                                                                      var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                                                                                      if (!self.cacheLanc[f_x])
                                                                                      self.cacheLanc[f_x] = {};
                                                                                      for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                                                                                      if (j < 0 || j >= self.src.height)
                                                                                      continue;
                                                                                      var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                                                                                      if (self.cacheLanc[f_x][f_y] == undefined)
                                                                                      self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                                                                                      weight = self.cacheLanc[f_x][f_y];
                                                                                      if (weight > 0) {
                                                                                      var idx = (j * self.src.width + i) * 4;
                                                                                      a += weight;
                                                                                      r += weight * self.src.data[idx];
                                                                                      g += weight * self.src.data[idx + 1];
                                                                                      b += weight * self.src.data[idx + 2];
                                                                                      }
                                                                                      }
                                                                                      }
                                                                                      var idx = (v * self.dest.width + u) * 3;
                                                                                      self.dest.data[idx] = r / a;
                                                                                      self.dest.data[idx + 1] = g / a;
                                                                                      self.dest.data[idx + 2] = b / a;
                                                                                      }

                                                                                      if (++u < self.dest.width)
                                                                                      setTimeout(process1, 0, self, u);
                                                                                      else
                                                                                      setTimeout(process2, 0, self);
                                                                                      };

                                                                                      process2 = function (self) {
                                                                                      self.canvas.width = self.dest.width;
                                                                                      self.canvas.height = self.dest.height;
                                                                                      self.ctx.drawImage(self.img, 0, 0);
                                                                                      self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                                                                                      var idx, idx2;
                                                                                      for (var i = 0; i < self.dest.width; i++) {
                                                                                      for (var j = 0; j < self.dest.height; j++) {
                                                                                      idx = (j * self.dest.width + i) * 3;
                                                                                      idx2 = (j * self.dest.width + i) * 4;
                                                                                      self.src.data[idx2] = self.dest.data[idx];
                                                                                      self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                                                                                      self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                                                                                      }
                                                                                      }
                                                                                      self.ctx.putImageData(self.src, 0, 0);
                                                                                      self.canvas.style.display = "block";
                                                                                      }
                                                                                      });





                                                                                      share|improve this answer






























                                                                                        0














                                                                                        Thanks @syockit for an awesome answer. however, I had to reformat a little as follows to make it work. Perhaps due to DOM scanning issues:



                                                                                        $(document).ready(function () {

                                                                                        $('img').on("load", clickA);
                                                                                        function clickA() {
                                                                                        var img = this;
                                                                                        var canvas = document.createElement("canvas");
                                                                                        new thumbnailer(canvas, img, 50, 3);
                                                                                        document.body.appendChild(canvas);
                                                                                        }

                                                                                        function thumbnailer(elem, img, sx, lobes) {
                                                                                        this.canvas = elem;
                                                                                        elem.width = img.width;
                                                                                        elem.height = img.height;
                                                                                        elem.style.display = "none";
                                                                                        this.ctx = elem.getContext("2d");
                                                                                        this.ctx.drawImage(img, 0, 0);
                                                                                        this.img = img;
                                                                                        this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                                                                                        this.dest = {
                                                                                        width: sx,
                                                                                        height: Math.round(img.height * sx / img.width)
                                                                                        };
                                                                                        this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                                                                                        this.lanczos = lanczosCreate(lobes);
                                                                                        this.ratio = img.width / sx;
                                                                                        this.rcp_ratio = 2 / this.ratio;
                                                                                        this.range2 = Math.ceil(this.ratio * lobes / 2);
                                                                                        this.cacheLanc = {};
                                                                                        this.center = {};
                                                                                        this.icenter = {};
                                                                                        setTimeout(process1, 0, this, 0);
                                                                                        }

                                                                                        //returns a function that calculates lanczos weight
                                                                                        function lanczosCreate(lobes) {
                                                                                        return function (x) {
                                                                                        if (x > lobes)
                                                                                        return 0;
                                                                                        x *= Math.PI;
                                                                                        if (Math.abs(x) < 1e-16)
                                                                                        return 1
                                                                                        var xx = x / lobes;
                                                                                        return Math.sin(x) * Math.sin(xx) / x / xx;
                                                                                        }
                                                                                        }

                                                                                        process1 = function (self, u) {
                                                                                        self.center.x = (u + 0.5) * self.ratio;
                                                                                        self.icenter.x = Math.floor(self.center.x);
                                                                                        for (var v = 0; v < self.dest.height; v++) {
                                                                                        self.center.y = (v + 0.5) * self.ratio;
                                                                                        self.icenter.y = Math.floor(self.center.y);
                                                                                        var a, r, g, b;
                                                                                        a = r = g = b = 0;
                                                                                        for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                                                                                        if (i < 0 || i >= self.src.width)
                                                                                        continue;
                                                                                        var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                                                                                        if (!self.cacheLanc[f_x])
                                                                                        self.cacheLanc[f_x] = {};
                                                                                        for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                                                                                        if (j < 0 || j >= self.src.height)
                                                                                        continue;
                                                                                        var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                                                                                        if (self.cacheLanc[f_x][f_y] == undefined)
                                                                                        self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                                                                                        weight = self.cacheLanc[f_x][f_y];
                                                                                        if (weight > 0) {
                                                                                        var idx = (j * self.src.width + i) * 4;
                                                                                        a += weight;
                                                                                        r += weight * self.src.data[idx];
                                                                                        g += weight * self.src.data[idx + 1];
                                                                                        b += weight * self.src.data[idx + 2];
                                                                                        }
                                                                                        }
                                                                                        }
                                                                                        var idx = (v * self.dest.width + u) * 3;
                                                                                        self.dest.data[idx] = r / a;
                                                                                        self.dest.data[idx + 1] = g / a;
                                                                                        self.dest.data[idx + 2] = b / a;
                                                                                        }

                                                                                        if (++u < self.dest.width)
                                                                                        setTimeout(process1, 0, self, u);
                                                                                        else
                                                                                        setTimeout(process2, 0, self);
                                                                                        };

                                                                                        process2 = function (self) {
                                                                                        self.canvas.width = self.dest.width;
                                                                                        self.canvas.height = self.dest.height;
                                                                                        self.ctx.drawImage(self.img, 0, 0);
                                                                                        self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                                                                                        var idx, idx2;
                                                                                        for (var i = 0; i < self.dest.width; i++) {
                                                                                        for (var j = 0; j < self.dest.height; j++) {
                                                                                        idx = (j * self.dest.width + i) * 3;
                                                                                        idx2 = (j * self.dest.width + i) * 4;
                                                                                        self.src.data[idx2] = self.dest.data[idx];
                                                                                        self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                                                                                        self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                                                                                        }
                                                                                        }
                                                                                        self.ctx.putImageData(self.src, 0, 0);
                                                                                        self.canvas.style.display = "block";
                                                                                        }
                                                                                        });





                                                                                        share|improve this answer




























                                                                                          0












                                                                                          0








                                                                                          0







                                                                                          Thanks @syockit for an awesome answer. however, I had to reformat a little as follows to make it work. Perhaps due to DOM scanning issues:



                                                                                          $(document).ready(function () {

                                                                                          $('img').on("load", clickA);
                                                                                          function clickA() {
                                                                                          var img = this;
                                                                                          var canvas = document.createElement("canvas");
                                                                                          new thumbnailer(canvas, img, 50, 3);
                                                                                          document.body.appendChild(canvas);
                                                                                          }

                                                                                          function thumbnailer(elem, img, sx, lobes) {
                                                                                          this.canvas = elem;
                                                                                          elem.width = img.width;
                                                                                          elem.height = img.height;
                                                                                          elem.style.display = "none";
                                                                                          this.ctx = elem.getContext("2d");
                                                                                          this.ctx.drawImage(img, 0, 0);
                                                                                          this.img = img;
                                                                                          this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                                                                                          this.dest = {
                                                                                          width: sx,
                                                                                          height: Math.round(img.height * sx / img.width)
                                                                                          };
                                                                                          this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                                                                                          this.lanczos = lanczosCreate(lobes);
                                                                                          this.ratio = img.width / sx;
                                                                                          this.rcp_ratio = 2 / this.ratio;
                                                                                          this.range2 = Math.ceil(this.ratio * lobes / 2);
                                                                                          this.cacheLanc = {};
                                                                                          this.center = {};
                                                                                          this.icenter = {};
                                                                                          setTimeout(process1, 0, this, 0);
                                                                                          }

                                                                                          //returns a function that calculates lanczos weight
                                                                                          function lanczosCreate(lobes) {
                                                                                          return function (x) {
                                                                                          if (x > lobes)
                                                                                          return 0;
                                                                                          x *= Math.PI;
                                                                                          if (Math.abs(x) < 1e-16)
                                                                                          return 1
                                                                                          var xx = x / lobes;
                                                                                          return Math.sin(x) * Math.sin(xx) / x / xx;
                                                                                          }
                                                                                          }

                                                                                          process1 = function (self, u) {
                                                                                          self.center.x = (u + 0.5) * self.ratio;
                                                                                          self.icenter.x = Math.floor(self.center.x);
                                                                                          for (var v = 0; v < self.dest.height; v++) {
                                                                                          self.center.y = (v + 0.5) * self.ratio;
                                                                                          self.icenter.y = Math.floor(self.center.y);
                                                                                          var a, r, g, b;
                                                                                          a = r = g = b = 0;
                                                                                          for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                                                                                          if (i < 0 || i >= self.src.width)
                                                                                          continue;
                                                                                          var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                                                                                          if (!self.cacheLanc[f_x])
                                                                                          self.cacheLanc[f_x] = {};
                                                                                          for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                                                                                          if (j < 0 || j >= self.src.height)
                                                                                          continue;
                                                                                          var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                                                                                          if (self.cacheLanc[f_x][f_y] == undefined)
                                                                                          self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                                                                                          weight = self.cacheLanc[f_x][f_y];
                                                                                          if (weight > 0) {
                                                                                          var idx = (j * self.src.width + i) * 4;
                                                                                          a += weight;
                                                                                          r += weight * self.src.data[idx];
                                                                                          g += weight * self.src.data[idx + 1];
                                                                                          b += weight * self.src.data[idx + 2];
                                                                                          }
                                                                                          }
                                                                                          }
                                                                                          var idx = (v * self.dest.width + u) * 3;
                                                                                          self.dest.data[idx] = r / a;
                                                                                          self.dest.data[idx + 1] = g / a;
                                                                                          self.dest.data[idx + 2] = b / a;
                                                                                          }

                                                                                          if (++u < self.dest.width)
                                                                                          setTimeout(process1, 0, self, u);
                                                                                          else
                                                                                          setTimeout(process2, 0, self);
                                                                                          };

                                                                                          process2 = function (self) {
                                                                                          self.canvas.width = self.dest.width;
                                                                                          self.canvas.height = self.dest.height;
                                                                                          self.ctx.drawImage(self.img, 0, 0);
                                                                                          self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                                                                                          var idx, idx2;
                                                                                          for (var i = 0; i < self.dest.width; i++) {
                                                                                          for (var j = 0; j < self.dest.height; j++) {
                                                                                          idx = (j * self.dest.width + i) * 3;
                                                                                          idx2 = (j * self.dest.width + i) * 4;
                                                                                          self.src.data[idx2] = self.dest.data[idx];
                                                                                          self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                                                                                          self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                                                                                          }
                                                                                          }
                                                                                          self.ctx.putImageData(self.src, 0, 0);
                                                                                          self.canvas.style.display = "block";
                                                                                          }
                                                                                          });





                                                                                          share|improve this answer















                                                                                          Thanks @syockit for an awesome answer. however, I had to reformat a little as follows to make it work. Perhaps due to DOM scanning issues:



                                                                                          $(document).ready(function () {

                                                                                          $('img').on("load", clickA);
                                                                                          function clickA() {
                                                                                          var img = this;
                                                                                          var canvas = document.createElement("canvas");
                                                                                          new thumbnailer(canvas, img, 50, 3);
                                                                                          document.body.appendChild(canvas);
                                                                                          }

                                                                                          function thumbnailer(elem, img, sx, lobes) {
                                                                                          this.canvas = elem;
                                                                                          elem.width = img.width;
                                                                                          elem.height = img.height;
                                                                                          elem.style.display = "none";
                                                                                          this.ctx = elem.getContext("2d");
                                                                                          this.ctx.drawImage(img, 0, 0);
                                                                                          this.img = img;
                                                                                          this.src = this.ctx.getImageData(0, 0, img.width, img.height);
                                                                                          this.dest = {
                                                                                          width: sx,
                                                                                          height: Math.round(img.height * sx / img.width)
                                                                                          };
                                                                                          this.dest.data = new Array(this.dest.width * this.dest.height * 3);
                                                                                          this.lanczos = lanczosCreate(lobes);
                                                                                          this.ratio = img.width / sx;
                                                                                          this.rcp_ratio = 2 / this.ratio;
                                                                                          this.range2 = Math.ceil(this.ratio * lobes / 2);
                                                                                          this.cacheLanc = {};
                                                                                          this.center = {};
                                                                                          this.icenter = {};
                                                                                          setTimeout(process1, 0, this, 0);
                                                                                          }

                                                                                          //returns a function that calculates lanczos weight
                                                                                          function lanczosCreate(lobes) {
                                                                                          return function (x) {
                                                                                          if (x > lobes)
                                                                                          return 0;
                                                                                          x *= Math.PI;
                                                                                          if (Math.abs(x) < 1e-16)
                                                                                          return 1
                                                                                          var xx = x / lobes;
                                                                                          return Math.sin(x) * Math.sin(xx) / x / xx;
                                                                                          }
                                                                                          }

                                                                                          process1 = function (self, u) {
                                                                                          self.center.x = (u + 0.5) * self.ratio;
                                                                                          self.icenter.x = Math.floor(self.center.x);
                                                                                          for (var v = 0; v < self.dest.height; v++) {
                                                                                          self.center.y = (v + 0.5) * self.ratio;
                                                                                          self.icenter.y = Math.floor(self.center.y);
                                                                                          var a, r, g, b;
                                                                                          a = r = g = b = 0;
                                                                                          for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
                                                                                          if (i < 0 || i >= self.src.width)
                                                                                          continue;
                                                                                          var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
                                                                                          if (!self.cacheLanc[f_x])
                                                                                          self.cacheLanc[f_x] = {};
                                                                                          for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                                                                                          if (j < 0 || j >= self.src.height)
                                                                                          continue;
                                                                                          var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                                                                                          if (self.cacheLanc[f_x][f_y] == undefined)
                                                                                          self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                                                                                          weight = self.cacheLanc[f_x][f_y];
                                                                                          if (weight > 0) {
                                                                                          var idx = (j * self.src.width + i) * 4;
                                                                                          a += weight;
                                                                                          r += weight * self.src.data[idx];
                                                                                          g += weight * self.src.data[idx + 1];
                                                                                          b += weight * self.src.data[idx + 2];
                                                                                          }
                                                                                          }
                                                                                          }
                                                                                          var idx = (v * self.dest.width + u) * 3;
                                                                                          self.dest.data[idx] = r / a;
                                                                                          self.dest.data[idx + 1] = g / a;
                                                                                          self.dest.data[idx + 2] = b / a;
                                                                                          }

                                                                                          if (++u < self.dest.width)
                                                                                          setTimeout(process1, 0, self, u);
                                                                                          else
                                                                                          setTimeout(process2, 0, self);
                                                                                          };

                                                                                          process2 = function (self) {
                                                                                          self.canvas.width = self.dest.width;
                                                                                          self.canvas.height = self.dest.height;
                                                                                          self.ctx.drawImage(self.img, 0, 0);
                                                                                          self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
                                                                                          var idx, idx2;
                                                                                          for (var i = 0; i < self.dest.width; i++) {
                                                                                          for (var j = 0; j < self.dest.height; j++) {
                                                                                          idx = (j * self.dest.width + i) * 3;
                                                                                          idx2 = (j * self.dest.width + i) * 4;
                                                                                          self.src.data[idx2] = self.dest.data[idx];
                                                                                          self.src.data[idx2 + 1] = self.dest.data[idx + 1];
                                                                                          self.src.data[idx2 + 2] = self.dest.data[idx + 2];
                                                                                          }
                                                                                          }
                                                                                          self.ctx.putImageData(self.src, 0, 0);
                                                                                          self.canvas.style.display = "block";
                                                                                          }
                                                                                          });






                                                                                          share|improve this answer














                                                                                          share|improve this answer



                                                                                          share|improve this answer








                                                                                          edited Feb 3 '18 at 20:35









                                                                                          AvrilAlejandro

                                                                                          3,32122131




                                                                                          3,32122131










                                                                                          answered Aug 14 '13 at 0:51









                                                                                          ManishManish

                                                                                          60511016




                                                                                          60511016























                                                                                              -1














                                                                                              I just ran a page of side by sides comparisons and unless something has changed recently, I could see no better downsizing (scaling) using canvas vs. simple css. I tested in FF6 Mac OSX 10.7. Still slightly soft vs. the original.



                                                                                              I did however stumble upon something that did make a huge difference and that was using image filters in browsers that support canvas. You can actually manipulate images much like you can in Photoshop with blur, sharpen, saturation, ripple, grayscale, etc.



                                                                                              I then found an awesome jQuery plug-in which makes application of these filters a snap:
                                                                                              http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234



                                                                                              I simply apply the sharpen filter right after resizing the image which should give you the desired effect. I didn't even have to use a canvas element.






                                                                                              share|improve this answer




























                                                                                                -1














                                                                                                I just ran a page of side by sides comparisons and unless something has changed recently, I could see no better downsizing (scaling) using canvas vs. simple css. I tested in FF6 Mac OSX 10.7. Still slightly soft vs. the original.



                                                                                                I did however stumble upon something that did make a huge difference and that was using image filters in browsers that support canvas. You can actually manipulate images much like you can in Photoshop with blur, sharpen, saturation, ripple, grayscale, etc.



                                                                                                I then found an awesome jQuery plug-in which makes application of these filters a snap:
                                                                                                http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234



                                                                                                I simply apply the sharpen filter right after resizing the image which should give you the desired effect. I didn't even have to use a canvas element.






                                                                                                share|improve this answer


























                                                                                                  -1












                                                                                                  -1








                                                                                                  -1







                                                                                                  I just ran a page of side by sides comparisons and unless something has changed recently, I could see no better downsizing (scaling) using canvas vs. simple css. I tested in FF6 Mac OSX 10.7. Still slightly soft vs. the original.



                                                                                                  I did however stumble upon something that did make a huge difference and that was using image filters in browsers that support canvas. You can actually manipulate images much like you can in Photoshop with blur, sharpen, saturation, ripple, grayscale, etc.



                                                                                                  I then found an awesome jQuery plug-in which makes application of these filters a snap:
                                                                                                  http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234



                                                                                                  I simply apply the sharpen filter right after resizing the image which should give you the desired effect. I didn't even have to use a canvas element.






                                                                                                  share|improve this answer













                                                                                                  I just ran a page of side by sides comparisons and unless something has changed recently, I could see no better downsizing (scaling) using canvas vs. simple css. I tested in FF6 Mac OSX 10.7. Still slightly soft vs. the original.



                                                                                                  I did however stumble upon something that did make a huge difference and that was using image filters in browsers that support canvas. You can actually manipulate images much like you can in Photoshop with blur, sharpen, saturation, ripple, grayscale, etc.



                                                                                                  I then found an awesome jQuery plug-in which makes application of these filters a snap:
                                                                                                  http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234



                                                                                                  I simply apply the sharpen filter right after resizing the image which should give you the desired effect. I didn't even have to use a canvas element.







                                                                                                  share|improve this answer












                                                                                                  share|improve this answer



                                                                                                  share|improve this answer










                                                                                                  answered Aug 24 '11 at 19:40









                                                                                                  Julian DormonJulian Dormon

                                                                                                  95632148




                                                                                                  95632148























                                                                                                      -1














                                                                                                      Looking for another great simple solution?



                                                                                                      var img=document.createElement('img');
                                                                                                      img.src=canvas.toDataURL();
                                                                                                      $(img).css("background", backgroundColor);
                                                                                                      $(img).width(settings.width);
                                                                                                      $(img).height(settings.height);


                                                                                                      This solution will use the resize algorith of browser! :)






                                                                                                      share|improve this answer
























                                                                                                      • The question is about downsampling the image, not just resizing it.

                                                                                                        – Jesús Carrera
                                                                                                        Aug 27 '14 at 13:49











                                                                                                      • [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                        – ale500
                                                                                                        Sep 3 '14 at 10:03
















                                                                                                      -1














                                                                                                      Looking for another great simple solution?



                                                                                                      var img=document.createElement('img');
                                                                                                      img.src=canvas.toDataURL();
                                                                                                      $(img).css("background", backgroundColor);
                                                                                                      $(img).width(settings.width);
                                                                                                      $(img).height(settings.height);


                                                                                                      This solution will use the resize algorith of browser! :)






                                                                                                      share|improve this answer
























                                                                                                      • The question is about downsampling the image, not just resizing it.

                                                                                                        – Jesús Carrera
                                                                                                        Aug 27 '14 at 13:49











                                                                                                      • [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                        – ale500
                                                                                                        Sep 3 '14 at 10:03














                                                                                                      -1












                                                                                                      -1








                                                                                                      -1







                                                                                                      Looking for another great simple solution?



                                                                                                      var img=document.createElement('img');
                                                                                                      img.src=canvas.toDataURL();
                                                                                                      $(img).css("background", backgroundColor);
                                                                                                      $(img).width(settings.width);
                                                                                                      $(img).height(settings.height);


                                                                                                      This solution will use the resize algorith of browser! :)






                                                                                                      share|improve this answer













                                                                                                      Looking for another great simple solution?



                                                                                                      var img=document.createElement('img');
                                                                                                      img.src=canvas.toDataURL();
                                                                                                      $(img).css("background", backgroundColor);
                                                                                                      $(img).width(settings.width);
                                                                                                      $(img).height(settings.height);


                                                                                                      This solution will use the resize algorith of browser! :)







                                                                                                      share|improve this answer












                                                                                                      share|improve this answer



                                                                                                      share|improve this answer










                                                                                                      answered Aug 20 '14 at 5:11









                                                                                                      ale500ale500

                                                                                                      235210




                                                                                                      235210













                                                                                                      • The question is about downsampling the image, not just resizing it.

                                                                                                        – Jesús Carrera
                                                                                                        Aug 27 '14 at 13:49











                                                                                                      • [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                        – ale500
                                                                                                        Sep 3 '14 at 10:03



















                                                                                                      • The question is about downsampling the image, not just resizing it.

                                                                                                        – Jesús Carrera
                                                                                                        Aug 27 '14 at 13:49











                                                                                                      • [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                        – ale500
                                                                                                        Sep 3 '14 at 10:03

















                                                                                                      The question is about downsampling the image, not just resizing it.

                                                                                                      – Jesús Carrera
                                                                                                      Aug 27 '14 at 13:49





                                                                                                      The question is about downsampling the image, not just resizing it.

                                                                                                      – Jesús Carrera
                                                                                                      Aug 27 '14 at 13:49













                                                                                                      [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                      – ale500
                                                                                                      Sep 3 '14 at 10:03





                                                                                                      [...] I'm trying to resize a jpg. I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized.[...] why you cannot use the <img> Jesus Carrera?

                                                                                                      – ale500
                                                                                                      Sep 3 '14 at 10:03





                                                                                                      protected by NullPoiиteя Jun 23 '13 at 10:13



                                                                                                      Thank you for your interest in this question.
                                                                                                      Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                      Would you like to answer one of these unanswered questions instead?



                                                                                                      Popular posts from this blog

                                                                                                      Contact image not getting when fetch all contact list from iPhone by CNContact

                                                                                                      count number of partitions of a set with n elements into k subsets

                                                                                                      A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks