我有大量的文档扫描成PDF格式,我希望编写一个shell脚本,将每个文档转换为DjVu格式。一些文件在200dpi扫描,一些在300dpi扫描,一些在600dpi扫描。由于DjVu是一种基于像素的格式,我想确保在目标DjVu文件中使用与扫描时相同的分辨率。
有谁知道我可以运行什么程序,或者我如何编写程序,以确定用于生成扫描PDF的分辨率? (像素数也可能有效,因为几乎所有文档都是8.5 x 11英寸。)
回复后的澄清:我知道布列塔尼突出的困难,我愿意承认这个问题总体上是不合适的,但我不是在问一般 PDF文件。我的特定文件来自扫描仪。它们每页包含一个扫描图像,每页包含相同的分辨率。如果我将PDF转换为PostScript,我可以手动搜索并轻松找到像素尺寸;我可能会找到更多工作的图像尺寸。如果迫切需要我可以修改gs
正在使用的字典堆栈;很久以前,我为PostScript Level 1写了一个翻译。
所有这些都是我想要避免的。
感谢收到的帮助,我在下面发布了一个答案:
identify
从PDF中提取边界框,仅获取第一页的输出,并了解单位将是PostScript点,其中有72到1英寸。pdfimages
从第一页提取图像。identify
会给出像素数。脚本的完整答案如下。我在实弹射击中使用它并且效果很好。感谢Harlequin为pdfimages
和Spiffeah提供关于每页多个图像的警报(这很少见,但我发现了一些)。
答案 0 :(得分:5)
如果通过扫描创建了pdf,那么每个页面应该只有一个图像。您可以通过使用iText(Java)或iTextSharp(.net端口)库轻松解析pdf来查找每个页面图像的每个图像分辨率。
如果您想要使用自己的实用程序来执行此操作,请在iTextSharp中执行以下操作:
PdfReader reader = new PdfReader(filename);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfDictionary pg = reader.GetPageN(i);
PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
PdfDictionary xobjs = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
if (xobjs != null)
{
foreach (PdfName xObjectKey in xobjs.Keys)
{
PdfObject xobj = xobjs.Get(xObjectKey);
PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(xobj);
PdfName subtype = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
if (subtype.Equals(PdfName.IMAGE))
{
PdfNumber width = (PdfNumber)tg.Get(PdfName.WIDTH);
PdfNumber height = (PdfNumber)tg.Get(PdfName.HEIGHT);
MessageBox.Show("image on page [" + i + "] resolution=[" + width +"x" + height + "]");
}
}
}
}
reader.Close();
这里针对每个页面,我们通过子类型Image的每个XObject读取并获取WIDTH和HEIGHT值。这将是扫描仪嵌入pdf中的图像的像素分辨率。
请注意,缩放此图像以匹配页面分辨率(如在Acrobat中呈现的页面大小 - A4,Letter等)在页面内容流中单独执行,表示为postscript的子集,如果不解析postscript就很难找到。
请注意,有些扫描仪会将扫描图像嵌入为较小图像的网格(我假设某种尺寸优化)。因此,如果您看到每个页面突然出现50个小图像,那可能就是原因。
希望如果你必须推出自己的实用程序,这会有所帮助。
答案 1 :(得分:5)
pdfimages
有一个-list
选项,用于提供高度宽度(以像素为单位)以及y-ppi
和x-ppi
。
pdfimages -list tmp.pdf
page num type width height color comp bpc enc interp object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
1 0 image 3300 2550 gray 1 1 ccitt no 477 0 389 232 172K 17%
2 1 image 3300 2550 gray 1 1 ccitt no 3 0 389 232 103K 10%
3 2 image 3300 2550 gray 1 1 ccitt no 7 0 389 232 236K 23%
4 3 image 3300 2550 gray 1 1 ccitt no 11 0 389 232 210K 20%
5 4 image 3300 2550 gray 1 1 ccitt no 15 0 389 232 250K 24%
6 5 image 3300 2550 gray 1 1 ccitt no 19 0 389 232 199K 19%
7 6 image 3300 2550 gray 1 1 ccitt no 23 0 389 232 503K 49%
8 7 image 3300 2550 gray 1 1 ccitt no 27 0 389 232 154K 15%
9 8 image 3300 2550 gray 1 1 ccitt no 31 0 389 232 21.5K 2.1%
10 9 image 3300 2550 gray 1 1 ccitt no 35 0 389 232 286K 28%
11 10 image 3300 2550 gray 1 1 ccitt no 39 0 389 232 46.8K 4.6%
12 11 image 3300 2550 gray 1 1 ccitt no 43 0 389 232 55.5K 5.4%
13 12 image 3300 2550 gray 1 1 ccitt no 47 0 389 232 35.0K 3.4%
14 13 image 3300 2550 gray 1 1 ccitt no 51 0 389 232 26.9K 2.6%
15 14 image 3300 2550 gray 1 1 ccitt no 55 0 389 232 66.5K 6.5%
16 15 image 3300 2550 gray 1 1 ccitt no 59 0 389 232 73.9K 7.2%
17 16 image 3300 2550 gray 1 1 ccitt no 63 0 389 232 47.0K 4.6%
18 17 image 3300 2550 gray 1 1 ccitt no 67 0 389 232 30.1K 2.9%
19 18 image 3300 2550 gray 1 1 ccitt no 71 0 389 232 70.3K 6.8%
20 19 image 3300 2550 gray 1 1 ccitt no 75 0 389 232 46.0K 4.5%
21 20 image 3300 2550 gray 1 1 ccitt no 79 0 389 232 28.9K 2.8%
22 21 image 3300 2550 gray 1 1 ccitt no 83 0 389 232 72.7K 7.1%
23 22 image 3300 2550 gray 1 1 ccitt no 87 0 389 232 47.5K 4.6%
24 23 image 3300 2550 gray 1 1 ccitt no 91 0 389 232 30.1K 2.9%
答案 2 :(得分:4)
我猜扫描作为图像包含在PDF中,因此您可以先使用pdfimages
提取它们。然后,identify
应该能够找到正确的数据。
答案 3 :(得分:4)
以下是这个答案的要素:
pdfimages
将提取图像,以便可以发现点数。identify
将以PostScript点(72英寸)为单位给出图像的大小下面是一个解决问题的Lua脚本。我可能使用了一个普通的外壳,但捕捉宽度和高度会产生更大的麻烦。
#!/usr/bin/env lua
require 'osutil'
require 'posixutil'
require 'mathutil'
local function runf(...) return os.execute(string.format(...)) end
assert(arg[1], "no file on command line")
local function dimens(filename)
local cmd = [[identify -format "return %w, %h\n" $file | sed 1q]]
cmd = cmd:gsub('$file', os.quote(filename))
local w, h = assert(loadstring(os.capture(cmd)))()
assert(w and h)
return w, h
end
assert(#arg == 1, "dpi of just one file")
for _, pdf in ipairs(arg) do
local w, h = dimens(pdf) -- units are points
local insquared = w * h / (72.00 * 72.00)
local imagedir = os.capture 'mktemp -d'
assert(posix.isdir(imagedir))
runf('pdfimages -f 1 -l 1 %s %s 1>&2', os.quote(pdf),
os.quote(imagedir .. '/img'))
local dotsquared = 0
for file in posix.glob(imagedir .. '/img*') do
local w, h = dimens(file) -- units are pixels
dotsquared = dotsquared + w * h
end
os.execute('rm -rf ' .. os.quote(imagedir))
local dpi = math.sqrt(dotsquared / insquared)
if true then
io.stderr:write(insquared, " square inches\n")
io.stderr:write(dotsquared, " square dots\n")
io.stderr:write(dpi, " exact dpi\n")
io.stderr:write(math.round(dpi, 10), " rounded dpi\n")
end
print(math.round(dpi, 10))
end
答案 4 :(得分:2)
发表评论的时间太长,但ImageMagick和GraphicsMagic都不能胜任这项工作; 每个答案都错了:
: nr@yorkie 1932 ; gm identify -format "x=%x y=%y w=%w h=%h" drh*rec*pdf
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
x=0 y=0 w=612 h=792
: nr@yorkie 1933 ; identify -format "x=%x y=%y w=%w h=%h" drh*rec*pdf
x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792x=72 Undefined y=72 Undefined w=612 h=792
: nr@yorkie 1934 ;
本文档的正确参数是每个扫描页面的宽度为5100像素,高度为6600像素,不出所料,这是在600dpi下扫描的8.5×11。 ImageMagic的输出非常不专业。
没有downvotes,因为你试图提供帮助,但*Magick
不起作用。
答案 5 :(得分:0)
PDF是一种独立于分辨率的格式,这是一个荒谬的问题。您可能已经扫描了特定分辨率的某些位图,并且这些位图分别嵌入在pdf中,但PDF本身可能包含多个分辨率的图像,以及独立于分辨率的矢量图形。没有破解打开pdf并检查其中的每个对象都无法知道。
编辑以继续解释问题:
你可能已经幸运了,你用来扫描文档的软件嵌入了一些有关此内容的元数据,但不要赌它。这样的元数据不太可能是标准的。就解析pdf而言,你需要一个预先编写的库 - 例如ghostscript。问题在于,PDF实际上并不是一种格式,因为它是PostScript编程语言的指定子集,并且是一种压缩/编译此子集以及一些二进制文件的商定方式。因此,阅读PDF比其他类型的图像格式更复杂,因为它涉及编写语言解释器 - 不是那么简单。
最好的办法是要么放弃你的手放弃,要么真的很努力地看看ghostscript,看看你能不能告诉你答案。
答案 6 :(得分:0)