【发布时间】:2019-09-30 11:45:26
【问题描述】:
我正在尝试使用PDFsharp library 提取图像。如示例程序中所述,该库不支持提取非JPEG图像,因此,我正在尝试自己做。
出于同样的目的,我发现了一个不工作的sample program。我正在使用以下代码提取嵌入在 PDF 文件中的400 x 400 PNG 图像(该图像首先插入到 MS Word 文件中,然后保存为 PDF 文件)。
PDF 文件链接:
https://drive.google.com/open?id=1aB-SrMB3eu00BywliOBC8AW0JqRa0Hbd
提取码:
static void ExportAsPngImage(PdfDictionary image, ref int count)
{
int width = image.Elements.GetInteger(PdfSharp.Pdf.Advanced.PdfImage.Keys.Width);
int height = image.Elements.GetInteger(PdfSharp.Pdf.Advanced.PdfImage.Keys.Height);
System.Drawing.Imaging.PixelFormat pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
byte[] original_byte_boundary = image.Stream.UnfilteredValue;
byte[] result_byte_boundary = null;
//Image data in BMP files always starts at a DWORD boundary, in PDF it starts at a BYTE boundary.
//You must copy the image data line by line and start each line at the DWORD boundary.
byte[, ,] copy_dword_boundary = new byte[3, height, width];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x <= width && (x + (y * width) != original_byte_boundary.Length))
// while not at end of line, take orignale array
{
copy_dword_boundary[0, y, x] = original_byte_boundary[3*x + (y * width)];
copy_dword_boundary[1, y, x] = original_byte_boundary[3*x + (y * width) + 1];
copy_dword_boundary[2, y, x] = original_byte_boundary[3*x + (y * width) + 2];
}
else //fill new array with ending 0
{
copy_dword_boundary[0, y, x] = 0;
copy_dword_boundary[1, y, x] = 0;
copy_dword_boundary[2, y, x] = 0;
}
}
}
result_byte_boundary = new byte[3 * width * height];
int counter = 0;
int n_width = copy_dword_boundary.GetLength(2);
int n_height = copy_dword_boundary.GetLength(1);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{ //put 3dim array back in 1dim array
result_byte_boundary[counter] = copy_dword_boundary[0, x, y];
result_byte_boundary[counter + 1] = copy_dword_boundary[1, x, y];
result_byte_boundary[counter + 2] = copy_dword_boundary[2, x, y];
//counter++;
counter = counter + 3;
}
}
Bitmap bmp = new Bitmap(width, height, pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(result_byte_boundary, 0, bmd.Scan0, result_byte_boundary.Length);
bmp.UnlockBits(bmd);
using (FileStream fs = new FileStream(@"D:\TestPdf\" + String.Format("Image{0}.png", count), FileMode.Create, FileAccess.Write))
{
bmp.Save(fs, ImageFormat.Png);
count++;
}
}
问题:
无论我选择什么PixelFormat 格式,保存的PNG 图像看起来都不正确。
原始 PNG 图像(位深 32):
PixelFormat = Format24bppRgb 的结果
【问题讨论】:
-
流位的格式化方式有多种选择,因此通用解决方案可能超出了堆栈溢出答案的范围。是否可以查看具有适当许可证且已实现图像导出功能的开源 PDF 库的代码以获取灵感?
-
@mkl:您能否推荐一个可以可靠地从 PDF 中提取图像的开源库。
Bit Miracle的库对我来说工作可靠,但它不是开源的。 -
您的问题与 iText 无关,我删除了标签。
-
我不做大规模图像提取,所以我不能谈论可靠性。此外,可靠性可能是出现的图像类型的问题:PDF 允许图像有多种变化......此外请注意,根据您让自己受到启发的方式,可能会产生许可方面的后果:如果您只是复制非平凡代码,您很可能会受到您复制的源库的许可的约束。
-
@mkl:我知道我不能简单地复制粘贴非平凡的代码 :) 我只需要一些灵感代码来提取图像。我不需要付费图书馆提供的其他功能。