pdf - 如何提取 PDF 提取图像的旋转/变换信息(即查看者如何知道旋转 180 度)
问题描述
我正在使用生成 PDF-1.3 的 ScanSnap 扫描仪,当在 Adobe Reader 中查看 PDF 时,它将自动更正扫描文档的方向(旋转 0 或 180 度)。OCR 由扫描软件完成,我假设然后确定方向并编码到 PDF 中。
请注意,我知道我可以使用 Tesseract 或其他 OCR 工具来确定是否需要旋转,但我不想使用它,因为扫描仪软件似乎已经确定了它并告诉 PDF 查看器是否需要(或不需要)旋转。
当我使用图像提取工具(如 xpdf pdfimages、python 库)时,它不能正确地将 jpeg 图像旋转 180 度(如果需要)。
注意:pdfimages 从 PDF 文件中提取原始图像数据,而不执行任何额外的转换。由 PDF 内容流完成的任何旋转、剪切、颜色反转等都将被忽略。
我已经旋转扫描了两次文档(0 度和 180 度)。我似乎无法逆向工程告诉 Adobe/Foxit 在查看时旋转(或不旋转)图像。我查看了 PDF-1.3 规范文档,并比较了方向校正和未校正的 PDF 二进制数据。我无法确定是什么在纠正方向?
- PDF 中没有 /Page/Rotate(默认为 0)
- JPEG 中没有 EXIF 方向
- 我在 PDF 中看不到任何转换矩阵(cm 运算符)
在这两种情况下,PDF 二进制文件如下所示(在 JPEG 流数据处停止)
%PDF-1.3
%âãÏÓ
1 0 obj
<</Metadata 20 0 R/Pages 2 0 R/Type/Catalog>>
endobj
2 0 obj
<</MediaBox[0.0 0.0 606.6 794.88]/Count 1/Type/Pages/Kids[4 0 R]>>
endobj
4 0 obj
<</Parent 2 0 R/Contents 18 0 R/PieceInfo<</PSL<</Private<</V(3.2.9)>>/LastModified(D:20190201125524-00'00')>>>>/MediaBox[0.0 0.0 606.6 794.88]/Resources<</XObject<</Im0 5 0 R>>/Font<</C0_0 11 0 R/T1_0 16 0 R>>/ProcSet[/PDF/Text/ImageC]>>/Type/Page/LastModified(D:20190201085524-04'00')>>
endobj
5 0 obj
<</Subtype/Image/Length 433576/Filter/DCTDecode/Name/X/BitsPerComponent 8/ColorSpace/DeviceRGB/Width 1685/Height 2208/Type/XObject>>stream
有谁知道PDF查看器如何知道将图像旋转180(或不旋转)。是否可以提取 PDF 或 JPEG 图像中的元数据?Adobe 和其他查看器是否会在打开文档时动态执行某些操作以确定是否需要方向校正?
我不是 PDF 规范方面的专家。但我希望有人可能已经找到了解决这个问题的方法。
解决方案
“internetfile-180.pdf”页面资源中的图像Im0没有旋转:
但是“internetfile.pdf”中页面资源中的图像Im0是旋转的:
在查看器中,两者看起来都是直立的,因此在“internetfile.pdf”中必须使用一种技术来旋转图像。
有两种主要技术:
- 相应地设置页面的Rotate属性,即此处为 180。
- 对页面内容流中的当前变换矩阵应用旋转变换。
我们先看一下页面字典,打印的有点漂亮:
4 0 obj
<<
/Parent 2 0 R
/Contents 13 0 R
/PieceInfo
<<
/PSL
<<
/Private <</V (3.2.9)>>
/LastModified (D:20190204142537-00'00')
>>
>>
/MediaBox [0.0 0.0 608.64 792.24]
/Resources
<<
/XObject <</Im0 5 0 R>>
/Font <</T1_0 11 0 R>>
/ProcSet [/PDF /Text /ImageC]
>>
/Type /Page
/LastModified (D:20190204102537-04'00')
>>
如我们所见,不存在Rotate条目。因此,我们必须查看页面内容流。根据页面字典,它位于对象 13,第 0 代。
该对象是一个带有压缩流数据的流对象:
13 0 obj
<<
/Length 4014
/Filter /FlateDecode
>>
stream
H‰”WÛŽÛF}Ÿ¯Ð[lÀÓÓ÷˾e½
[...]
ÿüòÛÿ ´ß
endstream
endobj
在对流数据进行膨胀后,它们开始如下:
q
-608.3999939 0 0 -792.9600067 608.3999939 792.9600067 cm
/Im0 Do
Q
[...]
这确实是第二种技术的应用,cm指令应用旋转,Do指令在旋转激活的情况下绘制图像!
详细地说,cm指令应用了由矩阵表示的仿射变换
-608.3999939 0 0
0 -792.9600067 0
608.3999939 792.9600067 1
换句话说:
x' = -608.3999939 * x + 608.3999939
y' = -792.9600067 * y + 792.9600067
这种变换实际上是旋转 180°、水平缩放 608.3999939 和垂直缩放 792.9600067 以及水平平移 608.3999939 和垂直平移 792.9600067 的组合。
Do指令现在绘制图像。这里需要知道,该指令首先将图像缩放以适合原点处的 1×1 单元格,然后应用当前变换矩阵。
因此,图像被旋转了 180°,有效地填充了页面的整个 608.64×792.24 MediaBox。
推荐阅读
- python - tf.cast 在尝试将 int 转换为 float 时返回零
- javascript - 在过滤器操作中使用 async/await 在第一次等待调用后不等待完成
- javascript - 提交表单后重定向到新页面
- algorithm - 最佳和最坏情况时间复杂度,并以渐近符号表示以下函数
- php - Codeigniter 网站 PHP 代码主题无法注册和登录
- python - 如何从 Trustpilot 获取业务部门 ID
- angular - 角度如何检测 ng-content 中有多少组件?
- javascript - 这里显示的是主体,而不是主体。无法弄清楚这有什么问题
- go - 是否可以在不丢失行号前缀的情况下包装 logrus.Logger 函数?
- json - 我想将循环引用 JSON 从客户端发送到服务器端