【问题标题】:System.Drawing.Image.Save throws ExternalException: A generic error occurred in GDISystem.Drawing.Image.Save 引发 ExternalException:GDI 中发生一般错误
【发布时间】:2012-05-02 19:13:42
【问题描述】:

我有一个函数,它需要一个位图,复制它的一部分并将其保存为 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)并抛出 System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI exception in other computer(主要是 Win XP)。

所有计算机都安装了 .NET 3.5 SP1 运行时。

如果我使用croped.Save(filename, ImageFormat.Tiff); 而不是croped.Save(filename, tiffEncoder, encoderParams);,则它适用于所有计算机,但我需要以 8bpp 格式保存 Tiff。

你有什么想法,问题可能出在哪里?

谢谢,卢卡斯

【问题讨论】:

  • 可能图片还没保存,开始处理?
  • 有没有可以运行的 Windows XP 机器?
  • GDI+ 在 Vista 中已更新至 1.1 版。我从来没有找到任何描述这些变化的文档。听起来你找到了。
  • (将答案从 OP 移至评论):SLaks:我已经在两台 Wn XP 计算机上测试过,但都没有工作。
  • 既然你的代码看起来完全没问题......那么“tiffEncoder”呢......问题可能在那里吗?

标签: .net exception gdi+ tiff


【解决方案1】:

GDI 是一个windows 操作系统的功能。我在处理 16 位 TIFF 文件时遇到了类似的问题,于是求助于不同的库。见using LibTIFF from c#

MSDN 帮助建议该功能可用,但是当您尝试将位图复制到新位图或将其保存到文件或流时,Windows 会引发“一般错误”异常。事实上,相同的功能在 Windows7 上运行良好(似乎有很好的 TIFF 支持)。见New WIC functioanity in Windows 7

我使用的另一个解决方案是制作 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;

    }

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 2011-12-03
    • 2015-08-21
    • 2014-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多