C# GDI+;将24bpp JPG转换为8bpp索引格式(PNG或GIF)时出错
我需要一个通用函数将图像转换为目标格式。(本例中为Format8BPindexed)目标是能够处理合理范围的常规.NET支持的映像。我们有很多客户机,它们拥有数百TB的不同类型的图像,我计划用这些代码对它们进行循环 下面是我试图转换的一个示例图像,它抛出了错误: 我意识到这段代码有多个内部try捕获,但是我想说明这个问题 在下面的每次尝试中,我都会给出一些注释,显示我收到的异常和错误C# GDI+;将24bpp JPG转换为8bpp索引格式(PNG或GIF)时出错,c#,.net,image,bitmap,C#,.net,Image,Bitmap,我需要一个通用函数将图像转换为目标格式。(本例中为Format8BPindexed)目标是能够处理合理范围的常规.NET支持的映像。我们有很多客户机,它们拥有数百TB的不同类型的图像,我计划用这些代码对它们进行循环 下面是我试图转换的一个示例图像,它抛出了错误: 我意识到这段代码有多个内部try捕获,但是我想说明这个问题 在下面的每次尝试中,我都会给出一些注释,显示我收到的异常和错误 public static Bitmap ConvertToFormat(this Bitmap Source
public static Bitmap ConvertToFormat(this Bitmap Source, PixelFormat TargetFormat)
{
try
{
//This throws OutOfMemoryException: "Out of memory."
return Source.Clone(new Rectangle(0, 0, Source.Width, Source.Height), TargetFormat);
}
catch (OutOfMemoryException)
{
try
{
MemoryStream ResultStream = new MemoryStream();
// This throws ExternalException: "A generic error occurred in GDI+"
Source.Save(ResultStream, ImageFormat.Gif);
ResultStream.Position = 0;
return new Bitmap(ResultStream);
}
catch (ExternalException)
{
// this is just an attempt to break the process down further to try and find the cause:
ImageCodecInfo myImageCodecInfo = GetCodecInfo(ImageFormat.Gif);
EncoderParameters myEncoderParameters = new EncoderParameters(2);
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW); ;
myEncoderParameters.Param[1] = new EncoderParameter(Encoder.Quality, 0L);
MemoryStream ResultStream = new MemoryStream();
// This throws ExternalException: "A generic error occurred in GDI+"
Source.Save(ResultStream, myImageCodecInfo, myEncoderParameters);
ResultStream.Position = 0;
return new Bitmap(ResultStream);
}
}
}
private static ImageCodecInfo GetCodecInfo(ImageFormat TargetFormat)
{
return ImageCodecInfo.GetImageEncoders().ToList().Find(
delegate (ImageCodecInfo codec)
{ return codec.FormatID == TargetFormat.Guid; });
}
我知道源图像很好,因为我可以使用LockBits()读取像素。我正在考虑使用一个循环来创建一个新的图像像素,但我更喜欢使用更直接的克隆选项,因为它可以自动处理调色板创建、颜色匹配和抖动
更新:我找到了导致问题的代码,但我不确定原因。 我不希望文件被锁定,所以我使用下面的代码将图像加载到内存中,然后解锁文件。显然,这会导致问题,但只有在调用Clone()方法时才会发生。当我将同一图像与LockBits()一起使用时,它允许我通过内存指针很好地访问每个像素,并且它在PictureBox中的显示也很好。有人知道为什么这个方法会导致.Clone()错误,以及我如何将图像文件加载到内存中,然后立即释放该文件吗
using (Stream s = File.OpenRead(SourceFileName))
{
return (Bitmap)Bitmap.FromStream(s);
}
您使用的是哪个版本的.Net?使用.NET4.5,使用您的初始代码和提供的图像,我可以将其保存为8bpp索引png,而不会引发任何异常。Hmm。。我被设置为4.6.1 x64,但我只是尝试了任何CPU 4.5、4.5.1、4.5.2、4.6,它们都不起作用。如果你从这里下载图像,它能起作用吗?(猜测上面的图片上传时被SO/Imgur修改了)我也想到了这一点,发布后立即尝试了一下。如果你能让这段代码正常工作,那么我的配置和你的配置肯定有些不同。我有另一台服务器,我可以在上面试一下,不过我需要一段时间来设置所有内容。好吧,考虑到这是一个OutOfMemory异常,我应该注意,我在这台机器上有32GB的内存。