Javascript images array preload speed and remove from memory - javascript

I have a asp.net MVC application where I display a number of image in a view, the number of these images rang between 100 to 2500 per group. On the view I preload the images for each group, then I select a different group from a dropdownlist, this will refresh the page. First preload works great, however, when I change the group it is very slow. The reference to these images are in a MS SQL database, the list of images for a particular gorup comes throught the controller (C#). Here is the Javascript I am using:
var impath = $("#ImagePath").val();
var im = $("#ImageName").val();
var images = null;
var images = [];
var tochar = $("#lastchar").val();
function preload_images() {
var i;
for (i = tochar; i < sl; i++) {
images[i] = new Image();
var name = impath.toString() + im.toString() + i;
}
}
My question is there is a way to speed up the preload process, and do I need to remove the preloaded images from the memory before loading the next group and how can I delete them, I used images=null, is this is the right way. Thanks in advance.

The best way to handle that many images would be using sprites. With sprites, you load one larger image that contains many, many smaller images. Since loading a single image is lot, lot faster in the browser than loading a lot of small images, your preloading can be a lot faster. In fact, you could literally just preload one image that contained a whole block of your sub-images.
Then, when you want to display one of those images, you display only a clipped portion of the image. There are a number of ways to do that display, but a common way is creating an object of the desired cell size and displaying the larger image as the background with the appropriate offset to line up with the desired part of the larger image.
Here's a useful reference on CSS and sprites: http://css-tricks.com/css-sprites/
You do have to create the appropriate sprites on the server side to use this technique.
In answer to some of your other questions.
No, you can't speed them up any more other than loading fewer images (as suggested above) or reducing the size of each image. The browser will only make N image requests at a time (likely to avoid overloading servers) over the network so the rest will be queued up until one finishes and then the next request will be made, etc...
You can release images from memory by just making sure that you aren't holding a reference to them any more. That way, the browser garbage collector will clean up the Image() objects that you had created. In your code setting images = null or images = [] will accomplish that as long as those Image() objects aren't referenced anywhere else. The images will still remain in the browser's cache and will still essentially be preloaded (they won't have to be loaded over the network if referenced again).

Related

Node-Webkit Application: Loading thousands of images from disk

I have created a node-webkit application that loads thousands of images (7,480 to be exact) from disk into an HTML table. After about 3500 images, the loading stops. In the console, I see ERR_INSUFFICIENT_RESOURCES. According to Task Manager, the memory (private working set) for my app is at around 1.37 GB when this happens. How can I prevent this from happening? Is there a way for me to increase this limit? What additional details should I provide to receive help?
In the past when i have faced a similar problem, i held the images in memory, and inserted them into the dom as they scrolled into view.
I created two queues one for images not the scroll down to, and one for images that have been scrolled past. this way only images that are visible are present in the page.
If the download time is an issue try loading them into memory and see what happens, there is a chance the limit you have encountered is about placing images in the dom, and not necessarily loading the images into memory, worth a try.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image
var myImage = new Image(100, 200);
myImage.src = 'picture.jpg';

preloading images into browser cache

I'm trying to make an image gallery that will show lots of art. Therefore the website will have lots of images. I noticed that when I viewed my code on another computer the images would take time to load. While on my computer they would display straight away and I guessing this is due to them already being cached.
So I did some looking around to see if I could prevent this and I found lots of people mentioning preloading images. However, I couldn't really find a solution that fits my desire or a explanation I could understand(I hate using code I don't understand). So I tried to have a go myself and it didn't work out, but I felt the logic I what I writing was right but needs tweaking I'm going to write my code below and any advice on what need to do next would be greatly appreciated.
Preloading images code:
var allImages = $(img).attr('src'); //select every image
var preloadImages = [];
//add images to empty array
for(var i = 0; i < allImages.length; i++ ) {
preloadImages.push(allImages[i]);
}
//then preload images
for(var i = 0; i < preloadImages.length; i++ ) {
new Image().src = preloadImages[i];
}
So that is the code I wrote to preload images on my page. Let me know where I'm going wrong. I'm really not sure how I go about selecting all images on my website and loading them into an array I can then cycle over?
Thanks for the responses I guess I didn't explain my problem that well. A lot of the solutions to preloading images seem to be manually typing in every image src into and array. What I was looking for was a way to select every image I have and then put them into an array without actually typing them in. Is that possible? My reason for that is when I keep adding more and more images it would be great if the preloading could just take care of itself.

Javascript - preloaded image is rendered late (only for the first time)

I use this code to preload an image:
var image = new Image();
image.addEventListener("load", loadHandler, false);
image.src = "someImage.png";
function loadHandler()
{
// the programme continues
}
Lets say the image refers to a certain button that occurs in the middle of a game.
The problem is that the code waits for a few seconds when the image should be rendered for the first time (using drawImage function). All the other usage (means the image should be shown another time) are instant.
The image is a sprite sheet, size about 3 MB. Everything on a local computer.
If I understand properly your issue, it's not about loading but more about rendering the sprite (which is quite big).
It might help to insert it into the document (wherever you want) and then wait for it to load before doing anything else.
You can hide it with the help of opacity, visibility, etc. properties (any choice should do the trick).
If your target browsers are supporting it, you could also use instead link prefetching.

