11 Replies Latest reply on Jul 21, 2016 7:55 AM by frankz60228614

    What is the best way to show images on device?

    frankz60228614

      I am working on an Android App with phonegap/cordova, trying to show images on Android device on page, the following is my code.

       

      $(function () {

          DEMODB.transaction(function (transaction){

              $sql = "SELECT * FROM project_pictures WHERE 1 LIMIT 1, 30";

              transaction.executeSql($sql, [], function (tx, results) {

                  var len = results.rows.length;

                  for (i = 0; i < len; i++){

                      $('#gallery').append('<div class="thumbnail"><img src="file:///data/data/me.app.id/files/'+results.rows.item(i).picture_name+'" alt="thumbnail" /></div>');

                  }

              }, function (t, e) {console.log(e.message);});

          }, function(err){alert(err.message);}, function(){});

      })

       

      It is able to display images on the page but after that, the response is very slow when scroll the page or click a link.

       

      What is the best way to improve this function?

        • 1. Re: What is the best way to show images on device?
          VectorP Level 4

          That slowness has nothing to do with your function, which seems perfectly OK.

          Without knowing the rest of your code, I would expect the trouble to be caused by the fact that you don't tell the browser the dimensions of each image.

          - Have you tried adding the 'width' and 'height' attributes of the 'img' element (or the equivalent CSS rule)?

          - Are you having the browser scale the image? If so, that might slow down things tremendously while scrolling with more than 10 such images on the same page

          • 2. Re: What is the best way to show images on device?
            Chris W. Griffith Adobe Community Professional

            There is one issue with the function. Instead of appending the html after each pass through the for loop, you will have better performance if you only make one append call after you have assembled the entirely new html.

             

            Chris

            • 3. Re: What is the best way to show images on device?
              frankz60228614 Level 1

              I made slight changes on appending the html, but it is still very slow.

               

                  DEMODB.transaction(function (transaction){

                      $sql = "SELECT date(date_uploaded) as date_uploaded FROM project_pictures WHERE 1 GROUP By date(date_uploaded) ORDER By date_uploaded DESC LIMIT 0, 10";

                          transaction.executeSql($sql, [], function (tx, results) {

                              var len = results.rows.length;

                              if(len>0){

                                  $('#gallery').html('');

                                  for (i = 0; i < len; i++){

                                      $('#gallery').append('<div id="'+results.rows.item(i).date_uploaded+'"><h5 class="date_uploaded">'+results.rows.item(i).date_uploaded+'</h5></div>');

                                      $sql1 = "SELECT date(date_uploaded) as date_uploaded, picture_description FROM project_pictures WHERE date_uploaded LIKE '"+results.rows.item(i).date_uploaded+"%' GROUP By picture_description";

                                      transaction.executeSql($sql1, [], function (tx, results) {

                                          var len = results.rows.length;

                                          for (i = 0; i < len; i++){

                                              $sql2 = "SELECT *, date(date_uploaded) as date_uploaded FROM project_pictures WHERE date_uploaded LIKE '"+results.rows.item(i).date_uploaded+"%' AND picture_description LIKE ?";

                                              transaction.executeSql($sql2, [results.rows.item(i).picture_description], function (tx, results) {

                                                  var len = results.rows.length;

                                                  var html = "";

                                                  var date_uploaded = results.rows.item(0).date_uploaded;

                                                  for (i = 0; i < len; i++){

                                                      html += '<div class="thumbnail"><img src="file:///data/data/me.app.id/files/'+results.rows.item(i).picture_name+'" alt="thumbnail" /></div>';

                                                      /*

                                                      var src = "file:///data/data/me.app.id/files/"+results.rows.item(i).picture_name;

                                                      var thumbnail = encodeImageUri(src);

                                                      $('#gallery div#'+results.rows.item(i).date_uploaded).append('<div class="thumbnail"><img src="'+thumbnail+'" alt="'+src+'" /></div>');

                                                      */

                                                  }

                                                  $('#gallery div#'+date_uploaded).append(html);

                                              }, function (t, e) {console.log(e.message);});

                                          }

                                      }, function (t, e) {console.log(e.message);});

                                  }  

                              }else{

                                  $('#gallery').html('No any pictures, please upload now.');

                              }

                          }, function (t, e) {console.log(e.message);});

                  }, function(err){alert(err.message);}, function(){});

              • 4. Re: What is the best way to show images on device?
                VectorP Level 4

                ...but it is still very slow.

                 

                What is slow? The actions on the page (like scrolling) after the images have initially been displayed? Or generating the images before displaying them?

                 

                If the former, you seem to ignore the suggestion that (a) specifying the image dimensions and (b) refraining from scaling might help.

                If the latter, then set up a div with some log information about the process. You could display the HR time for each step in your loop and for the db calls. That would enable you to see where things slow down.

                See HR time: https://www.sitepoint.com/10-html5-apis-worth-looking/

                10 HTML5 APIs Worth Looking Into

                • 5. Re: What is the best way to show images on device?
                  frankz60228614 Level 1

                  The actions on the page after images have been displayed, I think the problem because of having app/browser scale the images. is there a plugin to generate thumbnail from URL on the fly?

                  • 6. Re: What is the best way to show images on device?
                    VectorP Level 4

                    A plugin??

                     

                    You can either create thumbnails of the required size on the server (where the original images came from) and store these together with the original images on the SD card, or you can resize the images using javascript/canvas within the app.

                    See https://www.google.de/search?q=javascript+resize+image+canvas

                     

                    If you have 25+ images of 1MB each, rescaled to thumbnails of, say, 60x60px, your webview will be really busy while scrolling.

                    • 7. Re: What is the best way to show images on device?
                      frankz60228614 Level 1

                      But I saw one post mentioned resizing the images using canvas cause performance issue too.

                      • 8. Re: What is the best way to show images on device?
                        VectorP Level 4

                        Well, then:

                        - either do it anyway and test it yourself, OR

                        - create thumbnails of the proper dimension on the server where the images come from, and store them, too.

                        - (if the images are from the camera:) store the thumbnails in the proper dimensions

                        • 9. Re: What is the best way to show images on device?
                          kerrishotts Adobe Community Professional

                          You'd only use the canvas to create a thumbnail, not to show the final result. You'd also save the thumbnail to local storage so that you'd never have to generate the thumbnail again (but of course, this starts to get difficult, since now you have to manage this cache).

                           

                          Preferably, generate the thumbnails on the server, as @VectorP has said. The backend would have far more resources and space, and your client-side maintains simplicity by just using an URI to refer to the thumbnail. Once you add in using the canvas to generate a thumbnail, things get complicated quickly.

                           

                          Also, it might help to see what kind of images you're trying to squeeze into a thumbnail size. Are these huge monstrosities being squeezed into 60x60, or are they 512x512 being squeezed into 60x60? Neither is good, but the latter is going to be much faster, obviously.

                           

                          It might also help to see a screen recording of what you're actually referring to (regarding slowness). That might help us see what you mean by slow response.

                           

                          Other things to try:

                           

                          • Reduce the number of images -- does this improve performance? If not, then it's not likely the images themselves causing the problem.
                          • Are you using an onclick handler? If so, have you included fastclick library (or equivalent)? If not, you may be running into the 300ms click delay present on many devices (especially on older OS versions).

                           

                          Unrelated, but never ever do this:

                           

                                $sql1 = "SELECT date(date_uploaded) as date_uploaded, picture_description FROM project_pictures WHERE date_uploaded LIKE '"+results.rows.item(i).date_uploaded+"%' GROUP By picture_description";

                                transaction.executeSql($sql1, [], function (tx, results) {

                           

                          It's subject to SQL injection attacks -- instead you should use prepared statements, which let you specify parameters in a safe way, like so:

                           

                                $sql1 = "SELECT date(date_uploaded) as date_uploaded, picture_description FROM project_pictures WHERE date_uploaded LIKE ? GROUP By picture_description";

                                transaction.executeSql($sql1, [results.rows.item(i).date_uploaded + "%"], function (tx, results) {

                           

                          Notice the "?" in the SQL statement? That's a placeholder for the parameter. There is a 1:1 correspondence to the position in the array passed to transaction.executeSql.

                          • 10. Re: What is the best way to show images on device?
                            frankz60228614 Level 1

                            What I am trying to do is, taking multiple pictures from camera, and move the pictures to application folder and save into database, then display them. No backend involved.

                             

                            function onDeviceReady(){

                                console.log(cordova.file.cacheDirectory);

                                console.log(cordova.file.dataDirectory);

                                takePicture();

                            }

                             

                             

                            function setOptions(srcType) {

                                var options = {

                                    // Some common settings are 20, 50, and 100

                                    quality: 50,

                                    destinationType: Camera.DestinationType.FILE_URI,

                                    // In this app, dynamically set the picture source, Camera or photo gallery

                                    sourceType: srcType,

                                    encodingType: Camera.EncodingType.JPEG,

                                    mediaType: Camera.MediaType.PICTURE,

                                    allowEdit: false,

                                    targetWidth: 1024,

                                    targetHeight: 768,

                                    saveToPhotoAlbum: true,

                                    correctOrientation: true  //Corrects Android orientation quirks

                                }

                                return options;

                            }

                             

                             

                            function takePicture(){

                                var srcType = Camera.PictureSourceType.CAMERA;

                                var options = setOptions(srcType);

                               

                                navigator.camera.getPicture( cameraSuccess, cameraError, options);

                            }

                             

                             

                            function cameraSuccess(uri){  

                                //alert(uri);

                                currentName = uri.replace(/^.*[\\\/]/, '');

                                $('#gallery').append('<div class="thumbnail"><a href="#"><img src="'+uri+'" alt="'+currentName+'" /></a></div>');

                                takePicture();   

                            }

                             

                             

                            function cameraError(message){

                                uploadPictures();

                            }

                             

                             

                            function uploadPictures(){

                                DEMODB.transaction(function (transaction){

                                    $('#gallery div.thumbnail img').each(function(index){

                                        $file_url = $(this).attr('src');

                                        $file_name = $(this).attr('alt');

                                        moveFile($file_url, $file_name);

                                       

                                        $sql_insert = "INSERT INTO project_pictures (picture_name, picture_description, project_id) VALUES (?, ?, ?)";

                                        transaction.executeSql($sql_insert, [$file_name, $('.description').val(), sessionStorage.project_id], function (tx, results) {

                                            console.log($file_name + ' has been saved to local database');

                                        }, function (t, e) {console.log(e.message);});

                                    })

                                }, function(err){alert(err.message);}, function(){window.location.replace("index.html");/*go back to pictures page*/});

                            }

                             

                             

                            function moveFile(fileUri, fileName) {

                                window.resolveLocalFileSystemURL(

                                      fileUri,

                                      function(fileEntry){

                                            newFileUri  = cordova.file.dataDirectory + "images/";

                                            window.resolveLocalFileSystemURL(cordova.file.dataDirectory,

                                                    function(dirEntry) {

                                                        // move the file to a new directory and rename it

                                                        fileEntry.moveTo(dirEntry, fileName, successCallback, errorCallback);

                                                    },

                                                    errorCallback);

                                      },

                                      errorCallback);

                            }

                            function successCallback(fileSystem) {

                                console.log(fileSystem.toURL());

                            }

                            function errorCallback(evt) {

                                alert(evt.target.error.code);

                            }

                            • 11. Re: What is the best way to show images on device?
                              frankz60228614 Level 1

                              I can change the option to generate thumbnail on getPicture, but then I don't know how to get original sized picture, any relations between the picture in cache and saved in album when I set saveToPhotoAlbum to ture?