-1

I need to upload an png/jpeg image file (image a) as in this image with any size from browser then export it into a new image with different size (image b). As you can see, I want to keep image a's ratio and fill the missing part with plain color (eg. white). How do I do this using javascript?

EDIT: Sorry for the bad question. I've already edited my question by adding my own code to solve this problem. My work is using canvas to draw a white background first then draw the uploaded image as long as it fits the canvas. Then I use Reimg.js to capture the canvas and download it.

However, the problem is if I want to use the captured image, I have to upload it again. The below code is not what I want.

So, is there any better way to upload an image file, processing it like my code below then retrieve the file data (File object) without capturing and uploading that image again?

// reimg.js
window.ReImg = {

    OutputProcessor: function(encodedData, svgElement) {

        var isPng = function() {
            return encodedData.indexOf('data:image/png') === 0;
        };

        var downloadImage = function(data, filename) {
            var a = document.createElement('a');
            a.href = data;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
        };

        return {
            toBase64: function() {
                return encodedData;
            },
            toImg: function() {
                var imgElement = document.createElement('img');
                imgElement.src = encodedData;
                return imgElement;
            },
            toCanvas: function(callback) {
                var canvas = document.createElement('canvas');
                var boundedRect = svgElement.getBoundingClientRect();
                canvas.width = boundedRect.width;
                canvas.height = boundedRect.height;
                var canvasCtx = canvas.getContext('2d');

                var img = this.toImg();
                img.onload = function() {
                    canvasCtx.drawImage(img, 0, 0);
                    callback(canvas);
                };
            },
            toPng: function() {
                if (isPng()) {
                    var img = document.createElement('img');
                    img.src = encodedData;
                    return img;
                }

                this.toCanvas(function(canvas) {
                    var img = document.createElement('img');
                    img.src = canvas.toDataURL();
                    return img;
                });
            },
            toJpeg: function(quality) { // quality should be between 0-1
                quality = quality || 1.0;
                (function(q) {
                    this.toCanvas(function(canvas) {
                        var img = document.createElement('img');
                        img.src = canvas.toDataURL('image/jpeg', q);
                        return img;
                    });
                })(quality);
            },
            downloadPng: function(filename) {
                filename = filename || 'image.png';
                if (isPng()) {
                    // it's a canvas already
                    downloadImage(encodedData, filename);
                    return;
                }

                // convert to canvas first
                this.toCanvas(function(canvas) {
                    downloadImage(canvas.toDataURL(), filename);
                });
            }
        };
    },

    fromSvg: function(svgElement) {
        var svgString = new XMLSerializer().serializeToString(svgElement);
        return new this.OutputProcessor('data:image/svg+xml;base64,' + window.btoa(svgString), svgElement);
    },

    fromCanvas: function(canvasElement) {
        var dataUrl = canvasElement.toDataURL();
        return new this.OutputProcessor(dataUrl);
    }

};

// script.js
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

$('#uploadImage').on('change', function(event) {
  var img = new Image();
  var reader = new FileReader();
  reader.onload = function(e) {
    img.src = e.target.result;
  };
  reader.readAsDataURL(event.target.files[0]);

  img.onload = function() {
    // draw white background
    context.beginPath();
    context.rect(0, 0, 500, 500);
    context.fillStyle = "white";
    context.fill();

    // draw uploaded image
    var scale = Math.min((canvas.width / img.width), (canvas.height / img.height));
    context.drawImage(img, 0, 0, img.width, img.height, (canvas.width - img.width * scale) / 2, (canvas.height - img.height * scale) / 2, img.width * scale, img.height * scale);
  };

});

$('#btnCapture').on('click', function() {
  ReImg.fromCanvas(canvas).downloadPng();
});
#canvas {
  border: 1px solid seagreen;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Resize Image</title>
</head>

<body>
  <input id="uploadImage" type="file" accept="image/*" />
  <button id="btnCapture" type="button">Capture</button>
  <canvas id="canvas" height="500px" width="500px"></canvas>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script src="script.js"></script>
</body>

</html>
Thanh Vo
  • 1
  • 2
  • You need to supply the code you have already tried and explain what was wrong with it. Then we can help you fix your issue. This isn't a _"write my code for me"_ site. – Reinstate Monica Cellio Nov 08 '16 at 11:34
  • Sorry for the bad question. I've updated it already. – Thanh Vo Nov 08 '16 at 14:11
  • What do you want to do with the image? You have a reference to it already, as the href attribute of the link you create to download it. If you put an image in the page and set the src to the same value then you'll have the image. – Reinstate Monica Cellio Nov 08 '16 at 14:56
  • I've found what exactly I wanted to ask. That is how to convert Canvas element to File object in javascript. Luckily, I've found the answer. I will add the answer soon. Thanks for help. – Thanh Vo Nov 09 '16 at 02:50

1 Answers1

0

I've found the answer. This can be simply solved by converting the canvas to dataURI then converting dataURI to File. Canvas to dataURI can be done as below snippet. Then, Convert Data URI to File then append to FormData .

var imgB64 = canvas.toDataURL('image/png');
Community
  • 1
  • 1
Thanh Vo
  • 1
  • 2