通过 iTextSharp 4.1.6.0 从 Pdf 中提取图像
Extract Images from Pdf via iTextSharp 4.1.6.0
大家好(还有你 Bruno :))。
我正在使用为 Xamarin.Android.
移植的 iTextSharp 4.1.6.0
出于某种原因,我需要从 pdf 中提取图像。
我 建立了 太多的例子,但似乎它们不适合我的 案例 ,因为有些 类(比如 :
ImageCodeInfo , ImageRenderInfo , System.Drawing.Imaging.EncoderParameters , PdfImageObject 等等,不存在)。
但是有一个例子看起来不错,就是这个:
void ExtractJpeg(string file)
{
var dir1 = Path.GetDirectoryName(file);
var fn = Path.GetFileNameWithoutExtension(file);
var dir2 = Path.Combine(dir1, fn);
if (!Directory.Exists(dir2)) Directory.CreateDirectory(dir2);
var pdf = new PdfReader(file);
int n = pdf.NumberOfPages;
for (int i = 1; i <= n; i++)
{
var pg = pdf.GetPageN(i);
var res = PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES)) as PdfDictionary;
var xobj = PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)) as PdfDictionary;
if (xobj == null) continue;
var keys = xobj.Keys;
if (keys.Count == 0) continue;
var obj = xobj.Get(keys.ElementAt(0));
if (!obj.IsIndirect()) continue;
var tg = PdfReader.GetPdfObject(obj) as PdfDictionary;
var type = PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)) as PdfName;
if (!PdfName.IMAGE.Equals(type)) continue;
int XrefIndex = (obj as PRIndirectReference).Number;
var pdfStream = pdf.GetPdfObject(XrefIndex) as PRStream;
var data = PdfReader.GetStreamBytesRaw(pdfStream);
var jpeg = Path.Combine(dir2, string.Format("{0:0000}.jpg", i));
File.WriteAllBytes(jpeg, data);
}
}
这一行的问题:
var obj = xobj.Get(keys.ElementAt(0));
错误日志:
The type arguments for method
`System.Linq.ParallelEnumerable.ElementAt(this
System.Linq.ParallelQuery, int)' cannot be inferred from the
usage. Try specifying the type arguments explicitly
我不知道如何解决。有人可以解释一下吗?
此外,我想知道是否存在另一种从 pdf 中提取图像的方法。
谢谢!!
首先,旧的、过时的、官方不再支持的软件升级的必读词:
请升级到最新版本的 iTextSharp。我知道您会说您不能使用 iText 的新许可证,但请阅读他们的 sales FAQ,特别是解决 4.1.6 的 "Why shouldn't I use..." 部分。请记住,在大多数国家/地区,接受许可实际上意味着您签订了一份法律合同,因此我也希望有法律经验的人也能阅读。既然你说你正在使用 Xamarin,我认为你也正在将它提交给商店,所以这更重要,因为问题会很快成倍增加。
此外,即将推出新版本的 PDF,您可能也希望按计划支持它。
其次,您的代码做出了一个巨大且错误的假设,即 PDF 中的所有图像都是 JPEG。有关它的一些讨论,请参阅 this post and this post。也许您的 PDF 都是 JPEG,所以这对您有用,但很有可能会破坏 "tomorrow".
Third,我无法让 ElementAt
与 ICollection
一起工作。我不知道我是否遗漏了扩展名或某个地方的 using
,但您似乎从一个五岁的 post here that came from a six year old post here 那里复制了代码。我也不确定为什么仍然需要 "first" 元素,这很奇怪。解决方案是循环遍历密钥,而不是尝试明确地获取一个密钥。而不是:
var obj = xobj.Get(keys.ElementAt(0));
//...
File.WriteAllBytes(jpeg, data);
遍历每个键:
foreach (PdfName k in keys) {
var obj = xobj.Get(k);
//...
File.WriteAllBytes(jpeg, data);
}
这个小改动会让我们都哭泣,但至少应该可以提取图像。
大家好(还有你 Bruno :))。
我正在使用为 Xamarin.Android.
移植的 iTextSharp 4.1.6.0
出于某种原因,我需要从 pdf 中提取图像。
我 建立了 太多的例子,但似乎它们不适合我的 案例 ,因为有些 类(比如 :
ImageCodeInfo , ImageRenderInfo , System.Drawing.Imaging.EncoderParameters , PdfImageObject 等等,不存在)。
但是有一个例子看起来不错,就是这个:
void ExtractJpeg(string file)
{
var dir1 = Path.GetDirectoryName(file);
var fn = Path.GetFileNameWithoutExtension(file);
var dir2 = Path.Combine(dir1, fn);
if (!Directory.Exists(dir2)) Directory.CreateDirectory(dir2);
var pdf = new PdfReader(file);
int n = pdf.NumberOfPages;
for (int i = 1; i <= n; i++)
{
var pg = pdf.GetPageN(i);
var res = PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES)) as PdfDictionary;
var xobj = PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)) as PdfDictionary;
if (xobj == null) continue;
var keys = xobj.Keys;
if (keys.Count == 0) continue;
var obj = xobj.Get(keys.ElementAt(0));
if (!obj.IsIndirect()) continue;
var tg = PdfReader.GetPdfObject(obj) as PdfDictionary;
var type = PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)) as PdfName;
if (!PdfName.IMAGE.Equals(type)) continue;
int XrefIndex = (obj as PRIndirectReference).Number;
var pdfStream = pdf.GetPdfObject(XrefIndex) as PRStream;
var data = PdfReader.GetStreamBytesRaw(pdfStream);
var jpeg = Path.Combine(dir2, string.Format("{0:0000}.jpg", i));
File.WriteAllBytes(jpeg, data);
}
}
这一行的问题:
var obj = xobj.Get(keys.ElementAt(0));
错误日志:
The type arguments for method `System.Linq.ParallelEnumerable.ElementAt(this System.Linq.ParallelQuery, int)' cannot be inferred from the usage. Try specifying the type arguments explicitly
我不知道如何解决。有人可以解释一下吗?
此外,我想知道是否存在另一种从 pdf 中提取图像的方法。
谢谢!!
首先,旧的、过时的、官方不再支持的软件升级的必读词:
请升级到最新版本的 iTextSharp。我知道您会说您不能使用 iText 的新许可证,但请阅读他们的 sales FAQ,特别是解决 4.1.6 的 "Why shouldn't I use..." 部分。请记住,在大多数国家/地区,接受许可实际上意味着您签订了一份法律合同,因此我也希望有法律经验的人也能阅读。既然你说你正在使用 Xamarin,我认为你也正在将它提交给商店,所以这更重要,因为问题会很快成倍增加。
此外,即将推出新版本的 PDF,您可能也希望按计划支持它。
其次,您的代码做出了一个巨大且错误的假设,即 PDF 中的所有图像都是 JPEG。有关它的一些讨论,请参阅 this post and this post。也许您的 PDF 都是 JPEG,所以这对您有用,但很有可能会破坏 "tomorrow".
Third,我无法让 ElementAt
与 ICollection
一起工作。我不知道我是否遗漏了扩展名或某个地方的 using
,但您似乎从一个五岁的 post here that came from a six year old post here 那里复制了代码。我也不确定为什么仍然需要 "first" 元素,这很奇怪。解决方案是循环遍历密钥,而不是尝试明确地获取一个密钥。而不是:
var obj = xobj.Get(keys.ElementAt(0));
//...
File.WriteAllBytes(jpeg, data);
遍历每个键:
foreach (PdfName k in keys) {
var obj = xobj.Get(k);
//...
File.WriteAllBytes(jpeg, data);
}
这个小改动会让我们都哭泣,但至少应该可以提取图像。