CV_LOAD_IMAGE_COLOR 和 CV_BGR2RGBA找不到定义

添加下面头文件

#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/imgproc/types_c.h"

以下是file_compositor.py的完整代码:#文件合成模块 import os import tempfile import logging import csv import cv2 from PIL import Image, ImageDraw, ImageFont from pypdf import PdfReader, PdfWriter from core.font_manager import FontManager from utils.image_utils import pdf_to_image from typing import List, Dict, Tuple, Union, Optional, Any # 尝试提前导入,避免运行时导入带来的警告 try: import qrcode except ImportError: qrcode = None logger = logging.getLogger(__name__) def _generate_qrcode(data: str, region: Dict[str, Any]): """生成二维码 :param data: 二维码数据 :param region: 区域配置 :return: PIL 图像对象 """ if not qrcode: raise ImportError("qrcode 模块安装,请先通过 pip install qrcode 安装") # 获取二维码大小(使用区域宽度) size = int(region.get('rect').get('width', lambda: 100)()) # 假设 rect 是 QGIS 或 PyQt 的 Rect 对象模拟字典行为 qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=0, ) qr.add_data(data) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") return img.resize((size, size)) class FileCompositor: def __init__(self, data_path: Optional[str] = None, font_manager: Optional[FontManager] = None): self.data_path = data_path or os.path.join(os.path.dirname(__file__), "../../../data") self.font_manager = font_manager or FontManager(self.data_path) self.temp_dir = tempfile.mkdtemp(prefix="auto_print_") logger.info(f"合成引擎初始化,临时目录: {self.temp_dir}") def composite( self, template_path: str, regions: List[Dict[str, Any]], mapping: Dict[str, str], data_source: Union[str, Any], # DataFrame 或 CSV路径 output_path: str, logo_path: Optional[str] = None, spot_color_path: Optional[str] = None ) -> Tuple[bool, List[str]]: """ 执行合成操作 :param template_path: 模板文件路径 :param regions: 区域配置列表 :param mapping: 字段映射字典 {区域名: 字段名} :param data_source: 数据源(CSV文件路径或DataFrame) :param output_path: 输出文件路径 :param logo_path: Logo文件路径(可选) :param spot_color_path: 专色层文件路径(可选) :return: (成功标志, 日志信息) """ logs: List[str] = [] success = True # 解析数据源 try: data_rows = self._parse_data_source(data_source) logs.append(f"加载数据: {len(data_rows)}行记录") except Exception as e: logs.append(f"数据加载失败: {str(e)}") return False, logs # 准备输出PDF output_pdf = PdfWriter() total_pages = len(data_rows) # 处理每一行数据 for i, row in enumerate(data_rows): try: # 创建当前页 page_image = self._create_page( template_path, regions, mapping, row, logo_path, spot_color_path ) # 保存为PDF页面 page_path = os.path.join(self.temp_dir, f"page_{i}.pdf") page_image.save(page_path, "PDF", resolution=300) # 添加到输出PDF with open(page_path, "rb") as f: page_reader = PdfReader(f) output_pdf.add_page(page_reader.pages[0]) logs.append(f"页面 {i + 1}/{total_pages} 合成成功") except Exception as e: logs.append(f"页面 {i + 1} 合成失败: {str(e)}") success = False # 保存最终PDF if success: try: with open(output_path, "wb") as f: output_pdf.write(f) logs.append(f"输出文件已保存: {output_path}") except (IOError, OSError, PermissionError) as e: logs.append(f"保存输出文件失败: {str(e)}") success = False return success, logs def _parse_data_source(self, data_source: Union[str, Any]) -> List[Dict[str, Any]]: """解析数据源为行记录列表 :param data_source: 数据源(CSV文件路径或DataFrame) :return: 数据行列表 """ if isinstance(data_source, str): with open(data_source, 'r', encoding='utf-8') as f: reader = csv.DictReader(f) return list(reader) elif hasattr(data_source, 'to_dict'): # DataFrame return data_source.to_dict('records') else: raise ValueError("不支持的数据源类型") def _create_page( self, template_path: str, regions: List[Dict[str, Any]], mapping: Dict[str, str], data_row: Dict[str, str], logo_path: Optional[str], spot_color_path: Optional[str] ) -> Image.Image: """创建单个页面图像 :param template_path: 模板文件路径 :param regions: 区域配置列表 :param mapping: 字段映射字典 :param data_row: 单行数据 :param logo_path: Logo文件路径 :param spot_color_path: 专色层文件路径 :return: PIL图像对象 """ # 加载模板 if template_path.lower().endswith('.pdf'): template_img = pdf_to_image(template_path) if template_img is None: raise ValueError("无法加载PDF模板") template_pil = Image.fromarray(cv2.cvtColor(template_img, cv2.COLOR_BGR2RGB)) else: template_pil = Image.open(template_path) canvas = template_pil.copy() # 应用专白层(如果有) if spot_color_path: spot_color_img = self._load_spot_color(spot_color_path) if spot_color_img: canvas = self._apply_spot_color(canvas, spot_color_img) # 应用Logo(如果有) if logo_path: logo_img = self._load_logo(logo_path) if logo_img: canvas.paste(logo_img, (50, 50), logo_img) draw = ImageDraw.Draw(canvas) # 处理所有区域 for region in regions: region_name = region.get('name', '命名区域') region_type = region.get('type') rect = region.get('rect', {}) pos = region.get('pos', (0, 0)) field_name = mapping.get(region_name) if not field_name: continue value = data_row.get(field_name, "") if not value: continue x = rect.get('x', lambda: 0)() + pos[0] if isinstance(pos, tuple) else 0 y = rect.get('y', lambda: 0)() + pos[1] if isinstance(pos, tuple) else 0 width = rect.get('width', lambda: 100)() height = rect.get('height', lambda: 100)() # 根据区域类型处理 if region_type == 'text': self._render_text(draw, value, (int(x), int(y)), region, data_row) elif region_type == 'qrcode': try: qr_img = _generate_qrcode(value, region) canvas.paste(qr_img, (int(x), int(y))) except ImportError as e: logger.warning(f"二维码渲染失败: 缺少模块 {e}") elif region_type == 'image': img = self._load_image(value) if img: img = self._resize_image(img, (int(width), int(height))) canvas.paste(img, (int(x), int(y))) return canvas def _render_text( self, draw: ImageDraw.ImageDraw, text: str, position: Tuple[int, int], region: Dict[str, Any], data_row: Dict[str, str] ): """渲染文本区域 :param draw: ImageDraw 对象 :param text: 要渲染的文本 :param position: 文本位置 (x, y) :param region: 区域配置字典 :param data_row: 当前数据行 """ # 获取字体配置 font_name = region.get('font', 'SimHei') font_size = region.get('font_size', 12) # 获取字体对象 font = self.font_manager.get_font(f"{font_name},{font_size}") if not font: logger.warning(f"字体加载失败: {font_name}, 将使用默认字体") font = ImageFont.load_default() # 获取颜色 color_str = region.get('color', "0,0,0") font_color = self._parse_color(color_str) # 动态字段颜色 color_field = region.get('color_field') if color_field and color_field in data_row: font_color = self._parse_color(data_row[color_field]) # 绘制文本 draw.text(position, text, fill=font_color, font=font) @staticmethod def _load_image(image_path: str) -> Optional[Image.Image]: """加载图片""" if not os.path.exists(image_path): return None try: return Image.open(image_path) except Exception as e: logging.error(f"加载图片失败: {str(e)}") return None @staticmethod def _resize_image(img: Image.Image, size: Tuple[int, int]) -> Image.Image: """调整图片大小""" try: resample_method = Image.Resampling.LANCZOS except AttributeError: resample_method = Image.LANCZOS return img.resize(size, resample_method) @staticmethod def _load_spot_color(path: str) -> Optional[Image.Image]: """加载专色层""" try: return Image.open(path) except Exception as e: logging.error(f"加载专色层失败: {str(e)}") return None @staticmethod def _apply_spot_color( canvas: Image.Image, spot_img: Image.Image ) -> Image.Image: """应用专色层到画布""" if spot_img.size != canvas.size: try: resample_method = Image.Resampling.LANCZOS except AttributeError: resample_method = Image.LANCZOS spot_img = spot_img.resize(canvas.size, resample_method) mask = spot_img.convert("L") canvas.paste(spot_img, (0, 0), mask) return canvas @staticmethod def _load_logo(path: str) -> Optional[Image.Image]: """加载Logo""" try: logo = Image.open(path) if logo.mode != 'RGBA': logo = logo.convert('RGBA') return logo except Exception as e: logging.error(f"加载Logo失败: {str(e)}") return None @staticmethod def _parse_color(color_str: str) -> Tuple[int, int, int]: """解析颜色字符串为RGB元组""" if color_str.startswith('#'): hex_color = color_str.lstrip('#') return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4)) else: return tuple(map(int, color_str.split(','))) # type: ignore 运行后出现以下警告,请帮我逐一进行解决,并输出完整的修改后的代码
07-15
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值