【问题标题】:Image.Save() on MemoryBmp to TIFF with EncoderParams - How?使用 EncoderParams 将 MemoryBmp 上的 Image.Save() 转换为 TIFF - 如何?
【发布时间】:2011-05-05 22:27:00
【问题描述】:

我有一个允许用户定义图像区域并将该区域保存到文件的应用程序。我遇到了一个我无法解决的障碍。我创建的用于绘制选定区域的位图被“MemoryBmp”的 ImageFormat 卡住,看起来这是为任何非文件加载位图设置的 ImageFormat。问题是我的位图是在内存中创建的,我想将其保存为 CCITT4 双色 TIFF,但我收到“GDI+ 中发生一般错误”异常。我非常有信心这是因为 Image.RawFormat 属性是可怕的 MemoryBmp。

Image.Save() 有一个带有 ImageFormat 参数的重载,当我使用该参数传递 ImageFormat.Tiff 时,它保存得很好,但我没有机会指定我的编码器参数。

我能想到的唯一可能的解决方法是使用 Image.Save(Image, ImageFormat) 将其保存到磁盘,然后重新加载(RawFormat 现在将正确设置为 ImageFormat.Tif),然后通过编码器设置再次保存。不过这很愚蠢,一定有更好的方法。

这是一段代码(这只是测试的东西),如果我之前的描述不够清楚,应该可以让您了解我在做什么:

SizeF dpiScale = GetScreenToImageDPIRatio(loadedImage);
using (Bitmap image = new Bitmap(loadedImage,
    (int)(_cropBox.Width * dpiScale.Width),
    (int)(_cropBox.Height * dpiScale.Height)))
{
    image.SetResolution(loadedImage.HorizontalResolution, 
        loadedImage.VerticalResolution);

    using (Graphics g = Graphics.FromImage(image))
    {
        g.DrawImage(loadedImage, 0, 0, new Rectangle(
            (int)(_cropBox.Location.X * dpiScale.Width),
            (int)(_cropBox.Location.Y * dpiScale.Height),
            (int)(_cropBox.Width * dpiScale.Width),
            (int)(_cropBox.Height * dpiScale.Height)),
            GraphicsUnit.Pixel);
    }

    //  It's stuck as a MemoryBmp so none of these checks will work
    if (true || image.RawFormat.Equals(ImageFormat.Tiff))
    {
        ImageCodecInfo tiffCodecInfo = ImageUtils.GetEncoderInfo("image/tiff");
        EncoderParameters myEncoderParameters = new EncoderParameters(2);

        myEncoderParameters.Param[0] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.Compression,
                (long)EncoderValue.CompressionCCITT4);
        myEncoderParameters.Param[1] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);

        image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
            tiffCodecInfo, myEncoderParameters);

        //  The file is a "MemoryBmp" and it's screwing things up
        //image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
        //    ImageFormat.Tiff);
    }
    else
    {
        //  other format saving support, blah blah blah
    }
}

哦,我应该提一下,“loadedIimage”确实是一个 tiff 图像,我将对 loadedImage 的引用传递给 Bitmap.ctor() 以查看它是否会提示它正在处理的内容,但它没有任何区别。

【问题讨论】:

  • 我的理论离我很远,它是 MemoryBmp。在阅读了一些 CCITT4 规范后,我了解到源应该是双色调的,而我的图像不是。但是,我还不相信,因为我似乎重新使用 CCITT4 保存灰度扫描。无论如何,只是想发表评论,以防有人正在研究这个......我会在做更多测试后更新。

标签: c# gdi+ system.drawing system.drawing.imaging


【解决方案1】:

发现 CCITT4 确实需要双色调图像,哈!所以我去谷歌搜索,发现CodeProject article 并在源代码中窥探。作者提供了一个相当不错的方法来将 32bppARGB 转换为 1bpp 双色调。我试过了,它很快(测试显示单页大约 34 毫秒),它成功了!

我正在回答我自己的问题。我希望这至少可以帮助遇到这个问题的其他人。

【讨论】:

  • @Hans - 我试过了,但我收到“你明天可以接受你自己的答案”。我昨晚收到了这条消息,现在正在收到。
  • @Hans - 似乎有问题,因为我又试了一次,收到了同样的消息。你能把它标记为我的答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
相关资源
最近更新 更多