Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GDI+;将24bpp JPG转换为8bpp索引格式(PNG或GIF)时出错_C#_.net_Image_Bitmap - Fatal编程技术网

C# GDI+;将24bpp JPG转换为8bpp索引格式(PNG或GIF)时出错

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

我需要一个通用函数将图像转换为目标格式。(本例中为Format8BPindexed)目标是能够处理合理范围的常规.NET支持的映像。我们有很多客户机,它们拥有数百TB的不同类型的图像,我计划用这些代码对它们进行循环

下面是我试图转换的一个示例图像,它抛出了错误:

我意识到这段代码有多个内部try捕获,但是我想说明这个问题

在下面的每次尝试中,我都会给出一些注释,显示我收到的异常和错误

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的内存。