Python图片批量处理与PDF自动化生成完整指南

发布时间:2026/7/31 4:59:05
Python图片批量处理与PDF自动化生成完整指南 在日常办公和学习中我们经常会遇到大量图片需要统一处理或者需要将图片整合成PDF文档的场景。比如产品团队需要批量压缩商品图片上传到网站学生需要将扫描的笔记图片合并成一个PDF文件行政人员需要为会议材料添加统一水印。手动一张张处理不仅效率低下还容易出错。本文将完整介绍一套图片批量处理与PDF处理的自动化方案涵盖从环境搭建到实战应用的全流程。无论你是编程新手还是有一定经验的开发者都能快速上手这套重复活一条龙解决方案。1. 图片处理的核心需求与工具选型1.1 常见的图片处理需求在实际工作中图片处理通常涉及以下几个核心需求格式转换将不同格式的图片如PNG、JPG、WEBP统一转换为特定格式尺寸调整批量修改图片尺寸适应不同的展示需求质量压缩在保证视觉效果的前提下减小文件体积水印添加为图片添加版权信息或品牌标识元数据处理读取或修改图片的EXIF信息1.2 Python图像处理库对比Python作为自动化处理的首选语言提供了多个强大的图像处理库PIL/Pillow最常用的图像处理库功能全面API友好OpenCV更适合计算机视觉任务处理速度较快Wand基于ImageMagick的Python接口支持格式丰富对于大多数办公自动化场景Pillow库是最佳选择因为它安装简单、文档完善且能满足绝大部分需求。1.3 环境准备与安装在开始之前需要确保Python环境已就绪。推荐使用Python 3.7及以上版本# 安装必要的依赖库 pip install Pillow PyPDF2 reportlab如果是处理更复杂的PDF需求还可以安装pip install pdf2image img2pdf fpdf2. Pillow库基础与核心API详解2.1 图像的基本操作Pillow库的核心是Image模块它提供了打开、操作和保存图像的功能from PIL import Image import os # 基本图像操作示例 def basic_image_operations(image_path): # 打开图像 img Image.open(image_path) # 获取图像信息 print(f格式: {img.format}) print(f尺寸: {img.size}) print(f模式: {img.mode}) # 显示图像在支持图形界面的环境中 # img.show() # 转换图像模式 if img.mode ! RGB: img img.convert(RGB) return img # 使用示例 if __name__ __main__: image basic_image_operations(example.jpg)2.2 常用的图像处理方法掌握以下几个核心方法就能应对大部分图片处理需求from PIL import Image, ImageFilter, ImageDraw, ImageFont class ImageProcessor: def __init__(self, image_path): self.image Image.open(image_path) def resize_image(self, width, height, keep_ratioTrue): 调整图片尺寸 if keep_ratio: # 保持宽高比调整大小 self.image.thumbnail((width, height), Image.Resampling.LANCZOS) else: # 强制调整到指定尺寸 self.image self.image.resize((width, height), Image.Resampling.LANCZOS) return self def compress_image(self, quality85, optimizeTrue): 压缩图片质量 # 这里主要针对JPEG格式保存时设置质量参数 return self def add_watermark(self, watermark_text, position(10, 10)): 添加文字水印 draw ImageDraw.Draw(self.image) # 尝试加载字体如果失败使用默认字体 try: font ImageFont.truetype(arial.ttf, 36) except: font ImageFont.load_default() # 添加水印文本 draw.text(position, watermark_text, fill(255, 255, 255, 128), fontfont) return self def convert_format(self, formatJPEG): 转换图片格式 # 格式转换主要在保存时实现 return self def save_image(self, output_path, **kwargs): 保存处理后的图片 self.image.save(output_path, **kwargs) return self3. 图片批量处理实战方案3.1 创建批量处理框架建立一个可扩展的批量处理类支持多种处理操作import os from pathlib import Path from PIL import Image, ImageFilter, ImageDraw, ImageFont class BatchImageProcessor: def __init__(self, input_folder, output_folder): self.input_folder Path(input_folder) self.output_folder Path(output_folder) self.output_folder.mkdir(parentsTrue, exist_okTrue) # 支持的图片格式 self.supported_formats {.jpg, .jpeg, .png, .bmp, .gif, .tiff, .webp} def get_image_files(self): 获取输入文件夹中的所有图片文件 image_files [] for file_path in self.input_folder.iterdir(): if file_path.suffix.lower() in self.supported_formats and file_path.is_file(): image_files.append(file_path) return image_files def process_single_image(self, input_path, output_path, operations): 处理单张图片 try: with Image.open(input_path) as img: # 确保RGB模式 if img.mode ! RGB: img img.convert(RGB) # 应用所有操作 for operation in operations: img operation(img) # 保存图片 img.save(output_path, optimizeTrue, quality85) print(f成功处理: {input_path.name} - {output_path.name}) return True except Exception as e: print(f处理失败 {input_path.name}: {str(e)}) return False def batch_process(self, operations, output_suffix_processed): 批量处理所有图片 image_files self.get_image_files() success_count 0 for input_path in image_files: output_filename f{input_path.stem}{output_suffix}{input_path.suffix} output_path self.output_folder / output_filename if self.process_single_image(input_path, output_path, operations): success_count 1 print(f批量处理完成: {success_count}/{len(image_files)} 成功) return success_count3.2 常用的处理操作函数定义一系列可组合的处理函数# 尺寸调整操作 def resize_operation(max_width800, max_height600): def operation(img): img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS) return img return operation # 格式转换操作 def format_operation(output_formatJPEG): def operation(img): # 格式转换在保存时处理这里主要确保模式正确 if output_format JPEG and img.mode ! RGB: img img.convert(RGB) return img return operation # 水印添加操作 def watermark_operation(textConfidential, position(10, 10)): def operation(img): draw ImageDraw.Draw(img) try: font ImageFont.truetype(arial.ttf, 36) except: font ImageFont.load_default() draw.text(position, text, fill(255, 255, 255, 128), fontfont) return img return operation # 滤镜效果操作 def filter_operation(filter_typeSHARPEN): def operation(img): filter_map { BLUR: ImageFilter.BLUR, SHARPEN: ImageFilter.SHARPEN, EDGE_ENHANCE: ImageFilter.EDGE_ENHANCE } if filter_type in filter_map: img img.filter(filter_map[filter_type]) return img return operation3.3 完整的批量处理示例def main(): # 初始化处理器 processor BatchImageProcessor(input_images, output_images) # 定义处理操作序列 operations [ resize_operation(1200, 800), # 调整尺寸 watermark_operation(Sample Watermark, (20, 20)), # 添加水印 filter_operation(SHARPEN) # 锐化滤镜 ] # 执行批量处理 success_count processor.batch_process(operations) print(f处理完成成功处理 {success_count} 张图片) if __name__ __main__: main()4. PDF处理全流程详解4.1 图片转PDF的多种方案将多张图片合并为PDF有多种实现方式各有优缺点方案一使用img2pdf库最简单import img2pdf import os from pathlib import Path def images_to_pdf_simple(image_folder, output_pdf): 使用img2pdf库将图片转换为PDF image_files [] for file_path in Path(image_folder).iterdir(): if file_path.suffix.lower() in [.jpg, .jpeg, .png]: image_files.append(str(file_path)) # 按文件名排序 image_files.sort() # 转换为PDF with open(output_pdf, wb) as f: f.write(img2pdf.convert(image_files)) print(fPDF生成成功: {output_pdf}) # 使用示例 images_to_pdf_simple(output_images, output.pdf)方案二使用ReportLab可定制性最强from reportlab.lib.pagesizes import A4, letter from reportlab.pdfgen import canvas from reportlab.lib.utils import ImageReader from PIL import Image import os def images_to_pdf_reportlab(image_folder, output_pdf, page_sizeA4): 使用ReportLab创建自定义PDF # 获取图片文件列表 image_files [] for filename in os.listdir(image_folder): if filename.lower().endswith((.png, .jpg, .jpeg)): image_files.append(os.path.join(image_folder, filename)) image_files.sort() # 创建PDF c canvas.Canvas(output_pdf, pagesizepage_size) page_width, page_height page_size for image_path in image_files: # 打开图片并调整尺寸适应页面 img Image.open(image_path) img_width, img_height img.size # 计算缩放比例保持宽高比 scale_width page_width * 0.9 / img_width scale_height page_height * 0.9 / img_height scale min(scale_width, scale_height) # 计算居中位置 x (page_width - img_width * scale) / 2 y (page_height - img_height * scale) / 2 # 添加图片到PDF c.drawImage(image_path, x, y, widthimg_width*scale, heightimg_height*scale) c.showPage() # 新的一页 c.save() print(fPDF创建成功: {output_pdf})4.2 PDF到图片的转换有时也需要将PDF转换为图片进行处理from pdf2image import convert_from_path import os def pdf_to_images(pdf_path, output_folder, dpi200): 将PDF转换为图片 # 创建输出文件夹 os.makedirs(output_folder, exist_okTrue) # 转换PDF为图片 images convert_from_path(pdf_path, dpidpi) # 保存图片 for i, image in enumerate(images): image.save(f{output_folder}/page_{i1:03d}.jpg, JPEG) print(f转换完成: {len(images)} 页 - {output_folder}) # 使用前需要安装poppler-utils # Windows: 下载poppler并添加到PATH # Linux: sudo apt-get install poppler-utils # Mac: brew install poppler4.3 PDF页面操作与合并from PyPDF2 import PdfReader, PdfWriter def merge_pdfs(pdf_files, output_path): 合并多个PDF文件 pdf_writer PdfWriter() for pdf_file in pdf_files: pdf_reader PdfReader(pdf_file) for page in pdf_reader.pages: pdf_writer.add_page(page) with open(output_path, wb) as out: pdf_writer.write(out) print(fPDF合并完成: {output_path}) def split_pdf(input_pdf, output_folder, pages_per_split10): 拆分PDF文件 os.makedirs(output_folder, exist_okTrue) pdf_reader PdfReader(input_pdf) total_pages len(pdf_reader.pages) for start_page in range(0, total_pages, pages_per_split): pdf_writer PdfWriter() end_page min(start_page pages_per_split, total_pages) for page_num in range(start_page, end_page): pdf_writer.add_page(pdf_reader.pages[page_num]) output_path f{output_folder}/part_{start_page//pages_per_split 1}.pdf with open(output_path, wb) as out: pdf_writer.write(out) print(fPDF拆分完成: {total_pages}页 - {output_folder})5. 完整的一站式处理流程5.1 设计自动化处理管道将图片处理和PDF处理整合成一个完整的流程import os from pathlib import Path from datetime import datetime class ImageToPDFPipeline: def __init__(self, config): self.config config self.timestamp datetime.now().strftime(%Y%m%d_%H%M%S) def run_pipeline(self): 运行完整处理流程 print(开始图片转PDF处理流程...) # 步骤1: 批量处理图片 processed_images self.batch_process_images() # 步骤2: 转换为PDF if processed_images: pdf_path self.create_pdf(processed_images) print(f流程完成生成PDF: {pdf_path}) return pdf_path else: print(没有找到可处理的图片文件) return None def batch_process_images(self): 批量处理图片 input_folder Path(self.config[input_folder]) temp_folder Path(ftemp_processed_{self.timestamp}) temp_folder.mkdir(exist_okTrue) processor BatchImageProcessor(input_folder, temp_folder) # 根据配置构建处理操作 operations [] if self.config.get(resize, False): operations.append(resize_operation( self.config.get(max_width, 1200), self.config.get(max_height, 800) )) if self.config.get(watermark, False): operations.append(watermark_operation( self.config.get(watermark_text, Processed), self.config.get(watermark_position, (20, 20)) )) # 执行批量处理 success_count processor.batch_process(operations) if success_count 0: return temp_folder else: return None def create_pdf(self, images_folder): 创建PDF文件 output_pdf foutput_{self.timestamp}.pdf if self.config.get(pdf_engine, img2pdf) img2pdf: images_to_pdf_simple(images_folder, output_pdf) else: images_to_pdf_reportlab(images_folder, output_pdf) # 清理临时文件 if self.config.get(cleanup, True): import shutil shutil.rmtree(images_folder) return output_pdf # 配置示例 config { input_folder: input_images, resize: True, max_width: 1200, max_height: 800, watermark: True, watermark_text: Confidential - 2024, watermark_position: (30, 30), pdf_engine: img2pdf, cleanup: True } # 运行流程 pipeline ImageToPDFPipeline(config) result_pdf pipeline.run_pipeline()5.2 添加进度显示和日志记录增强用户体验添加进度显示和详细的日志记录import logging from tqdm import tqdm class EnhancedImageProcessor(BatchImageProcessor): def __init__(self, input_folder, output_folder): super().__init__(input_folder, output_folder) self.setup_logging() def setup_logging(self): 设置日志记录 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(image_processing.log), logging.StreamHandler() ] ) self.logger logging.getLogger(__name__) def batch_process(self, operations, output_suffix_processed): 增强的批量处理带进度显示 image_files self.get_image_files() success_count 0 self.logger.info(f开始处理 {len(image_files)} 张图片) with tqdm(totallen(image_files), desc处理进度) as pbar: for input_path in image_files: output_filename f{input_path.stem}{output_suffix}{input_path.suffix} output_path self.output_folder / output_filename if self.process_single_image(input_path, output_path, operations): success_count 1 self.logger.info(f成功处理: {input_path.name}) else: self.logger.error(f处理失败: {input_path.name}) pbar.update(1) self.logger.info(f批量处理完成: {success_count}/{len(image_files)} 成功) return success_count6. 常见问题与解决方案6.1 图片处理常见问题问题1内存不足错误当处理大量高分辨率图片时可能会遇到内存问题。解决方案def memory_efficient_process(image_path, output_path, operations): 内存友好的处理方式 try: # 分块处理大图片 with Image.open(image_path) as img: # 如果图片太大先缩小再处理 if img.size[0] * img.size[1] 2000 * 2000: img.thumbnail((2000, 2000), Image.Resampling.LANCZOS) for operation in operations: img operation(img) # 保存时优化 img.save(output_path, optimizeTrue, quality85) except Exception as e: print(f处理失败: {e})问题2格式兼容性问题某些格式转换可能导致颜色失真或透明度丢失。解决方案def safe_format_conversion(img, target_format): 安全的格式转换 if target_format.upper() JPEG: # JPEG不支持透明度需要转换 if img.mode in (RGBA, LA, P): background Image.new(RGB, img.size, (255, 255, 255)) if img.mode P: img img.convert(RGBA) background.paste(img, maskimg.split()[-1]) img background elif img.mode ! RGB: img img.convert(RGB) return img6.2 PDF处理常见问题问题1中文显示乱码在添加中文水印或文本时可能出现编码问题。解决方案def setup_chinese_font(): 设置中文字体支持 try: # 尝试常见的中文字体路径 font_paths [ C:/Windows/Fonts/simhei.ttf, # Windows /System/Library/Fonts/PingFang.ttc, # Mac /usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf # Linux ] for font_path in font_paths: if os.path.exists(font_path): return ImageFont.truetype(font_path, 36) except: pass # 回退到默认字体 return ImageFont.load_default()问题2PDF生成大小异常图片转PDF后文件过大。解决方案def optimize_pdf_size(image_folder, output_pdf, max_size_mb10): 优化PDF文件大小 temp_pdf temp.pdf images_to_pdf_simple(image_folder, temp_pdf) # 检查文件大小 file_size os.path.getsize(temp_pdf) / (1024 * 1024) # MB if file_size max_size_mb: print(fPDF文件过大 ({file_size:.1f}MB)进行优化...) # 使用更低的图片质量重新生成 optimize_images_for_pdf(image_folder, max_size_mb) images_to_pdf_simple(image_folder, output_pdf) os.remove(temp_pdf) else: os.rename(temp_pdf, output_pdf)7. 高级功能与性能优化7.1 多线程并行处理对于大量图片处理使用多线程可以显著提高效率import concurrent.futures from threading import Lock class ParallelImageProcessor(BatchImageProcessor): def __init__(self, input_folder, output_folder, max_workers4): super().__init__(input_folder, output_folder) self.max_workers max_workers self.lock Lock() self.success_count 0 def parallel_batch_process(self, operations, output_suffix_processed): 并行批量处理 image_files self.get_image_files() with concurrent.futures.ThreadPoolExecutor(max_workersself.max_workers) as executor: # 提交所有任务 future_to_file { executor.submit(self.process_single_image, file, self.output_folder / f{file.stem}{output_suffix}{file.suffix}, operations): file for file in image_files } # 处理完成的任务 for future in concurrent.futures.as_completed(future_to_file): file future_to_file[future] try: success future.result() if success: with self.lock: self.success_count 1 except Exception as e: print(f处理失败 {file.name}: {e}) print(f并行处理完成: {self.success_count}/{len(image_files)} 成功) return self.success_count7.2 图片质量智能优化根据图片内容自动优化处理参数def adaptive_compression(img, target_size_kb500): 自适应压缩达到目标文件大小 original_quality 95 min_quality 30 # 临时保存以检查大小 temp_path temp_quality_check.jpg for quality in range(original_quality, min_quality - 1, -5): img.save(temp_path, optimizeTrue, qualityquality) file_size_kb os.path.getsize(temp_path) / 1024 if file_size_kb target_size_kb: break # 清理临时文件 if os.path.exists(temp_path): os.remove(temp_path) return quality def smart_processing_pipeline(image_path, output_path): 智能处理管道 with Image.open(image_path) as img: # 分析图片特征 width, height img.size file_size os.path.getsize(image_path) / 1024 # KB # 根据特征决定处理策略 if file_size 1000: # 大于1MB的图片需要压缩 if width 2000 or height 2000: img.thumbnail((1200, 1200), Image.Resampling.LANCZOS) # 自适应质量调整 optimal_quality adaptive_compression(img, 500) img.save(output_path, optimizeTrue, qualityoptimal_quality) else: # 小文件直接保存 img.save(output_path, optimizeTrue)8. 实战案例企业宣传材料自动化生成8.1 场景需求分析某市场部门需要每周生成产品宣传PDF包含批量处理产品图片统一尺寸、添加水印按产品分类组织图片生成专业的PDF文档自动命名和版本管理8.2 完整实现代码import os from pathlib import Path from datetime import datetime import json class MarketingMaterialGenerator: def __init__(self, config_fileconfig.json): self.load_config(config_file) self.setup_folders() def load_config(self, config_file): 加载配置文件 with open(config_file, r, encodingutf-8) as f: self.config json.load(f) def setup_folders(self): 设置文件夹结构 self.base_dir Path(self.config[base_directory]) self.raw_images_dir self.base_dir / raw_images self.processed_dir self.base_dir / processed self.output_dir self.base_dir / output for folder in [self.raw_images_dir, self.processed_dir, self.output_dir]: folder.mkdir(parentsTrue, exist_okTrue) def generate_weekly_materials(self): 生成每周宣传材料 week_str datetime.now().strftime(%Y-%U) print(f开始生成第{week_str}周宣传材料...) # 处理每个产品类别的图片 for category in self.config[categories]: self.process_category(category, week_str) print(宣传材料生成完成) def process_category(self, category, week_str): 处理单个产品类别 category_input self.raw_images_dir / category[name] category_output self.processed_dir / category[name] if not category_input.exists(): print(f警告: {category_input} 不存在跳过) return # 批量处理图片 processor EnhancedImageProcessor(category_input, category_output) operations self.build_operations(category) processor.batch_process(operations) # 生成PDF pdf_name f{category[name]}_{week_str}.pdf pdf_path self.output_dir / pdf_name images_to_pdf_simple(category_output, pdf_path) print(f生成: {pdf_path}) # 配置文件示例 config_example { base_directory: marketing_materials, categories: [ { name: 电子产品, resize: True, max_width: 1200, watermark: True, watermark_text: 产品图 - 严禁外传 }, { name: 服装, resize: True, max_width: 800, watermark: True, watermark_text: 样品图 - 内部使用 } ] } # 保存配置文件 with open(config.json, w, encodingutf-8) as f: json.dump(config_example, f, ensure_asciiFalse, indent2) # 运行生成器 generator MarketingMaterialGenerator() generator.generate_weekly_materials()这套完整的图片批量处理与PDF生成方案从基础操作到企业级应用都提供了实用的解决方案。通过模块化设计和可配置的参数可以灵活适应不同的业务需求。建议在实际使用前先用测试数据进行验证确保处理效果符合预期。

相关新闻

最新新闻

日新闻

周新闻

月新闻