In Angular, use ng-img-max to adjust images in browsers

Posted by jgetner on Tue, 04 Jun 2019 06:50:39 +0200

You want to upload pictures in Angular applications. Do you want to limit the size of uploaded pictures at the front end before uploading them? The ng2-img-max module is exactly what you want! The ng2-img-max module uses web sorkers to calculate the image size and resides in the main thread.

Let's look at his use:

install

First, install modules using npm or Yarn:

$ npm install ng2-img-max blueimp-canvas-to-blob --save

# or Yarn :
$ yarn add ng2-img-max blueimp-canvas-to-blob

blueimp-canvas-to-blob is a polyfill so that canvas.toBlob() can be used in browsers such as Safari and older versions of Internet Explorer.

Include the polyfill script in the project. If you use Angular CLI, you can add the script to the. angular-cli.json file:

//: .angular-cli.json

...
"scripts": [
  "../node_modules/blueimp-canvas-to-blob/js/canvas-to-blob.min.js"
],
//...

After adding the script to the Angular CLI configuration, you will need to restart the local service.

Now we import modules into application modules or functional modules:

//: app.module.ts

//...
import { Ng2ImgMaxModule } from 'ng2-img-max';

@NgModule({
  declarations: [ AppComponent ],
  imports: [
    //...
    ng2ImgMaxModule
  ],
  providers: [],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

Finally, ng2-img-max services can be imported and injected into such components:

import { Component } from '@angular/core';

import { Ng2ImgMaxService } from 'ng2-img-max';

@Component({ ... })
export class AppComponent {
  constructor(private ng2ImgMax: Ng2ImgMaxService ) {}
}

Use

We add a File file input box to the component template, like this:

<input type='file' (change)="onImageChange($event)" accept="image/*" />

Adding the onImageChange method to the component class will limit the width of the image to 400px,300px:

updateImage: Blob;

constructor(private ng2ImgMax: Ng2ImgMaxService) {}

onImageChange(event){
  let image = event.target.files[0];
  
  this.ng2ImgMax.resizeImage(image,400,300).subscribe(result=> {
    this.uploadImage = result;
  },
  error=> {
    console.log('error:',error);
  })
}

If you have multiple images that need to be resized at once, use the resize method and pass in the image file array as the first parameter.

The result is a Blob type, but if necessary, you can use the File constructor to convert it to the correct file:

//: app.component.ts

uploadedImage: File;
constructor(private ng2ImgMax: Ng2ImgMaxService) {}
onImageChange(event){
  let image = event.target.files[0];
  
  this.ng2ImgMax.resizeImage(image,400,300).subscribe(result=> {
    this.uploadedImage = new File([result],result.name);
  },
  error=> {
    console.log('error',error);
  })
}

You can now upload files to your back end. Don't forget to validate in the back end, because the content here will prevent some users from uploading large or non-image files directly to the back end.

Limit width or height only

Suppose you just want to limit the height to 300 PX and adjust the width accordingly to maintain the same aspect ratio. Just set any threshold to 10000:

//...
onImageChange(event) {
  let image = event.target.files[0];
  this.ng2ImgMax.resizeImage(image,10000,300).subscribe(result=> {
    this.uploadedImage = new File([result],result.name);
  },
  error=> {
    console.log('error:',error);
  });
}

Compression instead of Resizing

You can also perform lossy compression using compress or compress image methods instead of resizing the image. Just pass the maximum (megabytes). You obviously want to run some tests to see how far you want to go for a few hours while keeping the image looking good.

In the following example, we limit the generated image to about 75Kb:

onImageChange(event) {
  let image = event.target.files[0];

  this.ng2ImgMax.compressImage(image, 0.075).subscribe(
    result => {
      this.uploadedImage = new File([result], result.name);
      this.getImagePreview(this.uploadedImage);
    },
    error => {
      console.log('😢 Oh no!', error);
    }
  );
}

Picture preview

You may want to preview the image to be uploaded to the user. You can do this using the FileReader object. You also need to use Angular's Dom Sanitizer to make it trust the base64 encoding data URI created with the FileReader object:

Now, our component content is like this. An interesting new approach in components is getImagePreview:

//: app.component.ts

import { Component } from '@angular/core';
import { Ng2ImgMaxService } from 'ng2-img-max';
import { DomSanitizer } from '@angular/platform-browser';

@Component({ ... })
export class AppComponent {
  uploadedImage: File;
  imagePreview: string;

  constructor(
    private ng2ImgMax: Ng2ImgMaxService,
    public sanitizer: DomSanitizer
  ) {}

  onImageChange(event) {
    let image = event.target.files[0];

    this.ng2ImgMax.resizeImage(image, 10000, 375).subscribe(
      result => {
        this.uploadedImage = new File([result], result.name);
        this.getImagePreview(this.uploadedImage);
      },
      error => {
        console.log('😢 Oh no!', error);
      }
    );
  }

  getImagePreview(file: File) {
    const reader: FileReader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      this.imagePreview = reader.result;
    };
  }
}

In our template, we can use sanitizer to display the image:

//: app.component.html

<img
    *ngIf="imagePreview"
    [src]="sanitizer.bypassSecurityTrustUrl(imagePreview)">

That's all about it! You can also view the ng2-img-tools package of the same author for more browser-side image processing (such as cropping).

God's favored one
Wednesday, August 16, 2017, Shenzhen

Topics: Javascript angular npm JSON encoding