15

We are capturing a visible tab in a Chrome browser (by using the extensions API chrome.tabs.captureVisibleTab) and receiving a snapshot in the data URI scheme (Base64 encoded string).

Is there a JavaScript library that can be used to scale down an image to a certain size?

Currently we are styling it via CSS, but have to pay performance penalties as pictures are mostly 100 times bigger than required. Additional concern is also the load on the localStorage we use to save our snapshots.

Does anyone know of a way to process this data URI scheme formatted pictures and reduce their size by scaling them down?

References:

Juha Syrjälä
  • 33,425
  • 31
  • 131
  • 183
Draško Kokić
  • 1,280
  • 1
  • 19
  • 34

2 Answers2

23

Here's a function that should do what you need. You give it the URL of an image (e.g. the result from chrome.tabs.captureVisibleTab, but it could be any URL), the desired size, and a callback. It executes asynchronously because there is no guarantee that the image will be loaded immediately when you set the src property. With a data URL it probably will since it doesn't need to download anything, but I haven't tried it.

The callback will be passed the resulting image as a data URL. Note that the resulting image will be a PNG, since Chrome's implementation of toDataURL doesn't support image/jpeg.

function resizeImage(url, width, height, callback) {
    var sourceImage = new Image();

    sourceImage.onload = function() {
        // Create a canvas with the desired dimensions
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;

        // Scale and draw the source image to the canvas
        canvas.getContext("2d").drawImage(sourceImage, 0, 0, width, height);

        // Convert the canvas to a data URL in PNG format
        callback(canvas.toDataURL());
    }

    sourceImage.src = url;
}
Matthew Crumley
  • 101,441
  • 24
  • 103
  • 129
  • Thanks Matthew, a very clean example ... I must have had too much bear the other night when I failed to get "exactly" the same working ... the only difference being that I used an existing canvas from HTML. – Draško Kokić Mar 27 '10 at 00:36
  • 2
    This also ONLY scales the Image and the Resultant `dataURL` is as Large as the one you would get without using `canvas.toDataURL()` (even if you have redrawn the `image` with new width and height :( ) – Om Shankar Sep 07 '12 at 13:26
  • Note if anyone finds sourceIMage.onload is not being called it means your input URL data is bad. For me I was using FileReader() and doing readAsBinaryString rather than readAsDataUrl. – bjm88 Apr 21 '15 at 19:21
  • This solution assumes that you won't be exceeding the max canvas size of your device. I'm looking for a way to accomplish this reliably on mobile devices. – Eric Gratta Feb 07 '21 at 17:04
2

As for the performance issues, maybe the canvas tag could help? https://developer.mozilla.org/en/Canvas_tutorial/Using_images#drawImage_example_2

If you load the image, display it with drawImage and then try to discard it, you may succeed. But I am not sure how to serialize a canvas as an image to save the resized file...

efi
  • 171
  • 6