Image Effects 3 Easy Ways to Eliminate Duplicate Images The Basics of Face Detection in Python Creating Custom Image Cropping Interfaces in Android How to Create Simple Yet Effective PHP Overlay Understanding Real-Time Image Recognition How to add a shadow effect to an image with CSS How to crop an image in Flutter with Cloudinary How To Rotate an Image with Java Image Processing with Python Rotating an image with CSS Enhancing User Experience with a Responsive Image Slider Building a Python Image Recognition System Building an Interactive JavaScript Image Manipulation Tool Image Align Centering with HTML and CSS Efficient Image Cropping Techniques with Angular and Cloudinary Ultimate Guide to Photo Gallery on Android A Comprehensive Guide to Adding Text to Images on Android Mastering Background Changes in React Applications Comprehensive Guide on Changing Background on Android Devices Mastering Image Rotation in Java A Guide to Adding Text to Images with Python A Guide to Converting Images to Grayscale with Python Introduction Creating an Image Overlay with JavaScript Rotating an Image in Python Creating a Dynamic Photo Gallery with jQuery Creating An Interactive Photo Gallery Using JavaScript Mastering Overlay in Android Mastering Angular Overlay: A Comprehensive Guide Comprehensive Guide to Overlay in Flutter Mastering Overlay React for Responsive Design Solutions Create a Blurred Image with PHP: A Comprehensive Guide Guide to Using Blur Image in Flutter Mastering Blur Image in React Native Mastering Image Blurring in Python Mastering the Art of Image Blurring Mastering the Art of Image Blurring in Java The Ultimate Guide to Blurring Images on Android Understanding and Implementing Blur Image in JQuery An Extensive Walkthrough of Blurring Images with JavaScript How to Use HTML, CSS, and JavaScript to Make an Image Slider HTML Image Tag How to Crop GIFs? How to Align Images with CSS Ken Burns Effect – Complete Guide and How to Apply It Cartoonify – Complete Guide on Cartoonify Image Effect Mastering Web Aesthetics: A Comprehensive Guide to Gradient Fades Sepia Effect: The Ultimate Guide to the Sepia Photo Effect What is Vignette? Guide to Vignette Image Editing Pixelate – The Ultimate Guide to the Pixelation Effect How to Outline an Image: Enhancing Visual Appeal and Depth Make Your Photos Pop with Image Effects Upscale Image – Developers guide to AI-driven image upscaling Image Manipulation: History, Concepts and a Complete Guide A Full Guide to Object-aware Cropping Simplify Your Life with Automatic Image Tagging How To Resize Images In WordPress How To Create a Progress Bar For Asset Uploads Animated GIFs – What They Are And How To Create Them How To Automatically Improve Image Resolution AI Drop Shadow Get Image Dimensions From URLs Automatically Add Sepia Effect To Images Automatically Make an Image a Cartoon Automatically Add Blur Faces Effect To Images Automatically Add Background Removal Effect to an Image How to Resize an Image with React How to Easily Resize an Image with React Native

Efficient Image Cropping Techniques with Angular and Cloudinary

angular image crop

Images are undoubtedly the most often used visual elements in today’s digital environment. They are effective tools for communication and visual presentations and are used everywhere, from marketing materials to artistic movements to memes about cats.

However, the importance of serving users images in the right format to ensure that the necessary information is conveyed cannot be overstated. Not everyone can interpret an image the same way, and if you’re trying to get a certain point across, there’s no better way than making it the focal point. One common method for achieving this is image cropping.

In this article, we’ll show you how to build an image cropper functionality in your Angular projects using Cloudinary.

In this article:

What is Image Cropping?

Image cropping is a technique that involves trimming the edges of an image to improve framing, alter the aspect ratio, or focus the viewer’s attention on a particular part of the image. This process can eliminate unwanted components from the picture or adjust its composition to better fit the design aesthetics or functionality requirements of a webpage, application, or marketing materials.

Essentially, image cropping allows you to redefine the boundaries of your image to ensure only the most important elements remain visible.

Cropping an image is often done for a wide range of reasons. These include removing sensitive and personal information, compressing file size, focusing on an image’s specific area of interest, changing an image’s shape and aspect ratio, and so on.

angular image crop

Cropping Images with Cloudinary

In this section, we’ll show you how to use the @cloudinary/url-gen package, which simplifies the generation of transformation URLs and includes special components and directives that allow you to integrate media assets easily in your Angular applications.

Prerequisites

Before you continue with this guide, we expect you’re familiar with HTML and CSS and have a good knowledge of JavaScript and Angular. If you’re not, check out the following resources before continuing.

You’ll also need to make sure you have the following prerequisites installed:

  • Node.js and npm (Node Package Manager)
  • Angular CLI (npm install -g @angular/cli)
  • A Cloudinary account (which you can sign up for a free account if you don’t have one)

Step 1: Setting up an Angular Project

First, create a new Angular project using the Angular CLI:

