PDFSharp-将FlateDecode提取为PNG

时间:2018-06-26 18:32:46

标签: c# pdf pdfsharp

目标 要从pdf处以png格式正确获取FlateDecode图像对象。

如果您发现以下代码可能导致问题,请告诉我。

下面的代码为我提供了图像,但是它完全失真了。请参阅:(左=良好,右=我的代码)

enter image description here

static void ExportAsPngImage(PdfDictionary image, string filename, ref int count)
    {
        int width = image.Elements.GetInteger(PdfImage.Keys.Width);
        int height = image.Elements.GetInteger(PdfImage.Keys.Height);
        int bitsPerComponent = image.Elements.GetInteger(PdfImage.Keys.BitsPerComponent);

        var canUnfilter = image.Stream.TryUnfilter();
        byte[] decoded = image.Stream.Value;

        System.Drawing.Imaging.PixelFormat pixelFormat;
        switch (bitsPerComponent)
        {
            case 1:
                pixelFormat = PixelFormat.Format1bppIndexed;
                break;
            case 8:
                pixelFormat = PixelFormat.Format8bppIndexed;
                break;
            case 24:
                pixelFormat = PixelFormat.Format24bppRgb;
                break;
            default:
                throw new Exception("Unknown pixel format " + bitsPerComponent);
        }

        Bitmap bmp = new Bitmap(width, height, pixelFormat);
        var bmd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, pixelFormat);
        int length = (int)Math.Ceiling(Convert.ToInt32(width) * bitsPerComponent / 8.0);
        for (int j = 0; j < height; j++)
        {
            int offset = j * length;
            int scanOffset = j * bmd.Stride;
            Marshal.Copy(decoded, offset, new IntPtr(bmd.Scan0.ToInt32() + scanOffset), length);
        }
        bmp.UnlockBits(bmd);
        using(var fs = new FileStream(filename + "_" + count + ".png",FileMode.Create, FileAccess.Write))
         bmp.Save(fs, ImageFormat.Png);
        count++;
    }

2 个答案:

答案 0 :(得分:0)

我认为这是case 8图像。如果您提取没有关联调色板的图像数据并使用默认调色板显示图像,则将获得与所显示图像相似的图像。

PDF文件中的图像可以包含多个PDF对象:像素数据,调色板,alpha蒙版,双级蒙版。

也许对于该图像而言,创建一个灰度调色板就足够了,其中颜色x具有RGB值(x,x,x)。但是对于一般解决方案,请从PDF中提取调色板。

答案 1 :(得分:0)

这是一段代码,它将为/ DeviceRGB颜色空间设置调色板:

using PdfSharp.Pdf;
using PdfSharp.Pdf.Advanced;

...

// get palette if required (pf is the pixel format, previously extracted from the imageDictionary, imageDictionary is the PdfDictionary for the image, bmp is the System.Drawing.Bitmap we're going to be dumping our image data to)
if (pf == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
{
    PdfArray colArr = imageDictionary.Elements.GetArray(PdfImage.Keys.ColorSpace);
    if (colArr != null && colArr.Elements.GetName(0) == "/Indexed" && colArr.Elements.GetName(1) == "/DeviceRGB")
    {
        System.Drawing.Imaging.ColorPalette pal = bmp.Palette;      // this returns a clone, so we'll manipulate it and then set it back at the end
        int palCount = colArr.Elements.GetInteger(2);
        char[] palVal = colArr.Elements.GetString(3).ToCharArray();
        int basePointer = 0;
        for (int i = 0; i < palCount; i++)
        {
            pal.Entries[i] = System.Drawing.Color.FromArgb(palVal[basePointer], palVal[basePointer + 1], palVal[basePointer + 2]);
            basePointer += 3;
        }
        bmp.Palette = pal;
    }
    else
    {
        // some other colorspace mechanism needs to be implemented
    }
}