1

I am currently trying to resize base64 images, since the image files are too big to be processed later on with php. I've found a way to achieve this by resizing the image using canvas. Unfortunately the image I get is just a black field which is 300px wide and 150px high. Maybe it has something to do with img.onload and canvas.toDataURL() order, or I am just using the wrong event (img.onload). Any idea where the mistake can be?

function exportImg(val){  
                var imageData = $('#image-cropper').cropit('export', {originalSize: true});
                imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");

                var imageDataRes = resize(imageData);


                $.post('php/upload.php', { imageDataRes: imageDataRes });
        }



function resize(base64){
            // Max size for thumbnail
            var maxWidth = 900;
            var maxHeight = 900;

            // Create and initialize two canvas
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext("2d");
            var canvasCopy = document.createElement("canvas");
            var copyContext = canvasCopy.getContext("2d");

            // Create original image
            var img = new Image();
            img.src = base64;

            img.onload = function(){

                // Determine new ratio based on max size
                var ratio = 1;
                if(img.width > maxWidth) {
                    ratio = maxWidth / img.width;
                }
                else if(img.height > maxHeight) {
                    ratio = maxHeight / img.height;
                }


            // Draw original image in second canvas
            canvasCopy.width = img.width;
            canvasCopy.height = img.height;
            copyContext.drawImage(img, 0, 0);

            // Copy and resize second canvas to first canvas
            canvas.width = img.width * ratio;
            canvas.height = img.height * ratio;
            ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

            }
            alert(canvas.toDataURL());

            return canvas.toDataURL();
        }

EDIT:

What is async in this case and how to solve it? Sorry, but unfortunately I don't see how this could help me further. The $.post works perfectly, I get the images. I just don't get the idea of img.onload and toDataURL() and how I should parse them from one function to another. At first, I got a blank result, with no string at all (just data,), but by adding this img.onload I got finally some base64 string...but it was just black screen.

PLAYCUBE
  • 795
  • 4
  • 14
  • 24
  • Yes `img.onload` is asynchronous. You need to wrap your `toDataURL` call in this event handler. See https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Kaiido Jun 06 '17 at 01:32
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Kaiido Jun 06 '17 at 01:32
  • 1
    Regarding your edit, the function inside `img.onload` will be called asynchronously. This means that it will be called after the completion of the full js current execution. So, in `resize` you create the canvas, the img element, and return the dataURL of your empty canvas. Only then, when the script that has called `exportImg` (so even after `$.post`) will you draw the image on the canvas, too late. You need to use an callback to be able to post the dataURL, itself grabbed only after the image has been loaded. `img.onload = function(){ctx.drawImage(img,0,0); callback(canvas.toDataURL())` – Kaiido Jun 06 '17 at 02:25
  • So, in other words, `img.onload` would go asynchronously not only with `resize()`, but also with `exportImg()`? And therefore I need to make manipulations and use `callback`? – PLAYCUBE Jun 06 '17 at 02:41

1 Answers1

1

You will need to wait onload event after that use global variable to save data and call upload function on the end .

Try this :

function exportImg(val){  
                var imageData = $('#image-cropper').cropit('export', {originalSize: true});
                imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");

                  resize(imageData);

        }


var SendWhenisReady = function(imageDataRes){

 $.post('php/upload.php', { imageDataRes: imageDataRes });

};

function resize(base64){
            // Max size for thumbnail
            var maxWidth = 900;
            var maxHeight = 900;

            // Create and initialize two canvas
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext("2d");
            var canvasCopy = document.createElement("canvas");
            var copyContext = canvasCopy.getContext("2d");

            // Create original image
            var img = new Image();
            img.src = base64;

            img.onload = function(){

                // Determine new ratio based on max size
                var ratio = 1;
                if(img.width > maxWidth) {
                    ratio = maxWidth / img.width;
                }
                else if(img.height > maxHeight) {
                    ratio = maxHeight / img.height;
                }


            // Draw original image in second canvas
            canvasCopy.width = img.width;
            canvasCopy.height = img.height;
            copyContext.drawImage(img, 0, 0);

            // Copy and resize second canvas to first canvas
            canvas.width = img.width * ratio;
            canvas.height = img.height * ratio;
            ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);


                 alert(canvas.toDataURL());
                 window['imageDataRes'] = canvas.toDataURL();
                 SendWhenisReady(window['imageDataRes'])
            }



        }
Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75