0

I have this code which reads a file (an image) from the local filesystem and I want to resize the image so I can upload it to a server in a smaller format. The problem I am having is that I can't figure out how to resive it and convert it back to base64 so that I can send that base64 string to Cloudinary servers. The file is more than 2 megabytes, as it is, and I believe I can get it down to less than half an MB if I resize the file.

      $scope.addLocalImage = function (file) {

             var reader = new FileReader();

             reader.onload = function () {

                var tempImage = new Image();
                tempImage.src = reader.result; // to get the base64 result

                var height = tempImage.height;
                var width = tempImage.width;
                if (height > 100) { // max height for our purposes is 100 pixels
                    width = width / (height / 100);
                    height = 100;
                }
                if (width > 150) { // max width for our purposes is 150 pixels
                    height = height / (width / 150);
                    width = 150;
                }
                var c = document.createElement('canvas');
                c.width = width;
                c.height = height;
                var ctx = c.getContext("2d");
                ctx.drawImage(tempImage, 0, 0, width, height);
                var b64str = c.toDataURL("image/jpeg"); // this is not base64, how can I get a base64 string?


                var localImage = {
                    originalImageURL: b64str,
                    origin: "local",
                    imageObject:{
                        result: b64str
                    }
                };

                $scope.suggestedImages.push(localImage);
                $scope.selectImage($scope.suggestedImages.length - 1); // Select new image
                $scope.$apply();

            };

            reader.readAsDataURL(file); //this initiates the loading of file to browser

       };

the problem is that "var b64str = c.toDataURL("image/jpeg");" yields a malformed string, it's not base64. If I were to guess I would think this line is incorrect, or I need to add some code here to convert the canvas to base64. The malformed string is "data:,", which looks the the beginning of a base64 string, but is truncated

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817

1 Answers1

2

The image needs an onload handler, so drawing to the canvas doesn't happen before the image has loaded

$scope.addLocalImage = function (file) {
     var reader = new FileReader();

     reader.onload = function () {
        var tempImage = new Image();

        tempImage.onload = function() {
            var height = tempImage.height;
            var width = tempImage.width;
            if (height > 100) { // max height for our purposes is 100 pixels
                width = width / (height / 100);
                height = 100;
            }
            if (width > 150) { // max width for our purposes is 150 pixels
                height = height / (width / 150);
                width = 150;
            }
            var c = document.createElement('canvas');
            c.width = width;
            c.height = height;
            var ctx = c.getContext("2d");
            ctx.drawImage(tempImage, 0, 0, width, height);
            var b64str = c.toDataURL("image/jpeg");

            var localImage = {
                originalImageURL: b64str,
                origin: "local",
                imageObject:{
                    result: b64str
                }
            };

            $scope.suggestedImages.push(localImage);
            $scope.selectImage($scope.suggestedImages.length - 1); // Select new image
            $scope.$apply();
        }
        tempImage.src = reader.result; // to get the base64 result
    }
    reader.readAsDataURL(file); //this initiates the loading of file to browser
}
adeneo
  • 312,895
  • 29
  • 395
  • 388