2

我正在使用生成 PDF-1.3 的 ScanSnap 扫描仪,当在 Adob​​e Reader 中查看 PDF 时,它将自动更正扫描文档的方向(旋转 0 或 180 度)。OCR 由扫描软件完成,我假设然后确定方向并编码到 PDF 中。

请注意,我知道我可以使用 Tesseract 或其他 OCR 工具来确定是否需要旋转,但我不想使用它,因为扫描仪软件似乎已经确定了它并告诉 PDF 查看器是否需要(或不需要)旋转。

当我使用图像提取工具(如 xpdf pdfimages、python 库)时,它不能正确地将 jpeg 图像旋转 180 度(如果需要)。

注意:pdfimages 从 PDF 文件中提取原始图像数据,而不执行任何额外的转换。由 PDF 内容流完成的任何旋转、剪切、颜色反转等都将被忽略。

我已经旋转扫描了两次文档(0 度和 180 度)。我似乎无法逆向工程告诉 Adob​​e/Foxit 在查看时旋转(或不旋转)图像。我查看了 PDF-1.3 规范文档,并比较了方向校正和未校正的 PDF 二进制数据。我无法确定是什么在纠正方向?

  • PDF 中没有 /Page/Rotate(默认为 0)
  • JPEG 中没有 EXIF 方向
  • 我在 PDF 中看不到任何转换矩阵(cm 运算符)

在这两种情况下,PDF 二进制文件如下所示(在 JPEG 流数据处停止)

更新:指向旋转 180 旋转 0的PDF 文件的链接

%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 规范方面的专家。但我希望有人可能已经找到了解决这个问题的方法。

4

2 回答 2

3

“internetfile-180.pdf”页面资源中的图像Im0没有旋转:

internetfile-180.pdf 图片

但是“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

于 2019-02-05T16:30:47.583 回答
0

mkl正确地回答了这个问题,为我完成了为我解码 PDF 的所有艰苦工作。

我想我会添加我的 python (PyPDF2) 代码来搜索找到的旋转条件,以防它帮助其他人。

input1 = PyPDF2.PdfFileReader(open(filepath, "rb"))
totalPages = input1.getNumPages()
for pgNum in range(0,totalPages):
    page0 = input1.getPage(pgNum)

    # Lets look to see if the page contains a transformation matrix to rotate it 180 degress 
    # (ScanScap iX500 encoded the PDF with a cm transformation matrix to rotate 180 degrees in PDF viewers
    # @see https://stackoverflow.com/questions/54483013/how-to-extract-rotation-transformation-information-for-pdf-extracted-images-i-e
    # @see 'PDF 1.3 Reference Manual March 11, 1999' Section 3.10 Transformation matrices which is applied to the scanned image
    #                                          [[a b 0]
    #                                           [c d 0]
    #                                           [e f 1]] 
    isPageRotated180 = False
    pgContent = page0['/Contents'].getData().decode('utf-8')
    FLOAT_REG = '([-+]?\d*\.\d+|\d+)'
    m = re.search( '{} {} {} {} {} {} cm'.format(FLOAT_REG,FLOAT_REG,FLOAT_REG,FLOAT_REG,FLOAT_REG,FLOAT_REG), pgContent )
    if m:
        (a,b,c,d,e,f) = list(map(float,m.groups()))
        isPageRotated180 = (a == -e and d == -f)   
于 2019-02-07T18:05:14.543 回答