使用iTextSharp提取FlateDecode图像

时间:2012-04-05 13:45:29

标签: c# itextsharp

我想从PDF中提取图像。我现在正在使用iTextSharp。 某些图像可以正确提取,但大多数图像没有正确的颜色并且是扭曲的。 我用不同的PixelFormats做了一些实验,但我找不到解决问题的方法......

这是分隔图像类型的代码:

if (filter == "/FlateDecode")
{
   // ...
   int w = int.Parse(width);
   int h = int.Parse(height);
   int bpp = tg.GetAsNumber(PdfName.BITSPERCOMPONENT).IntValue;

   byte[] rawBytes = PdfReader.GetStreamBytesRaw((PRStream)tg);
   byte[] decodedBytes = PdfReader.FlateDecode(rawBytes);
   byte[] streamBytes = PdfReader.DecodePredictor(decodedBytes, tg.GetAsDict(PdfName.DECODEPARMS));

   PixelFormat[] pixFormats = new PixelFormat[23] { 
         PixelFormat.Format24bppRgb,
         // ... all Pixel Formats
    };
    for (int i = 0; i < pixFormats.Length; i++)
    {
        Program.ToPixelFormat(w, h, pixFormats[i], streamBytes, bpp, images));
    }
}

这是将图像保存在MemoryStream中的代码。将图像保存在文件夹中稍后实现。

private static void ToPixelFormat(int width, int height, PixelFormat pixelformat, byte[] bytes, int bpp, IList<Image> images)
{
    Bitmap bmp = new Bitmap(width, height, pixelformat);
    BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, width, height),
       ImageLockMode.WriteOnly, pixelformat);
    Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length);
    bmp.UnlockBits(bmd);
    using (var ms = new MemoryStream())
    {
       bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
       bytes = ms.GetBuffer();
    }
    images.Add(bmp);
}

请帮帮我。

3 个答案:

答案 0 :(得分:3)

即使你找到了问题的解决方案,让我说建议修复上面的代码。

我认为失真问题是由于行数据边界不匹配引起的。 PdfReader以字节边界返回数据。例如,对于20像素宽的灰度图像,每个图像行将获得20个字节的数据。位图类适用于32位边界。当创建具有20个像素宽度的位图时,Bitmap类将生成具有步幅(字节宽度)= 32字节的灰度位图。这意味着您不能简单地使用Marshal.Copy()方法将检索到的字节从PdfReader复制到新的位图中,就像在ToPixelFormat()中一样。

源字节数组中的第一个像素位于第21个字节,但由于位图的32位边界,目标位图需要它作为第33个字节。为了解决这个问题,我不得不创建一个大小为每个数据行32位边界的字节数组。

逐行地将数据从从PdfReader检索到的字节aray复制到具有32位行边界考虑的新字节数组中。现在,我的数据字节的边界与Bitmap类边界匹配,因此我可以使用Marshal.Copy()将其复制到新的Bitmap。

答案 1 :(得分:2)

我为自己的问题找到了解决方案。 要提取所有页面上的所有图像,不必实现不同的过滤器。 iTextSharp有一个图像渲染器,可以将所有图像保存为原始图像类型。

只需执行以下操作:http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx 您不需要实现HttpHandler ...

答案 2 :(得分:1)

PDF支持各种各样的图像格式。我不认为我会选择你在这里选择的方法。您需要从流本身的字节中确定图像格式。例如,JPEG通常以ASCII字节JFIF开头。

.NET(3.0+)确实附带了一种尝试选择正确解码器的方法:BitmapDecoder.Create。见http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapdecoder.aspx

如果这不起作用,您可能需要考虑一些第三方成像库。我使用过ImageMagick.NET和LeadTools(估价过高)。