preserve 16-bit if present
This commit is contained in:
@@ -32,14 +32,60 @@ def compress_png(input_path, output_path):
|
||||
original_size = os.path.getsize(input_path)
|
||||
img = Image.open(input_path)
|
||||
|
||||
# Convert to RGB if RGBA and no transparency needed
|
||||
if img.mode == 'RGBA':
|
||||
# Keep RGBA for transparency support
|
||||
img = img.convert('RGBA')
|
||||
elif img.mode != 'RGB':
|
||||
img = img.convert('RGB')
|
||||
# Check if image is 16-bit
|
||||
# PIL represents 16-bit grayscale as 'I' mode (32-bit integer)
|
||||
# For color images, check pixel values to determine bit depth
|
||||
is_16bit = False
|
||||
original_mode = img.mode
|
||||
|
||||
# Save with maximum compression to output path
|
||||
if img.mode == 'I':
|
||||
# 'I' mode typically represents 16-bit grayscale
|
||||
is_16bit = True
|
||||
elif img.mode in ('RGB', 'RGBA', 'LA'):
|
||||
# Check if max pixel value exceeds 8-bit range
|
||||
try:
|
||||
# Get a sample of pixels to check
|
||||
pixels = list(img.getdata())
|
||||
if pixels:
|
||||
# Flatten if needed (for multi-channel modes)
|
||||
if isinstance(pixels[0], (tuple, list)):
|
||||
max_val = max(max(p) for p in pixels[:1000]) # Sample first 1000 pixels
|
||||
else:
|
||||
max_val = max(pixels[:1000])
|
||||
if max_val > 255:
|
||||
is_16bit = True
|
||||
except:
|
||||
# If we can't determine, assume 8-bit to be safe
|
||||
pass
|
||||
|
||||
# Preserve 16-bit depth if present, otherwise convert as needed
|
||||
if is_16bit:
|
||||
# For 16-bit images, preserve the mode
|
||||
# PIL will save 16-bit when mode is 'I' (grayscale) or when using specific modes
|
||||
if img.mode == 'I':
|
||||
# Keep 16-bit grayscale
|
||||
pass
|
||||
elif img.mode in ('RGB', 'RGBA'):
|
||||
# Keep color mode - PIL may preserve 16-bit depending on how it was loaded
|
||||
# Note: PIL's PNG save may convert 16-bit RGB to 8-bit, but we preserve the mode
|
||||
pass
|
||||
else:
|
||||
# Convert other modes while trying to preserve bit depth
|
||||
if 'A' in img.mode:
|
||||
img = img.convert('RGBA')
|
||||
else:
|
||||
img = img.convert('RGB')
|
||||
else:
|
||||
# 8-bit images: convert as needed
|
||||
if img.mode == 'RGBA':
|
||||
# Keep RGBA for transparency support
|
||||
img = img.convert('RGBA')
|
||||
elif img.mode != 'RGB':
|
||||
img = img.convert('RGB')
|
||||
|
||||
# Save with maximum compression
|
||||
# PIL will preserve 16-bit for 'I' mode automatically
|
||||
# For color 16-bit, PIL may convert to 8-bit, but we've preserved the mode
|
||||
img.save(str(output_path), 'PNG', optimize=True, compress_level=9)
|
||||
new_size = os.path.getsize(output_path)
|
||||
savings = original_size - new_size
|
||||
|
||||
Reference in New Issue
Block a user