Report this

What is the reason for this report?

How To Resize Images in the Browser in Angular with ng2-img-max

Published on July 4, 2017
How To Resize Images in the Browser in Angular with ng2-img-max
This tutorial is out of date and no longer maintained.

Introduction

So you want to allow for image uploads in your Angular 2+ apps, but would like to limit the dimension of uploaded images directly on the frontend before even uploading anything? The ng2-img-max module is just what you need! ng2-img-max will use web workers when available to perform the resizing computations, leaving the main thread alone.

Setting Up the Project

First, install the module using npm:

  1. npm install ng2-img-max blueimp-canvas-to-blob --save

Or Yarn:

  1. yarn add ng2-img-max blueimp-canvas-to-blob

blueimp-canvas-to-blob is a polyfill needed in order for canvas.toBlob() to be available on browsers like Safari and older versions of Internet Explorer.

Include the polyfill script in your project. If you’re using the Angular CLI, you can just add the script in your .angular-cli.json file:

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

Note: You will want to restart your local server after adding a script to the Angular CLI configuration.

Now let’s import the module in your app module or into a feature module:

app.module.ts
// ...

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

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

And finally, the ng2-img-max service can be imported and injected in a component like this:

app.component.ts
import { Component } from '@angular/core';

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

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

Using n2ImgMax

Let’s add a file input to our component’s template like this:

app.component.html
<input type="file" (change)="onImageChange($event)" accept="image/*">

And define the onImageChange method in the component class. This will limit the image to a width of 400px and a height of 300px:

app.component.ts
uploadedImage: Blob;

constructor(private ng2ImgMax: Ng2ImgMaxService) {}

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

  this.ng2ImgMax.resizeImage(image, 400, 300).subscribe(
    result => {
      this.uploadedImage = result;
    },
    error => {
      console.log('Oh no!', error);
    }
  );
}

Note: If you have multiple images to resize at once, use the resize method instead and pass-in an array of image files as the first argument.

The result is of type Blob, but you can convert that to a proper file using the File constructor like this if you want:

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('Oh no!', error);
    }
  );
}

Note: You can now upload the file to your backend. Don’t forget to validate things on the backend side, because nothing here prevents some conniving user from uploading oversized or non-image files directly to your backend.

Limiting Only Width or Height

Say you want to only limit the height to 300px, and have the width resized accordingly to keep the aspect ratio the same. Just set whichever side should just fallow to a value of 10000:

app.component.ts
// ...

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('Oh no!', error);
    }
  );
}

Compression Instead of Resizing

You can also use the compress or compressImage methods to perform lossy compression instead of resizing the image. Pass-in a maximum value in megabytes. You’ll obviously want to run some tests to see how small you’ll want to go here while still keeping the images looking good to the eye.

In the following example, we’re limiting the resulting 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);
    }
  );
}

Displaying an Image Preview

You’ll probably want to give a preview of the image to be uploaded to your users. You can do this using the FileReader object. You’ll also need to use Angular’s DomSanitizer to tell it to trust the base64-encoded data URI created using the FileReader object:

Here’s what our component now looks like. The interesting new method here 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;
    };
  }
}

And in our template we can use the sanitizer to display the image like this:

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

And that’s all there is to it!

Conclusion

You can also check out the ng2-img-tools package by the same author for more browser-side image manipulation like cropping.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author

Alligator
Alligator
Author
See author profile

Alligator.io is a developer-focused resource that offers tutorials and insights on a wide range of modern front-end technologies, including Angular 2+, Vue.js, React, TypeScript, Ionic, and JavaScript.

Category:
Tags:

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.