美文网首页
iText读取pdf中cmyk图片,颜色反转问题

iText读取pdf中cmyk图片,颜色反转问题

作者: 叶迎宪 | 来源:发表于2024-05-08 12:06 被阅读0次

pdf中的cmyk图片,提取出来,保存成文件,看到颜色是反转的

PdfImageXObject image

MemoryStream memoryStream = new MemoryStream(image.GetImageBytes());

using (BinaryWriter writer = new BinaryWriter(File.OpenWrite("1.jpg")))
{
    writer.Write(memoryStream.ToArray());
}

可以确定这个pdf中的cmyk图片是jpg的,因为pdf中object的filter是DCTDecode

可是神奇的是,如果把这个图片的数据,重新放回pdf中,pdf里面看到的也是反转颜色的了

        using (MagickImage origBitmap = new MagickImage(memoryStream))
        {
            if (origBitmap.ColorSpace == ColorSpace.CMYK)
            {
                int width = origBitmap.Width;
                int height = origBitmap.Height;

                var pixels = origBitmap.GetPixels();
                byte[] raw = pixels.GetValues();

                ImageData imageData = ImageDataFactory.Create(width, height, 4, 8, raw, null);

                PdfImageXObject imageXObject = new PdfImageXObject(imageData);

                var imgObj = imageXObject.GetPdfObject();
                xObjects.Put(pdfName, imgObj);
            }

对比了一下,修改后的pdf文件大了一些,主要是图片的filter变成了FlateDecode,就是从jpg格式变成png格式了。如果还是把图片保存成jpg呢?

        using (MagickImage origBitmap = new MagickImage(memoryStream))
        {
            if (origBitmap.ColorSpace == ColorSpace.CMYK)
            {
                int width = origBitmap.Width;
                int height = origBitmap.Height;

                var stream = new MemoryStream();
                origBitmap.Write(stream);  // 保存回cmyk的jpg

                ImageData imageData = ImageDataFactory.Create(stream.ToArray());

                PdfImageXObject imageXObject = new PdfImageXObject(imageData);

                var imgObj = imageXObject.GetPdfObject();
                xObjects.Put(pdfName, imgObj);
            }

pdf文件大小相差不大了,可是图片依然是颜色反转的!仔细的对比前后的pdf文件,发现颜色反转的pdf,其图片属性为
<</BitsPerComponent 8/ColorSpace/DeviceCMYK/Decode[1 0 1 0 1 0 1 0]/Filter/DCTDecode/Height 123/Length 3901/Subtype/Image/Type/XObject/Width 166>>

对比之前多出来一行/Decode[1 0 1 0 1 0 1 0]。如果去掉Decode这个属性

                imageXObjectStream.Remove(PdfName.Decode);

则pdf中图片颜色终于变成正常了。通过搜索得到的答案

https://graphicdesign.stackexchange.com/questions/12894/cmyk-jpegs-extracted-from-pdf-appear-inverted
https://gitlab.freedesktop.org/cairo/cairo/-/issues/156

原始pdf中,cmyk jpg图片不带/Decode参数。pdf中看到是白底。jpg图片的原始数据也是白底的。

直接把 /DCTDecode 那部分内容保存成jpg,用任何软件看都是黑底。jpg中带有adobe扩展的AppE。即使修改jpg中的AppE部分,去掉Adobe字样或者改AppE段名,依然是黑底。所有的看图软件都默认cmyk的jpeg是反转的。MagickImage也是默认cmyk的jpeg是反转的,解码出来的数据也变成了黑底,但是黑底数据送进去编码又变回白底jpg数据。

itext在加载jpeg时,看到有AppE标识,就认为是反转的,因此加入了decode参数组

itext7\itext.io\itext\io\image\JpegImageHelper.cs

ProcessParameters(Stream jpegStream, String errorID, ImageData image) 中

                    if (marker == M_APPE) {
                        len = GetShort(jpegStream) - 2;
                        byte[] byteappe = new byte[len];
                        for (int k = 0; k < len; ++k) {
                            byteappe[k] = (byte)jpegStream.Read();
                        }
                        if (byteappe.Length >= 12) {
                            String appe = iText.Commons.Utils.JavaUtil.GetStringForBytes(byteappe, 0, 5, "ISO-8859-1");
                            if (appe.Equals("Adobe")) {
                                image.SetInverted(true);
                            }
                        }


UpdateAttributes(ImageData image) 中

            if (colorComponents != 1 && colorComponents != 3 && image.IsInverted()) {
                image.decode = new float[] { 1, 0, 1, 0, 1, 0, 1, 0 };
            }

因为itext多加了一组decode参数进去,让pdf阅读器也把图片反转了。

相关文章

网友评论

      本文标题:iText读取pdf中cmyk图片,颜色反转问题

      本文链接:https://www.haomeiwen.com/subject/jyidfjtx.html