How to read chunks of an image?

Many many sites uses this technique (facebook, google as well)
For example, open facebook.com
Save this page (not as *.MHTM but HTML with images) (mean login page)
It saves:
facebook_files(dir)
facebook.html(file)
Then inside the folder, You can see one GIF file which containts all primary images for the page.
The question is: How to read many chunks inside one file??
And how to call this approach?
Those images are called "sprites". Take a look a this article on them.
The basic idea is that whenever you want to use an image from the sprite, you have an element which just shows part of the big sprite image. So each "image" in your page is actually a div with this image as the background, just offset so the right part shows through.
The main advantage is that your page needs fewer requests and so loads faster.
There are some tools online that make using sprites easier. I haven't used any of them so can't recommend one, but using a tool would save you a lot of work.
This is what you call "spriting", like the spriting used in arcade games (one image of a character with it's different positions). Basically it's one huge chunk of image containing smaller images.
The advantage of this approach is that instead of 100 different HTTP requests for 100 tiny gifs (which causes overhead), you only need to request one huge image containing this 100 gifs. Then instead of using <img> per image, you use the CSS background instead, then use background-position to align the right image "through" the container to show the right image.

javascript memory leak with HTML5 getImageData

I've been working on trying to make some visual effects for a javascript game I'm creating, and I noticed a piece of code that I'm using to modulate the color of my sprites makes my browsers memory usage go up and up, seemingly without limit.
You can see the code and the memory leak here: http://timzook.tk/javascript/test.html
This memory leak only happens in my updateimage() function when I call getImageData from my canvas context every frame (via setInterval) in order to make a new ImageData object to recolor. I would have thought that javascript's garbage collector would be destroying the old one, but if not I have no idea how to destroy it manually. Any help figuring out why it does this or how to fix it would be appreciated.
My question is very similar to this one: What is leaking memory with this use of getImageData, javascript, HTML5 canvas However, I NEED my code to run every frame in the functioned called by setInterval, his solution of moving it outside the setInterval function isn't an option for me, and I can't leave a comment asking if he found some other method of solving it.
Note to people testing it out: Since this example uses getImageData, it can't be tested out locally just by throwing it in a .html file, a web server is required. Also it obviously uses HTML5 elements so some browsers won't work with it.
Edit: *SOLVED* Thanks, the solution below fixed it. I didn't realize that you could use a canvas element the same way as you could use an image in drawImage(), I restructured my code so it now uses significantly less memory. I uploaded this changed code to the page linked above, if anyone wants to see it.
You aren't getting a memory leak from your calls to getImageData(). The source of your problem is this line:
TempImg.src = ImgCanvas.toDataURL("image/png");
Effectively, every time that line of code is executed the browser "downloads" another image and stores it in memory. So, what you actually end up with is a cache that is growing very quickly. You can easily verify this by opening the site in Chrome and checking the resources tab of the developer tools (ctrl+shift+i).
You can work around this by making a TempImgCanvas and storing your image data on that canvas instead of keeping an image object updated after every call to your updateimage() loop.
I have to step away for a while, but I can work up an example in a few hours when I get back, if you would like.
Edit: I restructured things a bit and eliminated your caching issue. You just have to make two changes. The first is replacing your updateimage() function with this one:
function updateimage() {
var TempImgData = ImgContext.getImageData(0, 0, ImgCanvas.width, ImgCanvas.height);
var NewData = TempImgData.data;
var OrigData = ImgData.data;
//Change image color
var len = 4*ImgData.width*ImgData.height-1;
for(var i=0;i<=len;i+=4) {
NewData[i+0] = OrigData[i+0] * color.r;
NewData[i+1] = OrigData[i+1] * color.g;
NewData[i+2] = OrigData[i+2] * color.b;
NewData[i+3] = OrigData[i+3];
}
//Put changed image onto the canvas
ImgContext.putImageData(TempImgData, 0, 0);
}
The second is updating the last line in draw() to read as follows:
drawImg(ImgCanvas, Positions[i].x, Positions[i].y, Positions[i].x+Positions[i].y);
Using this updated code, we simply refer to the original base (white) image data and calculate new values based on that every time we go through the updateimage() function. When you call getImageData() you receive a copy of the image data on the canvas, so if you edit the canvas or the data, the other one remains untouched. You were already grabbing the original base image data to begin with, so it made sense to just use that instead of having to re-acquire it every time we updated.
Also, you'll notice that I modified your loop that changes the image color slightly. By obtaining a handle to the actual data array that you want to access/modify, you save yourself having to resolve the array location from the parent object every time you go through the loop. This technique actually results in a pretty nice performance boost. Your performance was fine to start with, but it can't hurt to be more efficient since it's pretty straight-forward.

Categories