4

I am creating an application which browses a large amount of pictures. At this point, that portion of the project is done and it sorts, filters, and loads the correct pictures, and even splits them into separate pages for faster loading.

This works great, but it still takes over 8 seconds to load the 25 pictures per page. I have done some research and I have concluded that using asynchronous jQuery Ajax requests would be the best to load them all at the same time as fast as possible.

Here is my code for this so far:

var imageArray = <?php if (!empty($images)) {echo '["' . implode('", "', $images) . '"]';} else {echo "false";} ?>;
console.log(imageArray);
console.log(imageArray.length);
for (i = 0; i < imageArray.length; i++) {
    $.ajax({
        type: 'GET',
        url: imageArray[i],
        dataType: 'image/jpg',
        async: true,
        success: function (data) {
            $("#" + i).attr("src", data);
        }
    });
}

The problem with this code is that it doesn't load nothing but an empty white square with a grey border. When I modify the code and run it in console in Chrome, data ends up being a string of jumbled up characters which I presume are the raw image data.

I have been searching for several days now, including on SO, and I have yet to find a solution which does what I need. On the contrary, I have found solutions which simply put the url into the image source using jQuery attr() which isn't what I need.

If anyone can provide any kind of solution to fix this code, or even perhaps a different and more efficient method of getting all the images, I am open to anything.

imageArray: http://pastebin.com/03tvpNey

Regards, Emanuel

Susheel Singh
  • 3,687
  • 3
  • 27
  • 62
Emanuel Elliott
  • 243
  • 1
  • 3
  • 14

4 Answers4

5

If you're using Base64 image data (the string of jumbled characters you mentioned), you'll need to get your img src to be something like:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

So your code should be:

var imageArray = <?php if (!empty($images)) {echo '["' . implode('", "', $images) . '"]';} else {echo "false";} ?>;
console.log(imageArray);
console.log(imageArray.length);
for (i = 0; i < imageArray.length; i++) {
$.ajax({
    type: 'GET',
    url: imageArray[i],
    dataType: 'image/jpg',
    async: true,
    success: function (data) {
        $("#" + i).attr("src", 'data:image/png;base64,'+data);
    }
});
}

However... I'd be very surprised if loading the images over AJAX and using the Base64 content is any quicker than using a normal <img src="path"/> approach.

The point of AJAX is to fetch some data after the DOM is loaded. All moderns browsers will already fetch images asynchronously. I doubt you'll see any performance gain whatsoever.

I'd suggest the more likely problem is that your 25 images... which I suppose are displayed as thumbnails... are still large, hi-res images. You should save a smaller 'thumbnail' version, and then fetch the hi-res image when/if the user clicks on the thumbnail to view the full-size one.

Note that an element ID can start with (or be) a number. This wasn't valid in HTML4, but is perfectly fine in HTML5. However, you might have trouble with CSS rules - so you'd be better off prefixing with a letter (i.e. i1,i2,i3...).

Dave Salomon
  • 3,237
  • 1
  • 16
  • 29
  • No, its not base64. By "random jumbled characters" I mean odd symbols and a few letters that show picture format, date, color type, etc. – Emanuel Elliott Nov 14 '15 at 03:36
  • Now, your idea that I should use thumbnails is a good idea. Do you know of a good way to do this efficiently for 300+ pictures? – Emanuel Elliott Nov 14 '15 at 03:39
  • I will call your suggestion to use thumbnails as my answer here. It definitely helped! Thanks a lot Dave! – Emanuel Elliott Nov 14 '15 at 04:27
  • Thanks @Emanuel. As for the best way of implementing this - there's a few. How are images uploaded? You could use PHP to resize them, and keep 1x Thumbnail and 1x Original (hi-res). Alternatively, you could have a page - `thumbnail.php` which takes in the image URL as a querystring parameter, and then return it resized using GD - something like [this post](http://stackoverflow.com/questions/3628874/dynamic-image-resize-using-php). (I'd say keep 2 copies - it's less processor intensive. Processing = expensive, disk space = cheap!) – Dave Salomon Nov 14 '15 at 05:18
  • Well, cost isn't really a factor here as I host my own stuff. What is the best way to resize all the files to thumbnails with php? Should I use some sort of php plugin such as imagik? EDIT: I found this. http://php.net/manual/en/function.imagescale.php. Thanks for the help Dave! – Emanuel Elliott Nov 14 '15 at 18:57
  • @Emanuel, I meant cost as in, resource cost on the machine. :). Imageik is good, they're all built on top of GD, which is where you've found imagescale - so, yes. :). No worries - good luck! – Dave Salomon Nov 15 '15 at 11:46
  • 1
    Thanks for all the help. I got it all working beautifully, even from slow iPad wifi. I managed to reduce 1.4 GB of files to 10mb of files! I really can't thank you enough! – Emanuel Elliott Nov 16 '15 at 12:40
1

Just to update (May 2020) as I have been trying to get images via ajax, with no success despite using the base64 approach.

Here is some code I have modified which returns the image as a blob:

const trigger = $('.trigger');
const wrapper = $('#wrapper');
const url = 'https://66.media.tumblr.com/35a8d8dac5c288505b3edb4a52655283/ee225bfce5e62623-af/s1280x1920/fad4e25562ce1b05c69dc8cc8da5a9a12d26a1aa.jpg';

