gpt4 book ai didi

c# - 为什么我的图像在使用 iTextSharp 解码为 FlateDecode 时失真?

转载 作者:太空狗 更新时间:2023-10-30 00:16:11 28 4
gpt4 key购买 nike

当通过 iTextSharp 将 PDF 中的图像解码为 FlateDecode 时,图像失真,我似乎无法弄清楚原因。

识别的 bpp 是 Format1bppIndexed。如果我将 PixelFormat 修改为 Format4bppIndexed,则图像在某种程度上是可识别的(缩小,着色关闭但可读)并且以水平方式复制 4 次。如果我将像素格式调整为 Format8bppIndexed,它在某种程度上也是可识别的,并且以水平方式复制了 8 次。

下图采用Format1bppIndexed 像素格式方法。不幸的是,由于安全限制,我无法展示其他人。

distorted image

下面的代码基本上是我在 SO 和网络上遇到的唯一解决方案。

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 位,那也足够了。

更新:ImageMask 属性设置为 true,这意味着没有颜色空间,因此隐含为黑色和白色。随着 bpp 为 1,PixelFormat 应该是 Format1bppIndexed,如前所述,它会产生上面看到的嵌入图像。

更新:为了获得图像大小,我使用 Acrobat X Pro 将其提取出来,这个特定示例的图像大小列为 2403x3005。通过 iTextSharp 提取时,大小列为 2544x3300。我在调试器中将图像大小修改为镜像 2403x3005,但是在调用 Marshal.Copy(bytes, 0, bmd.Scan0, ​​bytes.Length); 时出现异常。

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

我的假设是,这是由于大小的修改,因此不再对应于正在使用的字节数据。

更新:根据 Jimmy 的建议,我验证调用 PdfReader.GetStreamBytes 返回一个 byte[] 长度等于 widthheight/8 自 GetStreamBytes 应该调用 FlateDecode。手动调用 FlateDecode 和调用 PdfReader.GetStreamBytes 都产生了 byte[] 长度为 1049401,而 widthheight/8 为 2544*3300/8 或 1049400 ,所以相差 1。不确定这是否是根本原因,相差一个;但是,如果确实如此,我不确定如何解决。

更新:在尝试 kuujinbo 提到的方法时,我在尝试调用 renderInfo.GetImage(); 时遇到了 IndexOutOfRangeExceptionRenderImage 监听器中。与调用 FlateDecode 时的 byte[] 长度相比,前面所述的 width*height/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)

更新:尝试改变我的原始解决方案中列出的不同方法以及 kuujinbo 提出的解决方案,PDF 中的不同页面会产生图像;然而,当过滤器类型为 /FlateDecode 并且没有为给定实例生成图像时,问题总是会出现。

最佳答案

尝试逐行复制你的数据,也许它会解决问题。

int w = imgObj.GetAsNumber(PdfName.WIDTH).IntValue;
int h = imgObj.GetAsNumber(PdfName.HEIGHT).IntValue;
int bpp = imgObj.GetAsNumber(PdfName.BITSPERCOMPONENT).IntValue;
var pixelFormat = PixelFormat.Format1bppIndexed;

byte[] rawBytes = PdfReader.GetStreamBytesRaw((PRStream)imgObj);
byte[] decodedBytes = PdfReader.FlateDecode(rawBytes);
byte[] streamBytes = PdfReader.DecodePredictor(decodedBytes, imgObj.GetAsDict(PdfName.DECODEPARMS));
// byte[] streamBytes = PdfReader.GetStreamBytes((PRStream)imgObj); // same result as above 3 lines of code.

using (Bitmap bmp = new Bitmap(w, h, pixelFormat))
{
var bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, pixelFormat);
int length = (int)Math.Ceiling(w * bpp / 8.0);
for (int i = 0; i < h; i++)
{
int offset = i * length;
int scanOffset = i * bmpData.Stride;
Marshal.Copy(streamBytes, offset, new IntPtr(bmpData.Scan0.ToInt32() + scanOffset), length);
}
bmp.UnlockBits(bmpData);

bmp.Save(fileName);
}

关于c# - 为什么我的图像在使用 iTextSharp 解码为 FlateDecode 时失真?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8493559/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com