Changing image format to jpg in Angular 4

In my web application using Angular 4 and TypeScript, I have enabled users to upload a thumbnail profile photo in either png, jpeg, or jpg format from their device. The challenge is that I need to convert the uploaded photo to jpg on the frontend due to file type restrictions. The main reason behind this conversion process is to ensure that when users visit the profile page, they do not experience slow loading times caused by large image files. Upon testing with a sample image, it was found that a png version of the image had a size of 35.4KB, whereas the converted jpg version was only 6.7KB. This significant reduction in size makes jpg conversion an appealing option for optimizing page loading speed. If there are alternative solutions or better methods for achieving this goal, I am open to suggestions and would appreciate any insights or recommendations. Thank you for your assistance!

Answer №1

I recently crafted some code that meets your specified requirements. Here is a breakdown of what I implemented:

  1. Loaded a local image using FileReader and attached a listener to its onload event.
  2. In the onload listener, instantiated an "Image" object with new Image(), and set the "src" attribute to the loaded image's source (in Data URL format).
  3. Created a "Canvas" element and rendered the image on this canvas.
  4. Utilized Canvas.toDataURL() to retrieve the converted image data in base64 format.
  5. Sent the image data to the server for processing.

Upon drawing an image onto the canvas, invoking Canvas.toDataURL() returns the canvas content in a Data URL string. It's important to note that this represents the canvas data and not the original image data. For instance, if the image size is 100 x 100 but the canvas dimensions are 50 x 50, calling this function will yield an image of 50 x 50 pixels. To obtain a full-size image, you must resize the canvas accordingly.

This function requires two parameters:

canvas.toDataURL(type, encoderOptions);

  • type - A DOMString specifying the image format. By default, the type is image/png. In your scenario, remember to set it as "image/jpeg".
  • encoderOptions - A number between 0 and 1 indicating the image quality when the type is image/jpeg or image/webp.

Below is my TypeScript implementation of the "preview and upload" function for your 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 = () => {
                    // omitted code for 'dx', 'dy', 'width', 'height' adjustments
                    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]);
        }
    }

The variables dx, dx, width, height have been left out from the above snippet, as they are used for adjusting the image position (primarily for clipping purposes).

Here is a 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

After updating to Angular 9, the ViewChild functionality seems to be malfunctioning

Is there a change in ViewChild behavior? Since upgrading to Angular 9, the MatSideNav menu has ceased to function. export class SidenavOpenCloseExample implements OnInit, AfterViewInit { @ViewChild('menuSide', {read: MatSidenav, static: true} ...

What is the process of utilizing angular-in-memory-web-api within an Angular 2 application?

I've successfully installed this package. Here is my mock data class: import { InMemoryDbService } from 'angular-in-memory-web-api'; export class InCredentialsService implements InMemoryDbService { public createDb() { const creden ...

Encountering problem while installing React: Unable to generate the node_modules folder

When using React, the npm install command may not create a node_modules folder even after running npm install completely. Instead, an error message similar to the following may be displayed and no node_modules will be present in the project: npm WARN depr ...

Testing a component that utilizes an observable time interval in Angular 2

I have implemented a slide-show component with an Input array of slide objects. Each slide is shown based on the time defined in slide.time. Additionally, there are two buttons that when clicked should move to the next item and reset the timer. To achieve ...

Establishing fixed values in an angular2 component

Is it possible in angular 2 to initialize values within the HTML view of a component that has already been rendered in PHP? //html page: <dropdown [(options)]="['Available', 'Busy', 'Away', 'Offline']"></dr ...

HTTP request in Angular with specific body content and custom headers

My goal is to access the sample API request from , as demonstrated in the documentation: curl -H "api-key: 123ABC" \ -H "Content-Type: application/json" \ -X POST \ ...

Transforming a JSON object into XML format

Currently, I am encountering an issue while attempting to convert my JSON object to XML using the xml-js library's json2xml function. When trying to implement this functionality, I keep getting an error message that states: Error: Buffer is not defin ...

The argument representing 'typeof Store' cannot be assigned to the parameter representing 'Store<AppState>'

I'm encountering an issue while trying to expand a service in Angular that utilizes ngrx. The error message I'm receiving is as follows: Argument of type 'typeof Store' is not assignable to parameter of type 'Store<AppState>& ...

State array is being updated

In my main container, I am setting a context for its children : import React, {useRef, useEffect, useState, ReactNode, createContext, useContext} from 'react'; import Provider from "./Provider"; import Consumer from "./Consumer&quo ...

Executing click on an HTML file element using a component in Angular 2

As a newcomer to Angular 2, I have a question: How can I trigger a click on an HTML file element from a component? rankingFilter() { this.RepsloaderShow = true; this.reps = []; var data = { from: this.fromFilter, to: this.to ...

Refreshing rows in ngx-datatable

Just started using ngx-datatable (version 11) with Angular-5 and encountered an issue. When loading rows during ngInit, everything works fine. However, when lazy-loading due to a user search request, the table shows the correct total number of rows but onl ...

The login option failed to redirect users to their dashboard

I am encountering an issue with the login services. The password check works fine, but there seems to be a problem with the navigation router not functioning correctly. I feel like I might be overlooking something specific, can you please help me pinpoint ...

Tips for implementing absolute import paths in a library project

In my workspace, I have a library with two projects: one for the library itself and another for a test application. ├── projects    ├── midi-app    └── midi-lib Within the workspace's tsconfig.json file, I set up paths for @a ...

Challenges with installing npm

After setting up express and fs along with a couple of other packages, I encountered an issue while running: npm ls The error message displayed was: â âââ <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80ede9ede5c0b1ae ...

Displaying multiple lines in an alert box using Angular 8

I need assistance in displaying an alert message when the user selects a checkbox. We have a shared alert service component that is being utilized by every module. My current code snippet is as follows: if(this.checkboxvalue) { this.al ...

Is it feasible for the Drawer to be a fixed feature that sits atop the content?

I am looking to have a compact drawer positioned on the left side of my screen, similar to the example shown in the Material UI Documentation: https://i.sstatic.net/W21Kd.png However, I would like it to float over the content (like the variant="temporary ...

Troubleshooting: Why is my Key Combination Event Listener not Functioning

I am currently working on adding multiple hotkeys to an application. My goal is to have key combinations ranging from alt+1 to alt+9. Interestingly, the alt+1 combination is functioning perfectly (breakpoint reached), but I am encountering issues with alt ...

Angular 2 observables failing to store returned object in designated variable

fetchEmployee(id : number) : void{ var employeeData : Employee; this.http.get(this.employeesUrl + '/' + id) .map(response => <Employee>response.json()) .subscribe((res) =>{employeeData = res}, ...

Working with material-design-icons offline in Vue and controlling their size

Incorporating materialdesignicons into my vue project has been a crucial aspect of my development process. import '../node_modules/@mdi/font/css/materialdesignicons.min.css'; Vue.use(Vuetify, { iconfont: 'mdi' }); I have successfully ...

I am experiencing difficulty loading my image in HTML5

Despite using the correct syntax and having my image file in the same folder as my HTML document, I am facing an issue where the programmed image does not appear on the page when I load the document. What could be causing this? In this case, both my HTML ...