MEDIA GUIDES / Image Effects

Using Python Image Compression for Media Optimization

After text, images are usually the second most crucial element for website usability. Modern web design relies heavily on images to guide users, structure content, and create a positive online experience.

Despite their importance, images can significantly slow down page loading times, consume unnecessary bandwidth, and reduce the overall performance of web applications. This is where image compression comes in. Image compression is a technique that is used to reduce the file size of an image without reducing its visual quality.

In this article, we’ll explore how you can use Python’s capabilities to compress images to optimize web performance and user experience.

In this article:

Why Image Compression Matters in Media Management

Images are often the largest media assets on a web page, and can negatively impact performance despite their visual importance. Compressing images is one of the most effective techniques for improving web performance and it offers several advantages in web design. Image compression offers several key advantages, including:

  • Faster loading times for web pages and applications: Large, uncompressed images slow down page load speeds and negatively impact the user experience. Compressing images result in smaller image files, which means less data needs to be transferred, resulting in quicker loading times.
  • Reduced bandwidth consumption: The larger an image file is, the higher the amount of bandwidth required to load the image on the end user’s device. When users load pages with compressed images, they use less data. This is especially important for users with limited data plans, and for website owners, as it translates to lower hosting and bandwidth costs.
  • Improved user experience: When web pages load quickly and images display without delays, users are more likely to stay longer and interact with your website. A faster and more responsive website or application leads to happier users, resulting in higher conversion rates.
  • Reduced storage costs: Uncompressed images occupy unnecessary space, especially for websites and apps that rely heavily on images, such as social media platforms and e-commerce sites. Smaller image files, on the other hand, take up less space on servers and devices, saving you storage costs.
  • Positive impact on SEO: Search engines like Google take page load times into account when ranking websites. Optimized images help improve page speed, which can positively impact your site’s SEO ranking.

Lossy vs. Lossless Image Compression: Which Do You Use?

When it comes to compressing images, there are two primary methods you can use, namely lossy compression and lossless compression. Both methods reduce image file sizes but do so in different ways.

Lossy compression works by permanently removing some data from the image, resulting in smaller file sizes, but potential quality loss. In applications where file size is key, lossy compression is often preferred, despite resulting in some image quality degradation. In contrast, lossless compression decreases file size while preserving all data, allowing for perfect reconstruction of the original image.

Choosing between lossy and lossless will often depend on your specific use case and quality requirements. A basic rule of thumb you should adopt is choose lossy compression when file size reduction is prioritized, and a slight quality loss is acceptable (e.g., images for the web or print) and choose lossless compression when data integrity and perfect quality are essential (e.g., archives, medical images).

Using Pillow for Python Image Compression

Pillow is a Python library for manipulating images and performing basic image processing tasks, including image compression. It was created as a fork of PIL (Python Imaging Library) with powerful image processing capabilities and extensive file format support.

Pillow allows compression of images in both lossy and lossless ways. Let’s look at how each can be done.

Lossy compression with Pillow

The following code shows how to perform lossy compression with Pillow:

from PIL import Image

def compress_jpeg(input_path, output_path, quality=85):
    try:
        with Image.open(input_path) as img:
            # Save with optimization and progressive loading (for web)
            img.save(
                output_path,
                "JPEG",
                optimize=True,
                quality=quality,    # 70-85 is a good balance
                progressive=True 
            )
        print(f"File compressed successfully: {output_path}")
    except Exception as e:
        print(f"Compression failed: {e}")

# Usage
compress_jpeg("sample-image.jpg", "compressed.jpg", quality=75)

In the code above, the output format is explicitly set to JPEG because JPEG uses lossy compression. By specifying “JPEG” in the img.save method, Pillow applies lossy compression by discarding some of the image’s data, which significantly reduces the file size while maintaining acceptable visual quality.

Lossless compression with Pillow

To compress an image losslessly with Pillow, we can use the following code:

from PIL import Image

def optimize_png(input_path, output_path, compression_level=6):
    try:
        with Image.open(input_path) as img:
            img.save(
                output_path,
                "PNG",
                optimize=True,
                compress_level=compression_level  # Ranges between 0-9. Default is 6
            )
        print(f"PNG optimized successfully: {output_path}")
    except Exception as e:
        print(f"Optimization failed: {e}")

# Example usage
optimize_png("sample-image.jpg", "optimized.png", compression_level=6)

While Pillow is great for basic compression tasks, managing and optimizing a large number of images or implementing more advanced techniques can become complex. This is where cloud-based solutions like Cloudinary come into play.

Cloudinary and Python Image Compression: Optimizing Images At Scale

Cloudinary simplifies image optimization by using an intelligent quality and encoding algorithm that analyzes an image to find the best quality compression level and optimal encoding settings based on the user’s device and bandwidth.

Cloudinary also provides many programming language SDKs, including a Python SDK that makes it easy to integrate Cloudinary capabilities into your Python applications. When you upload your images, Cloudinary automatically applies certain optimizations on the images. These include optimizations to image quality, format, and size, among others.

Want to see how Cloudinary’s Python SDK works? Take a look at our documentation to find out more.

For example, using auto as the value for the fetch_format and quality in your transformation parameters, it will automatically deliver the image in the format and quality that minimizes file size (while still meeting the required quality level).

import cloudinary
import cloudinary.uploader
import cloudinary.api
from cloudinary import CloudinaryImage

cloudinary.config(  
    cloud_name="your_cloudinary_cloud_name",  
    api_key="your_cloudinary_api_key",  
    api_secret="your_cloudinary_api_secret",
    secure=True
)

