当通过iTextSharp解码PDF中的图像为FlateDecode
时,图像失真,我似乎无法弄清楚原因。为什么使用iTextSharp解码FlateDecode时图像失真?
公认的bpp是Format1bppIndexed
。如果我将PixelFormat
修改为Format4bppIndexed
,则图像在某种程度上可识别(收缩,着色关闭但可读),并以水平方式复制4次。如果我将像素格式调整为Format8bppIndexed
,则它在某种程度上也可以识别,并以水平方式重复8次。
下面的图片是在Format1bppIndexed
像素格式的方法之后。不幸的是,由于安全限制,我无法显示其他人。
的代码被认为是下面基本上是单一的解决方案,我所遇到的周围既SO和web散落。
int xrefIdx = ((PRIndirectReference)obj).Number;
PdfObject pdfObj = doc.GetPdfObject(xrefIdx);
PdfStream str = (PdfStream)(pdfObj);
byte[] bytes = PdfReader.GetStreamBytesRaw((PRStream)str);
string filter = ((PdfArray)tg.Get(PdfName.FILTER))[0].ToString();
string width = tg.Get(PdfName.WIDTH).ToString();
string height = tg.Get(PdfName.HEIGHT).ToString();
string bpp = tg.Get(PdfName.BITSPERCOMPONENT).ToString();
if (filter == "/FlateDecode")
{
bytes = PdfReader.FlateDecode(bytes, true);
System.Drawing.Imaging.PixelFormat pixelFormat;
switch (int.Parse(bpp))
{
case 1:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format1bppIndexed;
break;
case 8:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
break;
case 24:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
break;
default:
throw new Exception("Unknown pixel format " + bpp);
}
var bmp = new System.Drawing.Bitmap(Int32.Parse(width), Int32.Parse(height), pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, Int32.Parse(width),
Int32.Parse(height)), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length);
bmp.UnlockBits(bmd);
bmp.Save(@"C:\temp\my_flate_picture-" + DateTime.Now.Ticks.ToString() + ".png", ImageFormat.Png);
}
什么我需要做什么来让自己的图像提取的作品与FlateDecode
打交道时所需?
注意:我不想用另一个库来提取图像。我正在寻找一个解决方案,利用只有 iTextSharp和.NET FW。如果一个解决方案通过Java(iText)存在,并且很容易移植到.NET FW位,那么这个位就足够了。
UPDATE:ImageMask
属性设置为true,这意味着没有颜色空间,因此隐含黑色和白色。在bpp进入1时,PixelFormat
应该是Format1bppIndexed
,如前所述,产生上面看到的嵌入式图像。
UPDATE:要使用Acrobat X Pro将图像大小提取出来,此特定示例的图像大小列为2403x3005。通过iTextSharp提取时,大小被列为2544x3300。我在调试器中修改了镜像大小,以镜像2403x3005,但是在调用Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length);
时,我收到了一个异常。
试图读取或写入受保护的内存。这通常是指示其他内存已损坏的 。
我的假设是,这是由于修改了大小,因此不再对应于正在使用的字节数据。
UPDATE:每Jimmy的建议,我已验证主叫PdfReader.GetStreamBytes
返回一个字节[]长度等于宽度高度/ 8由于GetStreamBytes
应当调用FlateDecode
。手动调用FlateDecode
和调用PdfReader.GetStreamBytes
都生成了一个byte []长度为1049401,而宽度为 height/8为2544 * 3300/8或1049400,因此存在差异1.不确定这是否是根本原因或不是,一个一个;但是,如果确实如此,我不确定如何解决。
UPDATE:在试图通过kuujinbo提到的方法,我遇到了一个IndexOutOfRangeException
当我尝试了RenderImage
监听器中调用renderInfo.GetImage();
。在调用FlateDecode
时,前面所述的宽度*高度/ 8与字节[]长度相比是1的事实使我认为这些都是相同的;然而,解决方案仍然没有解决。
at System.util.zlib.Adler32.adler32(Int64 adler, Byte[] buf, Int32 index, Int32 len)
at System.util.zlib.ZStream.read_buf(Byte[] buf, Int32 start, Int32 size)
at System.util.zlib.Deflate.fill_window()
at System.util.zlib.Deflate.deflate_slow(Int32 flush)
at System.util.zlib.Deflate.deflate(ZStream strm, Int32 flush)
at System.util.zlib.ZStream.deflate(Int32 flush)
at System.util.zlib.ZDeflaterOutputStream.Write(Byte[] b, Int32 off, Int32 len)
at iTextSharp.text.pdf.codec.PngWriter.WriteData(Byte[] data, Int32 stride)
at iTextSharp.text.pdf.parser.PdfImageObject.DecodeImageBytes()
at iTextSharp.text.pdf.parser.PdfImageObject..ctor(PdfDictionary dictionary, Byte[] samples)
at iTextSharp.text.pdf.parser.PdfImageObject..ctor(PRStream stream)
at iTextSharp.text.pdf.parser.ImageRenderInfo.PrepareImageObject()
at iTextSharp.text.pdf.parser.ImageRenderInfo.GetImage()
at cyos.infrastructure.Core.MyImageRenderListener.RenderImage(ImageRenderInfo renderInfo)
UPDATE:试图改变我原来的解决方案列在这里,以及通过kuujinbo与PDF中的不同页面所带来的解决方案不同的方法产生的图像;然而,当过滤器类型为/FlateDecode
并且没有为给定实例生成图像时,问题始终显示。
图像如何失真?你可以张贴截图吗?这听起来像你在某个地方出现了错误,或者错误地将事情放大了。 – ChrisF 2011-12-13 17:35:52
@ChrisF刚刚添加了一个图片 – 2011-12-13 17:38:07
这与这个问题有关吗? HTTP://计算器。com/questions/757265/how-do-pdfs-bitspercomponent-translate-to-bits-per-pixel-for-images如果不是,我会尽量深入挖掘当我有机会 – 2011-12-13 19:32:34