【问题标题】:Unexpected "Bitmap Region is already Locked" exception with GetEncoderParameterList. Any ideas?GetEncoderParameterList 出现意外的“位图区域已锁定”异常。有任何想法吗?
【发布时间】:2011-03-10 07:29:48
【问题描述】:

我正在尝试使用 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”总是抛出异常:Bitmap Region Is already Locked。

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

知道为什么 .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 的错误/限制....

【问题讨论】:

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


    【解决方案1】:

    我复制了这个。异常消息是虚假的,这对于 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= 的重大改进。

    【讨论】:

    • 谢谢!设置色度正是我想要做的。
    • 系统:Windows 7 x64、VisualStudio 2013、dotNET 4.5、C#。我尝试使用 Microsoft 提供的代码:“docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/…”以及所有可用的 ImageFormat 值,结果是它们都不起作用。 ImageFormat.Bmp 返回“未实现”,其余编解码器在 IntPtr 到 Int32() 处返回“算术运算导致溢出”。因此,确定哪些编解码器支持哪些参数的唯一方法是反复试验。
    • 不,这个例外意味着非常非常不同的东西。讨厌的问题,谷歌一下。
    【解决方案2】:

    这是针对 .NET Core 5.0 解决的 - 请参阅 https://github.com/dotnet/runtime/pull/32873

    【讨论】:

      猜你喜欢
      • 2012-12-15
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      • 2017-07-17
      相关资源
      最近更新 更多