我正在尝试使用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的错误/限制....
答案 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。