如何获取EPS文件元素边界框及检测EPS/PDF中的矢量元素
这两个问题都是处理EPS/PDF矢量内容时的常见需求,我来一步步帮你解决:
要提取EPS里每个元素的边界框,最可靠的方式是借助Ghostscript结合自定义PostScript脚本——因为EPS本质是PostScript的子集,直接解析文本容易遗漏复杂元素(比如贝塞尔曲线、变换后的图形)。
方法1:用Ghostscript脚本跟踪每个元素的BBox
你可以写一个简单的PostScript脚本,重定义核心绘图命令(比如moveto、lineto、fill、stroke),在执行绘图操作时记录坐标并计算边界框:
%!PS % 保存原始绘图命令 /oldmoveto { moveto } bind def /oldlineto { lineto } bind def /oldcurveto { curveto } bind def /oldfill { fill } bind def /oldstroke { stroke } bind def % 初始化边界框变量(用极值初始化) /minx 10000 def /maxx -10000 def /miny 10000 def /maxy -10000 def % 更新边界框的辅助函数 /updatebbox { dup minx lt { exch minx exch def } if dup maxx gt { exch maxx exch def } if } bind def % 重定义moveto,记录起点坐标 /moveto { dup updatebbox % 处理y坐标 3 1 roll dup updatebbox % 处理x坐标 oldmoveto } bind def % 重定义lineto,记录终点坐标 /lineto { dup updatebbox 3 1 roll dup updatebbox oldlineto } bind def % 重定义curveto,记录贝塞尔曲线的四个控制点 /curveto { dup updatebbox 3 1 roll dup updatebbox 3 1 roll dup updatebbox 3 1 roll dup updatebbox oldcurveto } bind def % 填充前输出当前元素的BBox并重置变量 /fill { (Element BBox: ) print minx ( ) print maxx ( ) print miny ( ) print maxy == /minx 10000 def /maxx -10000 def /miny 10000 def /maxy -10000 def oldfill } bind def % 描边前输出当前元素的BBox并重置变量 /stroke { (Element BBox: ) print minx ( ) print maxx ( ) print miny ( ) print maxy == /minx 10000 def /maxx -10000 def /miny 10000 def /maxy -10000 def oldstroke } bind def % 执行目标EPS文件 (your_input.eps) run
将脚本保存为track_bbox.ps,然后用Ghostscript运行:
gs -q -dNOPAUSE -dBATCH track_bbox.ps
运行后会输出每个填充/描边元素的边界框,格式类似Element BBox: 10 200 50 250(对应minX maxX minY maxY)。
方法2:获取整个EPS的全局边界框
如果只需要整个EPS文件的整体边界框,直接用Ghostscript的bbox设备即可:
gs -q -dNOPAUSE -dBATCH -sDEVICE=bbox your_input.eps
输出会包含%%BoundingBox: minX minY maxX maxY等信息。
你已经用pdftocairo转EPS并移除了文本和图像块,接下来可以通过以下几种方式验证是否还有剩余矢量内容:
方法1:用Ghostscript检查绘图指令
Ghostscript的nullpage设备会执行EPS的所有命令但不输出图像,我们可以捕获它的输出,检查是否存在核心矢量绘图命令:
gs -q -dNOPAUSE -dBATCH -sDEVICE=nullpage -f processed.eps 2>&1 | grep -E "(stroke|fill|lineto|curveto|rectfill|rectstroke)"
如果命令有输出,说明仍有矢量元素需要处理;如果无输出,大概率是空白画布。
方法2:直接解析EPS文本内容
EPS是纯文本格式(大部分情况下),可以用grep过滤掉注释行(以%开头),查找剩余的绘图命令:
grep -v "^%" processed.eps | grep -E "(moveto|lineto|curveto|closepath|stroke|fill|rectfill|rectstroke)"
如果匹配到任何行,说明画布上还有矢量元素。
方法3:生成极小图像验证
用Ghostscript生成1x1像素的PPM图像,检查是否有非白色像素:
# 生成1x1的PPM图像 gs -q -dNOPAUSE -dBATCH -sDEVICE=ppm -r1x1 -o test.ppm processed.eps # 检查像素颜色 convert test.ppm -threshold 50% -format "%[pixel:u.p{0,0}]" info:
如果输出是white,说明画布空白;如果是其他颜色(比如black),说明还有矢量内容。
补充:关于你现有命令的小提示
你用sed '/^8 dict dup begin$/,/^Q$/ c Q'移除图像块的方式,只适用于pdftocairo生成的EPS格式(它的图像块结构比较固定)。如果遇到其他工具生成的EPS,可能需要调整匹配规则,比如查找BI/ID/EI块(PostScript标准的图像标记):
sed '/BI/,/EI/ d' processed.eps
内容的提问来源于stack exchange,提问作者clarkk

