GetEncoderParameterList意外的“位图区域已锁定”异常。有任何想法吗?

时间:2010-06-30 19:05:07

标签: c# visual-studio-2010 graphics .net-4.0 bitmap

我正在尝试使用Microsoft的此示例代码来确定JPEG编码器可用的编码器选项。 (我想解决的真正问题是看看我是否可以明确设置色度子采样参数)

http://msdn.microsoft.com/en-us/library/bb882589.aspx

private void GetSupportedParameters(PaintEventArgs e)
{
    Bitmap bitmap1 = new Bitmap(1, 1);
    ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
    EncoderParameters paramList = bitmap1.GetEncoderParameterList(jpgEncoder.Clsid);
    EncoderParameter[] encParams = paramList.Param;
    StringBuilder paramInfo = new StringBuilder();

    for (int i = 0; i < encParams.Length; i++)
    {
        paramInfo.Append("Param " + i + " holds " + encParams[i].NumberOfValues +
            " items of type " +
            encParams[i].ValueType + "\r\n" + "Guid category: " + encParams[i].Encoder.Guid + "\r\n");

    }
    e.Graphics.DrawString(paramInfo.ToString(), this.Font, Brushes.Red, 10.0F, 10.0F);
}

private ImageCodecInfo GetEncoder(ImageFormat format)
{

    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

    foreach (ImageCodecInfo codec in codecs)
    {
        if (codec.FormatID == format.Guid)
        {
            return codec;
        }
    }
    return null;
}

问题是,“GetEncoderParameterList”总是抛出异常:位图区域已经被锁定。

我尝试将代码放在程序的最开头,而不是在on-paint事件处理程序中。一样。我尝试改变位图上的位深度,并以其他方式创建位图,没有区别。

知道为什么.NET认为新创建的位图有一个锁定区域?


更新!更多信息:如果我使用TIFF编码器,它不会失败:

    Bitmap bitmap1 = new Bitmap(1, 1);
    ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.TIFF);  // TIFF instead of JPEG
    EncoderParameters paramList = bitmap1.GetEncoderParameterList(jpgEncoder.Clsid);
    EncoderParameter[] encParams = paramList.Param;

所以我认为这可能只是jpeg的GetEncoderparameterList的错误/限制....

2 个答案:

答案 0 :(得分:5)

我重复这个。异常消息是伪造的,这对于GDI +异常是常见的。问题的根源是jpeg编解码器,GetEncoderParameterList()查询它支持的参数列表。它返回的列表包含一个错误的条目,NumberOfValues为0.这导致Marshal.AllocHGlobal()返回NULL,误解为内存不足异常,转而被误解为“位图区域已被锁定“例外。

呃,GDI +肯定是一团糟。这个问题几乎肯定是GDI +版本1.10特有的,这是Vista首次发布的版本。也可能是Win7特定的,我已经看过几个关于该操作系统上JPEG编解码器问题的论坛帖子。

好吧,在下一个Windows服务包可用之前,你无能为力。要解决您的特定查询,不,可能不是。 GDI +知道的编码器参数列表列在GdiPlusImaging.h SDK头文件中。唯一接近的是“EncoderChrominanceTable”,在.NET框架中以Encoder.ChrominanceTable.Guid的形式提供。不知道这是否接近你正在寻找的东西。

你应该考虑WPF JpegBitmapEncoder类,这是对GDI =的重大改进。

答案 1 :(得分:0)

.NET Core 5.0已解决此问题-请参见https://github.com/dotnet/corefx/pull/40181