使用EncoderParams将MemoryBmp上的Image.Save()转换为TIFF - 如何?

时间:2010-11-06 03:37:03

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

我有一个应用程序,允许用户定义图像的区域并将该区域保存到文件。我遇到了一个我无法解决的障碍。我创建的用于绘制所选区域的位图卡在“MemoryBmp”的ImageFormat中,看起来这是为任何非文件加载的位图设置的ImageFormat。问题是我的Bitmap是在内存中创建的,我想将它保存为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图像,我将对loadImage的引用传递给了Bitmap.ctor(),看看是否能够理解它正在处理的内容但它没有任何区别。

1 个答案:

答案 0 :(得分:5)

想出CCITT4需要双色调图像,哈哈!所以我去谷歌搜索并遇到CodeProject article并在源头窥探。作者提供了一种相当不错的方法将32bppARGB转换为1bpp双色调。我尝试了它并且速度很快(测试显示单页大约34毫秒)并且它完成了这个伎俩!

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