PDFSharp - извлечь FlateDecode как PNG - PullRequest
0 голосов
/ 26 июня 2018

Цель Чтобы правильно получить объекты изображения FlateDecode из pdf на png.

Пожалуйста, дайте мне знать, если вы видите что-то не так с приведенным ниже кодом, который может вызвать проблемы.

Код ниже дает мне изображение, но оно полностью искажено. Смотрите: (слева = хорошо, справа = мое с кодом)

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 голосов
/ 13 июня 2019

Вот фрагмент кода, который установит палитру для цветового пространства / 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
    }
}
0 голосов
/ 27 июня 2018

Я предполагаю, что это case 8 изображение. Если вы извлечете данные изображения без соответствующей цветовой палитры и отобразите изображение с цветовой палитрой по умолчанию, то вы получите изображения, подобные отображаемому.

Изображения в файлах PDF могут состоять из нескольких объектов PDF: данные пикселей, цветовая палитра, альфа-маска, двухуровневая маска.

Возможно, для этого изображения достаточно создать палитру градаций серого, в которой цвет x имеет значения RGB (x, x, x). Но для общего решения извлеките палитру из PDF.

...