19

I'm loading large images and having the browser resize them. I'm explicitly setting the size.

<img src="http://example.com/image1.jpg" width="240" height="360"/>

There are many such images on the page. Scrolling is very slow and choppy. The Events Timeline in chrome looks something like this when scrolling:

Paint

* Image decode (JPEG)
* Image resize (non-cached)
* Image decode (JPEG)
* Image resize (non-cached)
* ...

Paint

* Image resize (cached)
* Image resize (cached)
* Image resize (cached)
* Image resize (cached)

Paint

* Image decode (JPEG)
* Image resize (non-cached)
* Image decode (JPEG)
* Image resize (non-cached)
* ....

Paint

* Image resize (non-cached)
* Image resize (non-cached)
* Image resize (non-cached)
* Image resize (non-cached)

Paint

* Image decode (JPEG)
* Image resize (cached)
* Image decode (JPEG)
* Image resize (cached)
* ...

etc.

I'm not sure why some of the Paint events include image decoding and others don't, nor why sometimes the resizing is cached and sometimes it is not. I guess it must have to do with new images coming into the view-port.

Is there anything I can do to ensure that I only pay the image resize cost once per image when the page loads, and avoid image resizing during scroll?

(Of course, I understand that the best solution is to avoid browser resizing by loading in an image that is already of the appropriate size. In this case this is not practical.)

Joel
  • 11,431
  • 17
  • 62
  • 72
  • 1
    If you can rely on canvas, [you can use canvas to *really* resize the images](http://stackoverflow.com/questions/2303690/resizing-an-image-in-an-html5-canvas), instead of just scaling them. – Joseph Silber Jan 27 '13 at 04:13
  • 2
    Did you find a workaround? I'm seeing the same issue, no idea how to tackle it yet. – Mahn Feb 05 '13 at 00:42

4 Answers4

8

This function will permit you to resize an image only once, by replacing it with a new image resized at the desired scale :

function resizeImage(image, maxWidth, maxHeight) {

  // Output scale is the minimum of the two possible scales
  var scale = Math.min((maxWidth / image.width), (maxHeight / image.height))

  // Output canvas
  var outputCanvas = document.createElement('canvas')
  outputCanvas.width = image.width * scale
  outputCanvas.height = image.height * scale

  // Draw image content in output canvas
  var outputContext = outputCanvas.getContext('2d')
  outputContext.drawImage(image, 0, 0, parseInt(image.width * scale), parseInt(image.height * scale))

  // Replace image source
  image.src = outputCanvas.toDataURL()
}

It takes the image you pass as image parameter, and creates a canvas where it resizes image, and then sets the image.src attribute to the content of the output canvas, using toDataURL().

Images you resize have to be in RELATIVE path (yes it's not cool), or you will have security error due to CORS if not fulfilled.

But you can pass base64 data as src attribute, and it can be easy to do it with AJAX.

kube
  • 13,176
  • 9
  • 34
  • 38
1

Your problem is that you are downloading lots of images at the same time, lots of large images. The rendering of them to differnt sizes other than the orginal will also be slow if there are lots of large images and the users individual ram and processor limitations.

no matter what size you tell the browser to render the image the browser still loads the original image size and then adjusts it on the fly. The large image has to travel down the users internet connection to the browser from the server. by using html attributes all you are doing really is using CSS to change the image size once it has been downloaded.

Your best option would in mho be to create multiple image sizes server side, preferably at the time of creation of the asset rather than on the fly and call the image size closest to your needs. If you create images on the fly using scripts etc keep them on the server to use again later on and reduce load time and server resources.

one last tip is also make sure you are caching. more info here http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/

Orcra
  • 132
  • 9
0

CSS would help here. That would act as a default and may slow down individual load time. To achieve this just do basic css for images. Reference below:

 <img src="....." />

For your css you need the following code as an example:

 img {
height: 360;
width: 240;
}

Then you could add extra code to have rounded corners, border, or any effects you may want.

To avoid all resizing and this would of course help is to resize images in Photoshop. Then it would just show image and not render each image as different parts of the page are shown.

Patrick
  • 292
  • 1
  • 11
-1

large image takes more time to load to memory (RAM), even if the images already on memory (RAM) if there is huge memory consumption (too many large images or there is an application that takes large memory on background), invisible (outside of visible area) images get pushed to paging/swap file (on hard drive), so when the images come to visible area, browser would load that from paging/swap with hard drive speed (slow speed).

in this case, if you have many large images on one page, you cannot depend on client side resizing, because it would make your client browsing experience bad.

you should consider to resize your images on server side, either on demand, or pre-resized (thumbnail).

in case of on demand method, you could user Apache's mod_rewrite to point images to a script to resize and image that is beeing requested by your clients browser.

take a look at popular image sharing/hosting site, view a random image and copy its URL, paste it to another tab, and play with the URL by changing/removing some part of the URL. you can see that they dynamically resize the image on server side.

TLDR: you cannot have smooth scrolling with many large images on a page, either use thumbnails, or get choppy scrolling if you insist on not using thumbnails.

oh, there is one other thing to consider, that is increasing your (and your clients) RAM to handle such memory needs

am05mhz
  • 2,727
  • 2
  • 23
  • 37