Batch Compress Images
Overview
This Python script gradually reduces the quality and colors of all .png's in the same directory until a target size is reached.
1from PIL import Image, ImageEnhance
2import os
3
4# Define the target size in bytes
5TARGET_SIZE = 1048576/3
6
7def reduce_image_size(input_image_path, output_image_path):
8 # Load the image
9 image = Image.open(input_image_path)
10
11 # Convert image to RGB if it's not (necessary for JPEG format)
12 if image.mode != 'RGB':
13 image = image.convert('RGB')
14
15 # Start with full color depth
16 colors = 256
17
18 # Initial quality
19 quality = 95
20
21 # Initialize step counter
22 quality_steps = 0
23
24 # Save image with decreasing quality and color depth until size is less than target size
25 while True:
26 # Use dithering when reducing color depth
27 if colors < 256: # Apply dithering only when color depth is reduced
28 palette_image = image.quantize(colors=colors, method=Image.FASTOCTREE, dither=Image.FLOYDSTEINBERG)
29 else:
30 palette_image = image
31
32 # Convert the palette image back to RGB for JPEG saving
33 rgb_image = palette_image.convert('RGB')
34
35 # Save the image with the current quality and reduced color depth
36 rgb_image.save(output_image_path, format='JPEG', quality=quality, optimize=True, progressive=True)
37
38 # Check the size of the saved image
39 size = os.path.getsize(output_image_path)
40
41 print(f"Processing {input_image_path} -> Quality: {quality}, Colors: {colors}, Size: {size / 1024:.2f} KB")
42
43 # If the image size is below the target size, break the loop
44 if size < TARGET_SIZE:
45 break
46
47 # Reduce the quality two times before reducing color depth
48 if quality_steps < 2:
49 # Decrease the quality for the next iteration
50 quality -= 1
51 quality_steps += 1
52 # Ensure the quality does not go below 1
53 if quality < 1:
54 print("Quality is at minimum.")
55 break
56 else:
57 # Reset the quality step counter and reduce color depth
58 quality_steps = 0
59 # Reduce the number of colors
60 colors = max(16, colors - 1) # Reduce colors by 1 each time, down to a minimum of 16 colors
61 # Ensure the color depth does not go below 16
62 if colors <= 16:
63 print("Color depth is at minimum.")
64 break
65
66def optimize_directory_images(directory_path):
67 # List all files in the directory
68 for filename in os.listdir(directory_path):
69 # Process only PNG files
70 if filename.lower().endswith('.png'):
71 input_image_path = os.path.join(directory_path, filename)
72 output_image_path = os.path.join(directory_path, filename.replace('.png', '.jpg'))
73
74 # Reduce image size and save as JPEG
75 reduce_image_size(input_image_path, output_image_path)
76
77# Example usage
78directory_path = '.' # Path to the directory containing PNG images (use '.' for the current directory)
79optimize_directory_images(directory_path)