trigger.on('click', () => {
    $.ajax({
       url,
       xhrFields:{
          responseType: 'blob'
       },
       success (data) {
          const url = window.URL || window.webkitURL;
          const src = url.createObjectURL(data);
          wrapper.attr('src', src);
       }
   });
});

Working example here: http://jsfiddle.net/lharby/Ljwa1yhd/

I realise this is slightly different to the OP request, but I found my way here searching 'get images via ajax jquery' so I hope it is of help. And as I could not get the base64 method to work, I thought an example might be useful.

lharby
  • 2,720
  • 5
  • 19
  • 50
0

I had an issue with this a while ago, I used this code:

function loadImage(path, width, height, target) {
    var loaded = true;
    $('<img src="' + path + '">').load(function () {
        if (loaded) {
            $(this).css('maxWidth', width).css('maxHeight', height).appendTo(target);
            loaded = false;
        }
    });
}

UPDATE:

using your images array:

["20151107_140328.jpg", "20151107_140329.jpg", "20151107_141113.jpg", "20151107_141114.jpg", "20151107_141439.jpg", "20151107_141447.jpg", "20151107_141500.jpg", "20151107_205509.jpg", "20151107_205512.jpg", "20151107_213703.jpg", "20151107_213708.jpg", "20151107_213823.jpg", "20151108_143256.jpg", "20151108_143258.jpg", "20151108_143320.jpg", "20151108_143322.jpg", "20151108_143339.jpg", "20151108_143340.jpg", "20151108_143419.jpg", "20151108_143422.jpg", "20151108_143433.jpg", "20151108_143435.jpg", "20151108_143443.jpg", "20151108_143445.jpg"]

You can do this:

var image_array = ["20151107_140328.jpg", "20151107_140329.jpg", "20151107_141113.jpg", "20151107_141114.jpg", "20151107_141439.jpg", "20151107_141447.jpg", "20151107_141500.jpg", "20151107_205509.jpg", "20151107_205512.jpg", "20151107_213703.jpg", "20151107_213708.jpg", "20151107_213823.jpg", "20151108_143256.jpg", "20151108_143258.jpg", "20151108_143320.jpg", "20151108_143322.jpg", "20151108_143339.jpg", "20151108_143340.jpg", "20151108_143419.jpg", "20151108_143422.jpg", "20151108_143433.jpg", "20151108_143435.jpg", "20151108_143443.jpg", "20151108_143445.jpg"];

for(var i = 0; i < image_array.length; i++) {
    loadImage(image_array[i], <width>, <height>, <container targeted>);
}

and in the imageLoad function:

function loadImage(path, width, height, target) {
    var loaded = true;
    $('<img src="/path/to/image/' + path + '">').load(function () {
        if (loaded) {
            $(this).css('maxWidth', width).css('maxHeight', height).appendTo(target);
            loaded = false;
        }
    });
}
Haring10
  • 1,498
  • 1
  • 18
  • 35
  • So, if I am correct in my skim-reading, this code here loads an image in the tag and then appends it to the target of your choice? This isn't exactly what I'm looking for in that this code won't try to load more than one at a time. – Emanuel Elliott Nov 14 '15 at 03:33
  • @EmanuelElliott Use a `for` loop in your links to loop over all the images you want and call the `loadImage` function inside of the `for` – Haring10 Nov 14 '15 at 03:40
  • So does this code of yours, the `loadImage()` function, does it use an tag as its "target" or does it use something else like a div? – Emanuel Elliott Nov 14 '15 at 03:56
0

Change your ids to id1,id2 or something similar from 1,2 and in success use this:

            $("#id" + i).attr("src", data);

see why id should not start from a number:What are valid values for the id attribute in HTML?

Community
  • 1
  • 1
Suchit kumar
  • 11,448
  • 3
  • 17
  • 41
  • Hey, I tried what you suggested and I made the ids to be id0, id1, id2, etc. and it still shows blanks. I have noticed that when I inspect element on the pictures, it does not show anything in the `src` attribute. – Emanuel Elliott Nov 14 '15 at 03:35
  • @EmanuelElliott why don't you make a single ajax call to get all the image path then split them in success and assign them using a for loop. – Suchit kumar Nov 14 '15 at 03:40
  • Well my problem isn't in the getting of the paths of the images. That works just fine. My problem here is loading the images in a timely manner as at the moment it takes an extreme amount of time. – Emanuel Elliott Nov 14 '15 at 03:42
  • @EmanuelElliott are you getting image path in success.check on clicking that whether it shows the image or not.if not the path is not complete. – Suchit kumar Nov 14 '15 at 03:45
  • I'm not really sure what you are asking here. Could you please try wording it more clearly? – Emanuel Elliott Nov 14 '15 at 03:53
  • @EmanuelElliott what is the value in data.is it the path till the image or something else – Suchit kumar Nov 14 '15 at 03:55
  • The data variable contains what I assume is the raw image data. I have gathered this because it is many jumbled up symbols and letters. – Emanuel Elliott Nov 14 '15 at 03:57