关于从学术论文PDF中提取Form Xobjects格式图片的技术咨询
从PDF中提取LaTeX嵌入的Form Xobject图片相关问题
我想从PDF里提取由LaTeX编译器并入的原独立PDF图片,这类图片在PDF里是Form Xobjects格式。以某公开论文为例,用文本编辑器查看能看到类似如下的Form Xobject片段:
152 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./graphs/spectrum.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 203 0 R /BBox [135.2168 266.4003 592.6775 381.8708] /Resources << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 204 0 R >>/Font << /TT2 205 0 R>> >> /Length 1052 /Filter /FlateDecode >> stream x½VËn7¼ó+:/{6ÖRdóm'N`Áß-ƒÓ"‚Xdòû®&çAíZk xˆœN³º«ºÉ[zK·d™Š¡3yÇôñú‹þ£ó‹;Kû;²õïn/«3ÝPʦÎ>Ô¾ü€wªŽ×tõÍáIülõdó“x7š£üfÞ'rÆØ#§@Ó;mr‰ä8êì9© ÙkÃi¶E¸îlžXlÝ·Õ–`»î¬¶èØ<ZWtJ¡md]šöeí¸ô†P?#€[e]Bôjqäl[µ€˜,TÔÞ8Gn²Y_¦í&O‹eÙo± fG3î9_“e¯®»ì´ #x9içí"RrZ^ˆÞRADµïm"—ÎSÛžf†&¾Ë ù™rUHyÚoò´XÚ~Hr·jB5{£QË~S|{0}E%p ÿ!ù[\\®(îòBÝb‰6r)Œ*1øÛÞ7YŸuŽ6‘KV—d˜ö7uTSŽñ å$S}Íx64O¯é…%žˆ\¶dßžebƒ‡¶´eÇ:‹÷W;e³S;I¥vøµ/ºöÁÐî†Îw;Fл+zGÃ?n 8~Â`høÓð†¨†'ú›voèõ®ú!ìÃQ`@xÙw8B¢êÇSì\hx?là㦿"XÉ=Û Eí©Wsê-Ƈ€4¢ôÇùœñ£äæœQËÞš8æ\ÜŽ9_õ(ç÷bUÇÚ“ÎlµwYfûñÉ~v~[²‘sPV?@® :¨<` €ÿ[¬H4èº/‡2œA—tHšK¬£c·ÂÈ€: éöœÐ!k)5ÒêZ‘ÞçZC @¹i@‚¶-ðû÷”8ë´ (AÙ,¢Xq¤ÿïEIÉ:ù€¶~L ›’mi”´ùÒ’VÄ4¥äòg(AÎK‰`º³ äÉF ?,2U¨Ò"ØA°X‰Ê[¼|˜*%Ú]¥j©_>—.‰ƒQ²3:¸H6h `B“>Ä´R0¾àZÊrrtí˹Q¦µ`Æù×·/_:t¼„oOh_QêB‚ÌjH`…†ÜX(søàíùaø}õ“qª¦†6Õð ”Øz`@/*/6 \üV;š ÅC¥4qÒƒ²!àtÇY¶åÌÚg«’³µ”G«øwHbÀŽÒ_å„e% ä 0"‡oÓ®œºÒt14yXÏÁàà΂‹×|=æKÉ2ƒ}MW‹ŠÐâ„° HQâ€?ú"X†ªÔј¨w`OPßÓ3); ‘‹‹URk·‡³éúØ üì:´[£›îÓBøBHâCú€ì‚È€æ¾mõgOÌÛOR›Œ endstream endobj
这个片段对应论文里的图1。我试过用mutool extract paper.pdf提取,但只拿到字体文件;后来尝试渲染页面再用/BBox提取Pixmap,脚本如下:
var pdf_path = "paper.pdf" var doc = new Document(pdf_path); var page = doc.loadPage(1); var submap = new Pixmap(DeviceRGB, [135, 266, 592, 381], true) var dev = new DrawDevice(Identity, submap) page.run(dev, Identity, true) submap.saveAsPNG("result.png")
但提取出的PNG位置不对,对BBox的用法也有疑问,现在有三个问题:
- 上述代码片段包含了原“spectrum.pdf”的全部数据吗?
- 能否将这类Form Xobjects提取为独立的PDF文件?
- 如何计算这类图片在PDF中的最终绝对位置?
问题解答
1. 代码片段是否包含原PDF的全部数据?
是的,这个Form Xobject的stream部分就是原spectrum.pdf经过Flate压缩后的全部视觉数据,但要注意:
- 它依赖主PDF里的关联资源(比如片段中
/Resources引用的颜色空间、字体),这些资源存储在主PDF的其他对象中,单独取出stream无法直接还原完整内容。 - LaTeX嵌入原PDF时,可能已经对其做了裁剪、格式转换等处理,提取出的内容和原始独立PDF可能存在细微差异,但所有构成图像的核心数据都在这个stream里。
2. 能否提取为独立PDF?
可以,但需要手动构造新PDF文件,核心步骤如下:
- 解压Form Xobject的stream:用
mutool clean -d paper.pdf -命令可解压PDF中所有流,找到对应对象的原始未压缩内容。 - 新建空白PDF:将解压后的stream内容作为新PDF的页面内容。
- 配置页面参数:把原Form Xobject的
/BBox值设为新PDF页面的MediaBox和CropBox。 - 复制关联资源:将原Form Xobject引用的颜色空间、字体等资源,复制到新PDF的资源字典中。
也可以通过编写脚本简化流程:遍历PDF对象,识别带有/PTEX.FileName标记的Form Xobject,自动完成上述构造步骤。
3. 如何计算图片的绝对位置?
PDF以页面左下角为坐标原点,Form Xobject的/BBox是它自身的局部坐标范围,而它在页面上的最终位置由页面内容流中调用该Xobject的变换矩阵决定,具体方法:
- 找到页面内容流中调用该Xobject的指令,例如
q 0.8 0 0 0.8 120 250 cm /X152 Do Q,其中0.8 0 0 0.8 120 250 cm就是变换矩阵,格式为[a b c d e f],最后两个数值(120,250)是Xobject左下角在页面上的平移坐标。 - 结合
/BBox的四个值(x1,y1,x2,y2)和变换矩阵,计算绝对位置:- 绝对左下角坐标:
(x1*a + y1*c + e, x1*b + y1*d + f) - 绝对右上角坐标:
(x2*a + y2*c + e, x2*b + y2*d + f)
- 绝对左下角坐标:
你之前的脚本提取位置错误,是因为直接使用Identity(单位矩阵)渲染,没有考虑页面调用Xobject时的变换矩阵。正确做法是先找到该Xobject的调用矩阵,再用这个矩阵来渲染,而不是直接用BBox作为Pixmap的范围。
内容的提问来源于stack exchange,提问作者Kiyoaki
相关产品推荐
相关产品推荐