ng new angular-image-cropper`

Navigate to the project directory:

cd image-cropper-app
npm install @cloudinary/ng @cloudinary/url-gen

Finally, we’ll need to change one of our settings within Cloudinary before we can get started. Go to your Cloudinary dashboard and navigate to Settings > Security, set the Strict transformation option to disabled, as shown below, to allow the dynamic creation of new derived assets.

angular image crop

Step 2 – Import required packages

In this step, we import the necessary modules and components from Angular and Cloudinary and create a new instance of the Cloudinary object with our cloud name.

Open the src/app/app.component.ts and replace its content with the following:

import { Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';import { CommonModule } from '@angular/common';import { Cloudinary, CloudinaryImage } from '@cloudinary/url-gen';import {fill} from "@cloudinary/url-gen/actions/resize";import {focusOn} from "@cloudinary/url-gen/qualifiers/gravity";import {FocusOn} from "@cloudinary/url-gen/qualifiers/focusOn";import {autoGravity} from "@cloudinary/url-gen/qualifiers/gravity";// Create and configure your Cloudinary instance.const cld = new Cloudinary({
  cloud: {
    cloudName: '<YOUR_CLOUDINARY_CLOUDNAME>'  }
});

Make sure to replace <YOUR_CLOUDINARY_CLOUDNAME> with your unique Cloudinary cloud name, which you can find within your dashboard.

angular image crop

Step 3 – Create Our Image Transformation Functions

Let’s add the code that will crop the uploaded images:

// Fill cropping with face detection gravity
const fillCroppingWithFaces = (imageId: string) => {
const myImage = cld.image(imageId);
myImage.resize(fill().width(250).height(250).gravity(focusOn(FocusOn.faces())));
return myImage.toURL();
};

// Automatic gravity cropping
const autoGravityCropping = (imageId: string) => {
const myImage = cld.image(imageId);
myImage.resize(fill().width(200).height(300).gravity(autoGravity()));
return myImage.toURL();
};
  • The fillCroppingWithFaces function takes the image ID as input, creates a new Cloudinary image object from it, and resizes the image to 250×250 pixels while applying a gravity effect that focuses on faces in the image using the focusOn(FocusOn.faces()) qualifier. In this cropping mode, Cloudinary automatically crops the image to focus on faces detected in the image.
  • The autoGravityCropping function also takes the image ID as input, creates a new Cloudinary image object from it, and resizes the image to 200×300 pixels with the autoGravity() qualifier applied to automatically apply a gravity effect. The gravity parameter allows you to select which area or object to extract in the image. You can learn more about it here.

Step 4 – Component Definition

Next, add the following code to define the component’s template and create the AppComponent class component:

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <input type="file" (change)="onFileSelected($event)" />
    <button (click)="uploadImage()" [disabled]="!selectedImage">Upload Image</button>
    <div *ngIf="originalImageUrl">
      <h2>Original Image</h2>
      <img [src]="originalImageUrl" alt="Original Image" style="width: 50vw" />
    </div>
    <div *ngIf="fillCroppingWithFacesUrl">
      <h2>Fill Cropping with Face Detection Gravity</h2>
      <img [src]="fillCroppingWithFacesUrl" alt="Fill Cropping with Face Detection Gravity" />
    </div>
    <div *ngIf="autoGravityCroppingUrl">
      <h2>Automatic Gravity Cropping</h2>
      <img [src]="autoGravityCroppingUrl" alt="Automatic Gravity Cropping" />
    </div>
  `
})
export class AppComponent {
  // ...
}

Step 5 – Handle File Upload

Next, add the following code to the AppComponent class to create the logic for handling file upload:

export class AppComponent {
	  selectedImage: string | null = null;
	  originalImageUrl: string | null = null;
	  fillCroppingWithFacesUrl: string | null = null;
	  autoGravityCroppingUrl: string | null = null;
	  cloudName = '<YOUR_CLOUDINARY_CLOUDNAME>'; // Replace with your Cloudinary cloud name
	  uploadPreset = 'YOUR_UPLAOD_PRESET_NAME'; // Replace with your Cloudinary upload preset


	  onFileSelected(event: any) {
	    const file = event.target.files[0];
	    const reader = new FileReader();
	    reader.onload = () => {
	      this.selectedImage = reader.result as string;
	    };
	    reader.readAsDataURL(file);
	  }
}

Since we’re using unauthenticated upload requests, which allow us to perform uploads without generating an authentication signature on the backend, we need to use an upload preset to control unsigned requests.

To enable unsigned uploads, navigate to the Upload page in your Cloudinary dashboard. You can also create an upload preset on the Upload Presets page within your settings.

Step 6 – Upload the Image File to Cloudinary

While we’re still in the Appcomponent component, add the following code to handle the logic for sending the uploaded image to Cloudinary:

