如何降低WebP图片分辨率而非仅压缩文件大小?
如何用Python降低WebP图片的分辨率
问题背景
尝试通过Python代码压缩WebP图片,原代码仅通过调整JPEG保存质量减小了文件大小(从42.8kB降至8kB),但图片分辨率仍保持500x450不变,仅画质模糊。需要实现降低图片分辨率的效果,而非单纯压缩文件体积。
原代码如下:
import os import shutil as sh import cv2 import sys import PIL from PIL import Image img = PIL.Image.open("target.webp") width, height = img.size print(width, height) # define a function for # compressing an image def compressMe(file, verbose=False): # Get the path of the file filepath = os.path.join(os.getcwd(), file) # open the image picture = Image.open(filepath) # Save the picture with desired quality # To change the quality of image, # set the quality variable at # your desired level, The more # the value of quality variable # and lesser the compression picture.save("Compressed_" + file, "JPEG", optimize=True, quality=10) return # Define a main function def main(): verbose = False # checks for verbose flag if (len(sys.argv) > 1): if (sys.argv[1].lower() == "-v"): verbose = True # finds current working dir cwd = os.getcwd() formats = ('.jpg', '.jpeg') # looping through all the files # in a current directory for file in os.listdir(cwd): # If the file format is JPG or JPEG if os.path.splitext(file)[1].lower() in formats: print('compressing', file) compressMe(file, verbose) print("Done") if __name__ == "__main__": main() compressMe('target.webp') img2 = PIL.Image.open("Compressed_target.webp") PIL.Image._show(img2) width, height = img2.size print(width, height)
问题分析
原代码的compressMe函数仅修改了图片保存时的JPEG质量参数,没有对图片进行**缩放(resize)**操作,因此分辨率保持原始尺寸不变,只是通过降低画质来减小文件大小,导致图片模糊但分辨率未变。
解决方案
要降低分辨率,需要在处理流程中加入图片缩放步骤,通过PIL库的Image.resize()方法调整图片的宽高尺寸,同时可结合质量压缩进一步优化文件大小。
修改后的代码
import os import sys from PIL import Image def resize_and_compress(file, target_width=None, target_height=None, quality=75, verbose=False): filepath = os.path.join(os.getcwd(), file) picture = Image.open(filepath) original_width, original_height = picture.size # 计算缩放后的尺寸:支持指定单维度或按比例自动计算 if target_width and not target_height: ratio = target_width / original_width target_height = int(original_height * ratio) elif target_height and not target_width: ratio = target_height / original_height target_width = int(original_width * ratio) elif not target_width and not target_height: # 默认按50%比例缩放 target_width = int(original_width * 0.5) target_height = int(original_height * 0.5) # 使用LANCZOS滤镜缩放,保证画质 resized_picture = picture.resize((target_width, target_height), Image.Resampling.LANCZOS) # 保存时保留原图片格式(避免WebP转JPEG的额外损失) output_filename = f"Resized_Compressed_{file}" resized_picture.save(output_filename, format=picture.format, optimize=True, quality=quality) if verbose: print(f"原尺寸: {original_width}x{original_height} → 新尺寸: {target_width}x{target_height}") print(f"已生成文件: {output_filename}") return output_filename def main(): verbose = False target_width = None target_height = None quality = 75 # 解析命令行参数,支持自定义分辨率、质量和 verbose 模式 args = sys.argv[1:] i = 0 while i < len(args): if args[i].lower() == "-v": verbose = True elif args[i].lower() == "-w": target_width = int(args[i+1]) i += 1 elif args[i].lower() == "-h": target_height = int(args[i+1]) i += 1 elif args[i].lower() == "-q": quality = int(args[i+1]) i += 1 i += 1 cwd = os.getcwd() # 支持WebP、JPG、JPEG格式 supported_formats = ('.webp', '.jpg', '.jpeg') for file in os.listdir(cwd): file_ext = os.path.splitext(file)[1].lower() if file_ext in supported_formats: print(f"正在处理: {file}") resize_and_compress(file, target_width, target_height, quality, verbose) print("所有文件处理完成") if __name__ == "__main__": main() # 单独测试目标WebP文件,指定宽度为250,质量75 output_file = resize_and_compress('target.webp', target_width=250, quality=75, verbose=True) img2 = Image.open(output_file) print(f"新图片分辨率: {img2.size[0]}x{img2.size[1]}") img2.show()
关键说明
- 缩放逻辑:支持手动指定目标宽度/高度,或按比例自动计算;未指定时默认按50%比例缩放
- 画质保障:使用
Image.Resampling.LANCZOS滤镜(PIL 9.1.0+版本,旧版本可替换为Image.LANCZOS),缩放后画质优于默认滤镜 - 格式保留:保存时使用原图片的格式(如WebP),避免格式转换带来的画质损失
- 参数控制:通过命令行参数可灵活调整分辨率、压缩质量和输出详情,例如:
python script.py -w 300 -q 80 -v:将图片缩放到宽度300,质量80,显示详细信息
内容的提问来源于stack exchange,提问作者GR_ Gamer
相关产品推荐
相关产品推荐

