适用于PDF的PNG图像的PixelFormat

时间:2019-05-13 13:40:34

标签: c# pdf png pdfsharp

我正在尝试使用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):

enter image description here

  

PixelFormat的结果= Format24bppRgb

enter image description here

1 个答案:

答案 0 :(得分:0)

您可以从PDF文件中获取pixelformat。由于您的帖子中未包含PDF,因此我无法告诉您哪种格式是正确的。

PDF文件不包含PNG图像,而是图像使用特殊的PDF图像格式,该格式有点类似于Windows使用的BMP文件,但二进制数据中没有任何标题。而是可以使用Image对象的属性找到“标题”信息。有关更多详细信息,请参见PDF参考。