export class AppComponent {
// ...
uploadImage() {
  if (this.selectedImage) {
    const file = this.dataURItoBlob(this.selectedImage);
    const formData = new FormData();
    formData.append('file', file);
    formData.append('upload_preset', this.uploadPreset);
    fetch(`https://api.cloudinary.com/v1_1/${this.cloudName}/upload`, {
      method: 'POST',
      body: formData
    })
    .then(response => response.json())
    .then(data => {
      console.log('Image uploaded:', data);
      this.originalImageUrl = data.secure_url;
      this.updateCroppedImages(data.public_id);
    })
    .catch(error => {
      console.error('Error uploading image:', error);
    });
  }
}

}

Step 7 – Create a Helper Method

Next, below the uploadImage method, add the following code:

updateCroppedImages(publicId: string) {
    this.fillCroppingWithFacesUrl = fillCroppingWithFaces(publicId);
    this.autoGravityCroppingUrl = autoGravityCropping(publicId);
  }


dataURItoBlob(dataURI: string) {
  const byteString = atob(dataURI.split(',')[1]);
  const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ab], { type: mimeString });
}

In the code above:

  • The updateCroppedImages function updates the transformation functions with the uploaded image’s Cloudinary public ID so that each cropping transformation can be applied to the image.
  • The dataURItoBlob function is a helper function that converts the uploaded image’s data URL to a Blob object so we can upload it to Cloudinary.

Trying it Out

Finally, we can run npm run start to start up the application. Here’s what the result of the code looks like:

angular image crop

You can find the complete code for this guide on GitHub.

Wrapping Up

Whether you are building an e-commerce platform to showcase products, creating a social networking site where users can upload profile pictures, or developing any application that requires custom image inputs, Angular and Cloudinary offer a powerful combination for developers. With Cloudinary’s cloud-based approach, managing and manipulating images becomes less resource-intensive, ensuring your app remains fast and responsive.

Leverage the power of Cloudinary within your Angular applications to crop images and optimize and deliver them efficiently across all devices. Whether you’re an experienced developer or just starting, Cloudinary’s extensive documentation and supportive community make it accessible to integrate and use.

Don’t miss out on the opportunity to create more engaging and visually appealing web applications. Dive into Cloudinary today and elevate your Angular projects to the next level.

QUICK TIPS
Colby Fayock
Cloudinary Logo Colby Fayock

In my experience, here are tips that can help you better implement efficient image cropping techniques in Angular with Cloudinary:

  1. Preload images with ngx-lazy-load-image
    Use the ngx-lazy-load-image package in Angular to implement lazy loading of images. This optimizes performance by loading only the images visible in the viewport, reducing initial page load time, and improving the user experience, especially for high-resolution images.
  2. Optimize Cloudinary transformations using eager transformations
    When uploading images to Cloudinary, set up eager transformations to generate cropped or resized variants at upload time. This approach minimizes on-the-fly transformations, resulting in faster image delivery and reduced load on your Cloudinary account.
  3. Implement a cropping preview using Angular’s Change Detection
    Utilize Angular’s ChangeDetectorRef to dynamically update the preview of cropped images without causing unnecessary component re-renders. This ensures a smooth and responsive user interface as users adjust the crop area.
  4. Use Cloudinary auto-format and quality settings
    Always set format: "auto" and quality: "auto" in your Cloudinary transformations. This ensures that the cropped image is delivered in the optimal format and quality based on the user’s device, saving bandwidth and maintaining visual quality.
  5. Add focus-aware cropping for better subject centering
    Use Cloudinary’s gravity option with auto:subject to focus on the most prominent part of the image. This setting works well with images that might have varied focal points, ensuring that your crop highlights the most important areas of the image automatically.
  6. Create a reusable Angular directive for cropping
    Build a custom Angular directive for image cropping that you can attach to any component. This allows for easy reuse across multiple components and improves the maintainability of your cropping functionality, especially in large projects.
  7. Use Intersection Observer API for cropping interactions
    Enhance your Angular cropping tool by integrating the Intersection Observer API. Trigger cropping transformations only when the image is in view. This reduces unnecessary API calls and transformations for images that are not visible, optimizing your Cloudinary usage.
  8. Add metadata-based cropping for personalized experiences
    When working with user-uploaded images, use metadata (such as face detection or object recognition tags) stored in Cloudinary to apply custom cropping rules. For example, highlight a specific user’s face based on known positions or automatically crop around detected logos for branding.
  9. Set up background tasks for complex transformations
    If you’re applying multiple or complex transformations (e.g., multi-step face recognition followed by custom overlays), offload these to background workers in Angular using ng-web-worker or similar libraries. This prevents blocking the main UI thread and enhances responsiveness.
  10. Enable image transformations in Angular pipes for declarative syntax
    Implement custom Angular pipes to handle Cloudinary transformations declaratively within templates. This approach lets you keep the transformation logic clean and concise, making it easier to manage and extend for complex image processing needs.

These tips will help you build a more responsive, maintainable, and performant image cropping tool in Angular with Cloudinary, ensuring a high-quality user experience.

Last updated: Oct 2, 2024