# Upload the image
upload_result = cloudinary.uploader.upload(
    "image.jpg"
)

# Generate a transformed URL with auto quality and format
transformed_url = CloudinaryImage("auto_optimized_image").image(transformation=[
    {"width": 500, "crop": "scale"},
    {"quality": "auto"},
    {"fetch_format": "auto"}
])

print("Transformed Image URL:", transformed_url)

Cloudinary offers several advantages compared to Pillow in image optimization. If you’re handling hundreds of images, Cloudinary automates compression, format conversion, and CDN delivery out of the box.

Automating Python Image Compression in Workflows

If you’re building websites and applications that handle a large volume of images, automating the compression process becomes a necessity for maintaining performance and efficiency.

Building automated pipelines for image compression can become quite tedious with all the manual configurations and time investment involved. However, services like Cloudinary simplify this process, offering an easy and streamlined way to automate image optimization.

Here are some steps you can follow in a typical image compression pipeline.

  • Include automated compression during the upload process: Your system can automatically build optimized copies of an image when a user submits it by utilizing a cloud-based service like Cloudinary.
  • Integrate with web frameworks or content management systems (CMS): A lot of web frameworks and CMS platforms come with plugins or libraries that can optimize pictures automatically when images are created or uploaded. This eliminates the need for setting up your own image compression workflow.
  • Use scripts and APIs to automate compression tasks: You can create reusable Python scripts that process batches of photos or keep an eye out for new images in folders and automatically compress them using libraries like the Cloudinary SDK.

Handling Different Image Formats and Sizes

When working with various image formats, it’s important to understand their unique properties and choose the right one for your specific use case, to ensure effective media optimization. Some of the most common image formats are:

  • JPEG uses lossy compression and is one of the most universally recognized and supported image formats. It can be opened and viewed by virtually all web browsers, image viewers, operating systems, and image editing software.
  • PNG is widely used on the internet and is suitable for graphics, logos, and images with transparency, making it a go-to choice for designers, photographers, and developers.
  • WebP offers both lossy and lossless compression, often achieving better compression ratios and quality compared to JPEG and PNG. It supports several features including both lossy and lossless compression, transparency, animation, and wide browser support.

Deliver the Best Media Quality

The ultimate goal of image compression is to balance file size reduction with visual quality. Here are some strategies that can help you achieve this:

  • Choose the right compression method: Both lossy and lossless compression have their strengths and weaknesses. Use lossy for photos where slight quality loss is acceptable and lossless for graphics like logos where detail is important.
  • Use appropriate compression levels: Compression can make or mar your images. Don’t over-compress images but experiment with different quality settings for lossy formats to find the sweet spot between file size and visual quality.
  • Apply image responsiveness: Serve images that are appropriately sized for different devices using srcset or CSS media queries. This ensures that mobile users don’t download unnecessarily large images.
  • Use lazy loading for web images: Lazy loading is a technique for loading images only when they’re needed, like when a user scrolls to them. This helps to reduce initial load times by loading resources only when needed, improves user experience, and can lead to better SEO performance.
  • Use Content Delivery Networks (CDNs): CDNs store copies of your images on servers around the world. This helps deliver images faster to users no matter where they are, improving performance and reliability.

As web performance becomes more important in SEO and user experience, taking the time to implement efficient image compression techniques can have a significant impact on your site’s success.

To learn how to optimize images at scale without sacrificing performance or maintainability, sign up for a free Cloudinary account and start exploring our platform.

QUICK TIPS
Colby Fayock
Cloudinary Logo Colby Fayock

In my experience, here are tips that can help you better optimize image compression in Python-based workflows:

  1. Benchmark different libraries beyond Pillow and Cloudinary
    Libraries like imgkit, pyguetzli, and imageio can outperform Pillow in specific scenarios—benchmark compression ratio, speed, and visual quality across these tools to select the most efficient one for your use case.
  2. Leverage perceptual hashing to detect duplicate or near-duplicate images
    Before compressing or storing, use perceptual hashing (e.g., imagehash library) to identify and eliminate redundant images, significantly saving storage and processing time in large-scale image systems.
  3. Implement progressive enhancement with JPEG XL and AVIF
    These newer formats offer superior compression at better quality than WebP or JPEG. Use them for future-proofing your workflows, especially where browser support permits.
  4. Batch process images with multithreading or multiprocessing
    When handling large folders of images, use Python’s concurrent.futures or multiprocessing to parallelize compression—significantly reducing runtime on multicore machines.
  5. Auto-rotate based on EXIF data before compression
    Many images taken from smartphones contain orientation metadata. Use img._getexif() or piexif to correct orientation prior to compression for consistent display.
  6. Compress thumbnails separately using more aggressive settings
    For use cases like galleries or previews, apply heavier lossy compression to thumbnails. This ensures that users get fast-loading previews while maintaining high-resolution versions separately.
  7. Track compression efficacy via metrics
    Store pre- and post-compression sizes, compression ratios, and load times. Use these analytics to tune your quality settings and validate their impact on user performance.
  8. Use perceptual quality metrics instead of just PSNR
    Use SSIM (Structural Similarity Index) or MS-SSIM instead of PSNR when evaluating image quality post-compression—these better reflect human visual perception.
  9. Optimize image metadata stripping
    Use Pillow or exiftool to strip metadata like GPS, camera info, and thumbnails that inflate file size. This is especially valuable for public web use where such metadata has no value.
  10. Integrate image compression into CI/CD
    For dynamic websites or apps, add automated compression checks to your CI pipeline (e.g., GitHub Actions). This ensures all assets pushed to production meet compression standards without manual effort.
Last updated: Apr 30, 2025