Ethan Harlig
Ethan Harlig

Reputation: 766

Converting image to jpg Angular 4

I am using Angular 4 with TypeScript for a web application. I am allowing users to upload a thumbnail profile photo from their device as either a png, jpeg, or jpg, and I want to convert that photo to a jpg on the frontend. I am looking for some way to do this, as the file type is readonly.

The reason that I am doing this is so that when users load the profile page, they don't have to download large images so the page is quick. I think that converting to a jpg might be the best bet because when tested with a sample image, a png of an image was 35.4KB while a converted jpg of the same image was 6.7KB. If there is a better solution, I would love to hear it!

Thank you in advance!

Upvotes: 3

Views: 8743

Answers (1)

kite.js.org
kite.js.org

Reputation: 1649

I just wrote some code like your requirements, here is what I did:

  1. load a local image by FileReader and add a listener to its onload event
  2. in the onload listener, create an "Image" object by new Image(), and set "src" attribute by the loaded image "src" (Data URL format)
  3. create a "Canvas" element, and draw the image on this canvas
  4. use Canvas.toDataURL() to fetch the converted image data (in base64)
  5. post the image data to server

After you draw an image to canvas, call Canvas.toDataURL() will get the canvas content in Data URL string, please note that it's the canvas data not original image data, for example, if image size is 100 x 100 and canvas size is 50 x 50, you'll get an image in 50 x 50 pixel with this function, so if you want a full size image, you need to resize the canvas to the certain size.

this function has two parameters:

canvas.toDataURL(type, encoderOptions);

  • type - A DOMString indicating the image format. The default format type is image/png. in your code, set to "image/jpeg" in your case
  • encoderOptions - A Number between 0 and 1 indicating image quality if the requested type is image/jpeg or image/webp.

Here is my "preview and upload" function write in TypesScript for reference:

preview(input: HTMLInputElement) {
        if (input.files.length) {
            let reader = new FileReader();
            reader.onload = (e) => {
                if (!this.img) {
                    this.img = new Image();
                }

                this.img.src = (e.target as any).result;
                this.img.onload = () => {
                    // omit code of setting 'dx', 'dy', 'width', 'height'
                    let ctx = <CanvasRenderingContext2D>this.canvas.nativeElement.getContext('2d');
                    ctx.drawImage(this.img, dx, dy, width, height);

                    let dataUrl = (<HTMLCanvasElement>this.canvas.nativeElement).toDataURL('image/jpeg', 0.7);
                    this.uploadService.upload(dataUrl).then((resp: any) => {
                        if (resp.key) {
                            this.asset.image = resp.key;
                        }
                    });
                };
            }

            reader.readAsDataURL(input.files[0]);
        }
    }

I omitted some variables: dx, dx, width, height in the above code, I use these variables to adjust image position (for clipping purpose).

This is JavaScript example:

function _elm(id) {
  return document.getElementById(id);
}

_elm('fileInput').onchange= function(event) {
  if (event.target.files.length) {
    var fileReader = new FileReader();
    fileReader.onload = function(event) {
      var img = new Image();
      img.src = event.target.result;
      _elm('sizeRaw').innerText = '+ data-url size ' + event.target.result.length;
      img.onload = function() {
        var canvas = _elm('canvas');
        var context = canvas.getContext('2d');
        context.drawImage(img, 0, 0, 200, 200);
        var dataUrl = canvas.toDataURL('image/jpeg', 0.5);
        _elm('output').innerText = dataUrl;
        _elm('sizeNew').innerText = '+ data-url size ' + dataUrl.length;
      }
    };
    fileReader.readAsDataURL(event.target.files[0]);
  }
};
#canvas {
  border: 1px solid blue;
}

#output {
  word-break: break-all;
}
<h3>Input file <span id="sizeRaw"></span>: </h3>
<input id="fileInput" type="file" accept="image/*">
<h3>Canvas</h3>
<div>
<canvas id="canvas" width="200" height="200"></canvas>
</div>
<h3>Output <span id="sizeNew"></span>: </h3>
<div id="output">
</div>

Upvotes: 2

Related Questions