PPT 图片差异为何会漏掉“删掉一张相同图片”:从集合比较改为计数比较
比较两份 PPT 时,“图片有没有变”看起来可以用内容哈希解决:抽取每张图片,计算哈希,然后比较旧版和新版的哈希集合。但图片是可以重复出现的。同一页贴了两份完全一样的图,只删除其中一份时,哈希集合仍然是同一个集合。若实现只比较集合,就会把一次真实的删除判成没有图片变化。
我用一个合成文件复现了这个边界:旧版只有一页,标题下有两张字节完全相同的 20×20 红色 PNG;新版保留其中一张,其余不变。当前脚本的摘要报告却显示“图片变化 0、修改页面 0”。这个结果不代表用户没改过文件,只说明检测逻辑没保留重复图片的出现次数。测试文件不含真实文档或个人资料。
集合和多重集合的差别
假设每张图的内容哈希都是 A:
旧版:[A, A] → 集合 {A}
新版:[A] → 集合 {A}
旧版集合减新版集合、新版集合减旧版集合都为空。把列表转为哈希到图片的字典也一样:第二张图片会覆盖第一张对应的键。这个结构适合回答“某种图片内容是否存在”,却不能回答“同一内容出现了几次”。
对此,最小且明确的改法是按哈希计数。Python 的 Counter 可以直接表达多重集合差集:
from collections import Counter
old_hashes = ["A", "A"]
new_hashes = ["A"]
removed = Counter(old_hashes) - Counter(new_hashes)
added = Counter(new_hashes) - Counter(old_hashes)
assert removed == Counter({"A": 1})
assert not added
这段计算只回答数量差异。报告若还需要展示“删掉的是页面上哪一张”,则要保留每个哈希对应的出现列表,并按位置或形状 ID 匹配:先把旧、新图片按哈希分组,再从对应组里配对相同位置的实例;剩余的旧实例记为删除,剩余的新实例记为新增。不能先用字典覆盖同哈希实例,再尝试恢复位置信息。
复现与验收
用 python-pptx 可以在同一页放入同一份 PNG 字节两次,保存为旧版,再只放一次保存为新版。执行差异工具时,应至少看到删除一张图片,以及该页存在修改。验收不应仅检查总页数,因为两个文件都仍然只有一页。
建议补四组边界用例:[A,A] → [A] 应报告删除 1;[A] → [A,A] 应报告新增 1;[A,A] → [A,A] 应报告无变化;[A,B] → [A,C] 应分别报告 B 删除与 C 新增。若工具还区分“图片移动”与“图片替换”,再加入同内容跨位置和不同内容同位置的例子,避免把数量变化与位置变化混为一谈。
更一般地说,页面中的图片、表格单元、批注等对象都可能重复。选择数据结构前先问清楚需求:只关心“是否存在”,可以用集合;关心“新增或删除多少个”,就必须保留计数;关心“具体哪一个实例发生变化”,还需要对象级匹配。这个区别决定了差异报告是否可信。
复现记录:GitCode Issue #37。
- 点赞
- 收藏
- 关注作者
评论(0)