System.Drawing.Image.Save抛出ExternalException异常:GDI发生了一般性错误。

4

我有一个函数,它接受一个位图,复制其中的一部分并将其保存为8bpp tiff格式。结果图像的文件名是唯一的且文件不存在,程序有写入目标文件夹的权限。

void CropImage(Bitmap map) {
        Bitmap croped = new Bitmap(200, 50);

        using (Graphics g = Graphics.FromImage(croped)) {
            g.DrawImage(map, new Rectangle(0, 0, 200, 50), ...);
        }

        var encoderParams = new EncoderParameters(2);
        encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8L);
        encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);

        croped.Save(filename, tiffEncoder, encoderParams);
        croped.Dispose();
    }

奇怪的是这个函数在一些电脑上(Win 7)运行良好,而在其他电脑上(大多数是Win XP)则会抛出System.Runtime.InteropServices.ExternalException:GDI中发生了通用错误异常。
所有电脑都安装了.NET 3.5 SP1运行时。
如果我使用croped.Save(filename, ImageFormat.Tiff);而不是croped.Save(filename, tiffEncoder, encoderParams);,那么它就可以在所有电脑上运行,但我需要以8bpp格式保存Tiff。
你有任何想法,问题可能出在哪里吗?
谢谢,Lukas

也许图片还没有保存,就开始被处理了? - serhio
它能在任何Windows XP机器上运行吗? - SLaks
你解决了吗?我有一个类似的问题 http://stackoverflow.com/questions/10381768/c-sharp-image-cant-be-opened-in-windows-xp-but-same-code-works-in-windows-7#10381768 - Juan
@Lukas Kabrt,你能找到这个问题的原因和解决方案吗? - UnhandledExcepSean
没有,我还没有找到任何解决办法。 - Lukas Kabrt
显示剩余3条评论
1个回答

1

GDI是Windows操作系统的功能。当处理16位TIFF文件时,我遇到了类似的问题,并采用了不同的库。请参见使用c#中的LibTIFF

MSDN帮助建议该功能可用,但在尝试将位图复制到新位图或将其保存到文件或流时,Windows会抛出“通用错误”异常。实际上,相同的功能在Windows7上运行良好(似乎具有良好的TIFF支持)。请参见Windows 7中的新WIC功能

我使用的另一种解决方案是进行8位的不安全复制。这样,我能够保存PNG文件(带调色板)。我没有尝试过这个方法来处理TIFF。

       // part of a function taking a proprietary TIFF tile structure as input and saving it into the desired bitmap format
      // tile.buf is a byterarray, containing 16-bit samples from TIFF.

        bmp = new Bitmap(_tile_width, _tile_height, PixelFormat.Format8bppIndexed);
        System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData =bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,bmp.PixelFormat);
        int bytes = bmpData.Stride * bmp.Height;

        dstBitsPalette = (byte *)bmpData.Scan0;

        offset=0;


        for (offset = 0; offset < _tile_size; offset += 2)
        {
             dstBitsPalette[offset >> 1] = tile.buf[offset + 1];
        }

        // setup grayscale palette
        ColorPalette palette = bmp.Palette;
        for (int i = 0; i < 256; i++)
        {
            Color c = Color.FromArgb(i, i, i);
            palette.Entries[i] = c;
        }
        bmp.Palette = palette;
        bmp.UnlockBits(bmpData);

        return bmp;

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接