The parameter “compress_level” is invalid for the APNG file extension #9299
Description
Activity
Could you provide a self-contained example demonstrating your point? In other words, code, along with any image files required to run that code?
Could you provide a self-contained example demonstrating your point? In other words, code, along with any image files required to run that code?
I also tested all formats supporting Sequence and included a comparison report of their differences.
Test code:
import time from pathlib import Path import numpy as np import pandas as pd from PIL import Image from PIL import report # 自动打印PIL报告 def test_image_compression(): """优化版图像压缩测试 - 支持多种格式""" script_dir = Path(__file__).resolve().parent output_dir = script_dir / 'compression_test' output_dir.mkdir(exist_ok=True) # 加载图像 img = Image.open(script_dir / 'example.png') bw_img = Image.open(script_dir / 'example_bw.png') if (script_dir / 'example_bw.png').exists() else img.convert('L') print(f"✅ Loaded color image: {img.size}, {img.mode}") print(f"✅ Loaded BW image: {bw_img.size}, {bw_img.mode}") # 创建动画序列 frames = [img if i % 2 == 0 else bw_img.resize(img.size) for i in range(10)] # 统一测试配置 - 所有格式都测试4个质量等级 test_configs = [ ('PNG', [9, 6, 3, 0]), # 4个压缩级别 ('GIF', [256, 128, 64, 32]), # 4个调色板大小 ('WEBP_LOSSY', [100, 85, 55, 25]), # 4个质量等级 ('WEBP_LOSSLESS', [100, 67, 33, 0]), # 4个质量等级(无损模式) ('TIFF', ['none', 'tiff_adobe_deflate', 'tiff_lzw', 'lzma']), # 4种压缩算法 ('AVIF', [100, 85, 55, 25]) # 4个质量等级 ] results = [] for format_type, params in test_configs: # 为每个格式统计成功/失败数量 success_count = 0 total_tests = len(params) * 2 # 单帧和多帧 print(f"\n🔧 Testing {format_type} format...") for param in params: for frame_count in [1, 10]: # 单帧和多帧 # 生成文件名 prefix = 'seq_' if frame_count > 1 else '' param_display = str(param).replace('/', '_') filename = f"{prefix}{format_type.lower()}_{param_display}.{format_type.split('_')[0].lower()}" filepath = output_dir / filename try: start_time = time.time() test_img = frames if frame_count > 1 else img # 统一保存逻辑 if format_type == 'PNG': save_args = {'compress_level': param} elif format_type == 'GIF': save_args = {'colors': param} elif format_type == 'WEBP_LOSSY': save_args = {'quality': param} elif format_type == 'WEBP_LOSSLESS': save_args = {'lossless': True, 'quality': param} elif format_type == 'TIFF': save_args = {'compression': param} else: # AVIF save_args = {'quality': param} # 多帧处理 if frame_count > 1: save_args.update({'save_all': True, 'append_images': test_img[1:], 'duration': 200, 'loop': 0}) if format_type == 'GIF': gif_frames = [f.quantize(colors=param) if f.mode != 'P' else f for f in test_img] gif_frames[0].save(filepath, **save_args) else: # 对于TIFF和AVIF,尝试多帧保存 try: test_img[0].save(filepath, **save_args) except Exception as e: # 如果不支持多帧,回退到单帧 if "animation" in str(e).lower() or "multiple" in str(e).lower(): test_img[0].save(filepath, **{k: v for k, v in save_args.items() if k not in ['save_all', 'append_images', 'duration', 'loop']}) else: raise e else: if format_type == 'GIF': gif_img = test_img.quantize(colors=param) if test_img.mode != 'P' else test_img gif_img.save(filepath) else: test_img.save(filepath, **save_args) # 计算差异 write_time = time.time() - start_time file_size = filepath.stat().st_size saved_img = Image.open(filepath) if frame_count > 1 and hasattr(saved_img, 'n_frames'): saved_img.seek(0) # 简单差异计算 orig_arr = np.array(img.convert('RGB')) saved_arr = np.array(saved_img.convert('RGB')) mse = np.mean((orig_arr - saved_arr) ** 2) psnr = 20 * np.log10(255.0 / np.sqrt(mse)) if mse > 0 else float('inf') saved_img.close() result = { 'Type': format_type, 'Frames': frame_count, 'Filename': filename, 'Param': param, 'Size_KB': file_size / 1024, 'Time_Sec': write_time, 'MSE': mse, 'PSNR': psnr } results.append(result) success_count += 1 except Exception as e: error_msg = str(e) if "encoder" in error_msg.lower() or "format" in error_msg.lower(): error_msg = "Format not supported" # 只打印失败信息 frame_info = f"{frame_count} frames" if frame_count > 1 else "single frame" print(f"❌ {format_type} {frame_info} {param}: Failed - {error_msg[:50]}") result = { 'Type': format_type, 'Frames': frame_count, 'Filename': filename, 'Param': param, 'Size_KB': float('nan'), 'Time_Sec': float('nan'), 'MSE': float('nan'), 'PSNR': float('nan'), 'Error': error_msg[:100] } results.append(result) # 每个格式测试完成后打印汇总 print(f"✅ {format_type}: {success_count}/{total_tests} tests passed") # 保存和显示结果 df = pd.DataFrame(results) df.to_csv(output_dir / 'results.csv', index=False) # 英文报告,标题包含帧数 print("\n📊 RESULTS SUMMARY:") for format_type in df['Type'].unique(): format_df = df[df['Type'] == format_type] for frame_count in sorted(format_df['Frames'].unique()): frame_df = format_df[format_df['Frames'] == frame_count] # 按参数值排序(特殊处理无损WebP) if 'WEBP_LOSSLESS' in format_type: frame_df = frame_df.sort_values('Param') else: frame_df = frame_df.sort_values('Size_KB') frame_label = f"{frame_count} frames" if frame_count > 1 else "single frame" print(f"\n{format_type} {frame_label}:") for _, row in frame_df.iterrows(): if pd.isna(row['Size_KB']): print(f" {row['Param']}: FAILED") else: psnr_info = f"∞" if row['PSNR'] == float('inf') else f"{row['PSNR']:.1f}" print(f" {row['Param']}: {row['Size_KB']:.1f}KB, Time: {row['Time_Sec']:.3f}s, PSNR: {psnr_info}dB, MSE: {row['MSE']:.2f}") return df if __name__ == "__main__": test_image_compression()
Simply pick any image, use Photoshop or any other tool to create an identical black-and-white version of the same dimensions, then use both as looping sequence frames.
The file size of the written PNG sequence shows absolutely no difference in quality.
PNG 10 frames:
9: 417.4KB, Time: 0.044s, PSNR: ∞dB, MSE: 0.00
6: 417.4KB, Time: 0.045s, PSNR: ∞dB, MSE: 0.00
3: 417.4KB, Time: 0.045s, PSNR: ∞dB, MSE: 0.00
0: 417.4KB, Time: 0.043s, PSNR: ∞dB, MSE: 0.00Other formats can produce files of different sizes as expected.
- changed the title
[-]The parameter “compress_level” is invalid for the APNG file extension.[/-][+]The parameter “compress_level” is invalid for the APNG file extension[/+]on Nov 13, 2025 I've created #9300
Reacted by HJH_Chenhe