Tutorial

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

Published on July 4, 2017
Default avatar

By Alligator.io

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 us


About the authors
Default avatar
Alligator.io

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel