From 3f33ae41655b12f095a3140509b0cb29d8aba9c4 Mon Sep 17 00:00:00 2001 From: Ian-Jhon Date: Wed, 15 Oct 2025 17:10:34 +0800 Subject: [PATCH 1/4] Update draw_pdf.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1, 改进self.OP(针对页面),从reportlab.lib.units 导入长度单位毫米,并将self.OP定义为1mm,是页面尺寸符合实际大小。 2, 改进draw_chars函数(针对印章): 对有CTM的字符位置,改用reportlab中canvas.transform方法对pdf页面先进行变换再写入字符,使印章文字位置更准确。 3, 改进draw_line函数(针对印章): 对彩色线条,通过提取StrokeColor得到正确的颜色。 4, 改进draw_pdf函数(针对印章): 绘制顺序由文本(draw_chars)为先调整为线条(draw_line)为先,这样可以使印章线条在最下面但印章始终文字保持在最上面。 --- easyofd/draw/draw_pdf.py | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/easyofd/draw/draw_pdf.py b/easyofd/draw/draw_pdf.py index cd45b1c..bf78252 100644 --- a/easyofd/draw/draw_pdf.py +++ b/easyofd/draw/draw_pdf.py @@ -16,7 +16,7 @@ from reportlab.lib.pagesizes import A4 from reportlab.lib.utils import ImageReader from reportlab.pdfgen import canvas - +from reportlab.lib.units import mm from easyofd.draw.font_tools import FontTool from .find_seal_img import SealExtract @@ -32,8 +32,8 @@ def __init__(self, data, *args, **kwargs): assert data, "未输入ofd解析结果" self.data = data self.author = "renoyuan" - self.OP = 200 / 25.4 - # self.OP = 1 + #self.OP = 200 / 25.4 + self.OP = 1*mm self.pdf_uuid_name = self.data[0]["pdf_name"] self.pdf_io = BytesIO() self.SupportImgType = ("JPG", "JPEG", "PNG") @@ -187,16 +187,12 @@ def draw_chars(self, canvas, text_list, fonts, page_size): # print("Y",page_size[3]) # print("x",page_size[2]) # if line_dict.get("Glyphs_d") and FontFilePath.get(line_dict["font"]) and font_f not in FONTS: - if False: # 对于自定义字体 写入字形 drawPath 性能差暂时作废 - Glyphs = [int(i) for i in line_dict.get("Glyphs_d").get("Glyphs").split(" ")] - for idx, Glyph_id in enumerate(Glyphs): - _cahr_x = float(x_list[idx]) * self.OP - _cahr_y = (float(page_size[3]) - (float(y_list[idx]))) * self.OP - imageFile = draw_Glyph(FontFilePath.get(line_dict["font"]), Glyph_id, text[idx]) - - # font_img_info.append((FontFilePath.get(line_dict["font"]), Glyph_id,text[idx],_cahr_x,_cahr_y,-line_dict["size"]*Op*2,line_dict["size"]*Op*2)) - c.drawImage(imageFile, _cahr_x, _cahr_y, -line_dict["size"] * self.OP * 2, - line_dict["size"] * self.OP * 2) + if CTM: + #print(f"text: {text}, CTM_info:",CTM_info) + c.saveState() + c.transform(float(CTMS[0]), -1*float(CTMS[1]), -1*float(CTMS[2]), float(CTMS[3]), (pos[0]+float(CTMS[4]))*self.OP, (page_size[3]-pos[1]-float(CTMS[5]))*self.OP) + c.drawString(float(X)*self.OP, -float(Y)*self.OP, text) + c.restoreState() else: if len(text) > len(x_list) or len(text) > len(y_list): text = re.sub("[^\u4e00-\u9fa5]", "", text) @@ -551,8 +547,8 @@ def convert_coord(p_list, direction, page_size, pos): for line in line_list: path = canvas.beginPath() Abbr = line.get("AbbreviatedData").split(" ") # AbbreviatedData - color = line.get("FillColor", [0, 0, 0]) - + #color = line.get("FillColor", [0, 0, 0]) + color = line.get("StrokeColor", "").split(" ") #StrokeColor String relu_list = match_mode(Abbr) # TODO 组合 relu_list 1 M L 直线 2 M B*n 三次贝塞尔线 3 M Q*n 二次贝塞尔线 @@ -697,15 +693,14 @@ def draw_pdf(self): if img_list: self.draw_img(c, img_list, images, page_size) - # 写入文本 - if text_list: - - self.draw_chars(c, text_list, fonts, page_size) - # 绘制线条 if line_list: self.draw_line(c, line_list, page_size) + # 写入文本 + if text_list: + self.draw_chars(c, text_list, fonts, page_size) + # 绘制签章 if signatures_page_id: self.draw_signature(c, signatures_page_id.get(pg_no), page_size) From f61262c037ba7da40093cd81456a3b036a0dec8e Mon Sep 17 00:00:00 2001 From: Ian-Jhon Date: Wed, 15 Oct 2025 17:13:13 +0800 Subject: [PATCH 2/4] Update file_signature_parser.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改进SignatureFileParser函数(针对火车票): 将StampAnnot_res_key设置为传入参数,且默认为 "ofd:StampAnnot" --- easyofd/parser_ofd/file_signature_parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easyofd/parser_ofd/file_signature_parser.py b/easyofd/parser_ofd/file_signature_parser.py index f86093a..0dd55e0 100644 --- a/easyofd/parser_ofd/file_signature_parser.py +++ b/easyofd/parser_ofd/file_signature_parser.py @@ -38,10 +38,10 @@ class SignatureFileParser(FileParserBase): 签章信息 """ - def __call__(self, prefix=""): + def __call__(self, prefix="", StampAnnot_res_key="ofd:StampAnnot"): info = {} StampAnnot_res: list = [] - StampAnnot_res_key = "ofd:StampAnnot" + #StampAnnot_res_key = "ofd:StampAnnot" self.recursion_ext(self.xml_obj, StampAnnot_res, StampAnnot_res_key) From 28dc1b09be3ca8ec693921bb06d778c3cd6e2590 Mon Sep 17 00:00:00 2001 From: Ian-Jhon Date: Wed, 15 Oct 2025 17:17:43 +0800 Subject: [PATCH 3/4] Update ofd_parser.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改进Signature解析流程(针对火车票): 先用StampAnnot_res_key = "ofd:StampAnnot"运行SignatureFileParser函数,签章信息的标签名不为"ofd:StampAnnot",如火车票的为'ofd:Signature',则从signature_xml_obj.keys()获取第一个key为sign_key传入SignatureFileParser。 --- easyofd/parser_ofd/ofd_parser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/easyofd/parser_ofd/ofd_parser.py b/easyofd/parser_ofd/ofd_parser.py index 61c5982..478d0f0 100644 --- a/easyofd/parser_ofd/ofd_parser.py +++ b/easyofd/parser_ofd/ofd_parser.py @@ -306,6 +306,9 @@ def parser(self, ): # print(BaseLoc) prefix = BaseLoc.split("/")[0] signatures_info = SignatureFileParser(signature_xml_obj)(prefix=prefix) + if len(signatures_info)==0: + sign_key = list(signature_xml_obj.keys())[0] + signatures_info = SignatureFileParser(signature_xml_obj)(prefix=prefix, StampAnnot_res_key=sign_key) # print(signatures_info) logger.debug(f"signatures_info {signatures_info}") PageRef = signatures_info.get("PageRef") From 58aee7ac2ba8b598f7b8121e3dcafbb8919f8045 Mon Sep 17 00:00:00 2001 From: Ian-Jhon Date: Wed, 15 Oct 2025 19:12:24 +0800 Subject: [PATCH 4/4] Update draw_pdf.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 升级draw_annotation,Annotation.xml中除了ImgageObject还有TextObject (有些发票的annotation包含了“下载次数:”),改进以后,只要ImgageObject对应的"ResourceID"存在就会将其添加到pdf中,而对于没有"ResourceID"的TextObject,即使解析为一个ImgageObject,也不会添加图片到pdf中。 --- easyofd/draw/draw_pdf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easyofd/draw/draw_pdf.py b/easyofd/draw/draw_pdf.py index bf78252..55658da 100644 --- a/easyofd/draw/draw_pdf.py +++ b/easyofd/draw/draw_pdf.py @@ -637,7 +637,8 @@ def draw_annotation(self, canvas, annota_info, images, page_size): """ img_list = [] for key, annotation in annota_info.items(): - if annotation.get("AnnoType").get("type") == "Stamp": + #if annotation.get("AnnoType").get("type") == "Stamp": + if annotation.get("ImgageObject").get("ResourceID"): pos = annotation.get("ImgageObject").get("Boundary","").split(" ") pos = [float(i) for i in pos] if pos else [] wrap_pos = annotation.get("Appearance").get("Boundary","").split(" ")