Compressing and Cropping Images Without Losing Quality in Python

When working with images, especially for web applications, it’s essential to balance quality and file size. Large images can slow down your website, leading to a poor user experience. Python provides several libraries that make it easy to compress and crop images without significantly losing quality. In this blog post, we'll explore how to achieve this using popular libraries like Pillow, OpenCV, and Imageio.

Getting Started

First, you need to install the necessary libraries. You can do this using pip:

pip install Pillow opencv-python imageio

Compressing Images

Image compression reduces the file size without reducing the image’s quality too much. Here's how you can compress an image using Pillow, OpenCV, and Imageio.

Using Pillow

from PIL import Image

def compress_image_pillow(input_path, output_path, quality=85):
    with Image.open(input_path) as img:
        img.save(output_path, "JPEG", quality=quality)

# Example usage
compress_image_pillow("input.jpg", "compressed_output_pillow.jpg")

Using OpenCV

import cv2

def compress_image_opencv(input_path, output_path, quality=85):
    img = cv2.imread(input_path)
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
    cv2.imwrite(output_path, img, encode_param)

# Example usage
compress_image_opencv("input.jpg", "compressed_output_opencv.jpg")

Using Imageio

import imageio

def compress_image_imageio(input_path, output_path, quality=85):
    img = imageio.imread(input_path)
    imageio.imwrite(output_path, img, quality=quality)

# Example usage
compress_image_imageio("input.jpg", "compressed_output_imageio.jpg", quality=85)

Cropping Images

Cropping allows you to remove unwanted outer areas from an image. Here's how you can crop an image using Pillow, OpenCV, and Imageio.

Using Pillow

from PIL import Image

def crop_image_pillow(input_path, output_path, crop_area):
    with Image.open(input_path) as img:
        cropped_img = img.crop(crop_area)
        cropped_img.save(output_path)

# Example usage
crop_area = (100, 100, 400, 400)
crop_image_pillow("input.jpg", "cropped_output_pillow.jpg", crop_area)

Using OpenCV

import cv2

def crop_image_opencv(input_path, output_path, x, y, w, h):
    img = cv2.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    cv2.imwrite(output_path, cropped_img)

# Example usage
crop_image_opencv("input.jpg", "cropped_output_opencv.jpg", 100, 100, 300, 300)

Using Imageio

import imageio

def crop_image_imageio(input_path, output_path, x, y, w, h):
    img = imageio.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    imageio.imwrite(output_path, cropped_img)

# Example usage
crop_image_imageio("input.jpg", "cropped_output_imageio.jpg", 100, 100, 300, 300)

Combining Compression and Cropping

Often, you might need to both crop and compress an image. Here's how you can combine these operations using Pillow, OpenCV, and Imageio.

Using Pillow

from PIL import Image

def crop_and_compress_image_pillow(input_path, output_path, crop_area, quality=85):
    with Image.open(input_path) as img:
        cropped_img = img.crop(crop_area)
        cropped_img.save(output_path, "JPEG", quality=quality)

# Example usage
crop_area = (100, 100, 400, 400)
crop_and_compress_image_pillow("input.jpg", "final_output_pillow.jpg", crop_area)

Using OpenCV

import cv2

def crop_and_compress_image_opencv(input_path, output_path, x, y, w, h, quality=85):
    img = cv2.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
    cv2.imwrite(output_path, cropped_img, encode_param)

# Example usage
crop_and_compress_image_opencv("input.jpg", "final_output_opencv.jpg", 100, 100, 300, 300)

Using Imageio

import imageio

def crop_and_compress_image_imageio(input_path, output_path, x, y, w, h, quality=85):
    img = imageio.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    imageio.imwrite(output_path, cropped_img, quality=quality)

# Example usage
crop_and_compress_image_imageio("input.jpg", "final_output_imageio.jpg", 100, 100, 300, 300, quality=85)

Preserving Image Quality

While compressing and cropping can reduce file size and remove unwanted areas, preserving image quality is crucial. Here are some tips to maintain quality:

  1. Choose the Right Quality Setting: For JPEG images, a quality setting of 85 is usually optimal. For PNG images, you can use the optimize=True parameter.

  2. Use Appropriate Formats: JPEG is suitable for photos, while PNG is better for images with transparency or sharp edges.

  3. Avoid Multiple Saves: Opening, editing, and saving an image multiple times can degrade its quality. Try to perform all operations in one go.

Here’s a complete example that combines these advanced techniques:

import cv2
import imageio
from PIL import Image

def compress_image_pillow(input_path, output_path, quality=85):
    with Image.open(input_path) as img:
        img.save(output_path, "JPEG", quality=quality)

def crop_image_pillow(input_path, output_path, crop_area):
    with Image.open(input_path) as img:
        cropped_img = img.crop(crop_area)
        cropped_img.save(output_path)

def crop_and_compress_image_pillow(input_path, output_path, crop_area, quality=85):
    with Image.open(input_path) as img:
        cropped_img = img.crop(crop_area)
        cropped_img.save(output_path, "JPEG", quality=quality)

def compress_image_opencv(input_path, output_path, quality=85):
    img = cv2.imread(input_path)
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
    cv2.imwrite(output_path, img, encode_param)

def crop_image_opencv(input_path, output_path, x, y, w, h):
    img = cv2.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    cv2.imwrite(output_path, cropped_img)

def crop_and_compress_image_opencv(input_path, output_path, x, y, w, h, quality=85):
    img = cv2.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
    cv2.imwrite(output_path, cropped_img, encode_param)

def compress_image_imageio(input_path, output_path, quality=85):
    img = imageio.imread(input_path)
    imageio.imwrite(output_path, img, quality=quality)

def crop_image_imageio(input_path, output_path, x, y, w, h):
    img = imageio.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    imageio.imwrite(output_path, cropped_img)

def crop_and_compress_image_imageio(input_path, output_path, x, y, w, h, quality=85):
    img = imageio.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    imageio.imwrite(output_path, cropped_img, quality=quality)

def advanced_crop_and_compress_image_opencv(input_path, output_path, x, y, w, h, quality=85):
    img = cv2.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
    cv2.imwrite(output_path, cropped_img, encode_param)

def advanced_crop_and_compress_image_imageio(input_path, output_path, x, y, w, h, quality=85):
    img = imageio.imread(input_path)
    cropped_img = img[y:y+h, x:x+w]
    imageio.imwrite(output_path, cropped_img, quality=quality)

Use these functions as per your requirements to efficiently handle images in your Python projects.

Conclusion
Compressing and cropping images in Python is straightforward with libraries like Pillow, OpenCV, and Imageio. By adjusting parameters and combining operations, you can significantly reduce image file sizes without compromising quality. This is essential for web applications and any other projects where efficient image handling is crucial.
82
Subscribe to my newsletter

Read articles from ByteScrum Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ByteScrum Technologies
ByteScrum Technologies

Our company comprises seasoned professionals, each an expert in their field. Customer satisfaction is our top priority, exceeding clients' needs. We ensure competitive pricing and quality in web and mobile development without compromise.