C#使用GDI+实现GIF图片透明

GIF的全称是图像交换格式Graphics Interchange Format,是CompuServe公司在1987年创建并使用 的。这种格式使用8位索引值来表达一个像素,也就是说1个像素1个byte,最多可以表示256种颜色。它使用LZW无损压缩算法来对图像进行压缩,之后 这家公司又和几家其他的公司发明了PNG文件格式,并被更广泛地应用在Web以及其他领域。GIF支持动画,可以保存数个帧并不断地播放。关于动画的部分 我们将会放到非常后面来讲,现在只谈谈GIF的透明。
在GIF文件的头部有一个调色板Palette,里面保存了颜色的信息。一般而言,如果对 GIF进行LockBits的操作,只能把它lock成Format*bppIndexed,这样才不会导致前面调色板信息的丢失,在处理上也更方便一 些。在调色板里面定义了透明的颜色,也就是说当实际数据为这个颜色时,那个位置的颜色为透明。让我们来看看Palette是怎么使用的。 顺便再说一句,GIF没有半透明,只支持完全透明或者不透明。此外,在一个调色板中,只有一种颜色可以设置为透明,这是GIF标准所决定 的。

public static unsafe void ConvertTransparancyGif(int colorIndex, string baseFile, string outputFile)
{
    using (FileStream fs = new FileStream(baseFile, FileMode.Open, FileAccess.Read))
    {
        Bitmap img = (Bitmap)Image.FromStream(fs, false, false);
        int width = img.Width;
        int height = img.Height;

        Bitmap resultbmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
        ColorPalette palette = resultbmp.Palette;
        int n = 0;
        foreach (Color tc in img.Palette.Entries)
        {
            palette.Entries[n] = Color.FromArgb(255, tc);
            n++;
        }

        palette.Entries[colorIndex] = Color.FromArgb(0, palette.Entries[colorIndex]);
        resultbmp.Palette = palette;

        //now to copy the actual bitmap data
        BitmapData src = img.LockBits(
            new Rectangle(0, 0, width, height),
            ImageLockMode.ReadOnly,
            img.PixelFormat);

        BitmapData dst = resultbmp.LockBits(
            new Rectangle(0, 0, width, height),
            ImageLockMode.WriteOnly,
            resultbmp.PixelFormat);

        byte* pSrc = (byte*)src.Scan0.ToPointer();
        byte* pDst = (byte*)dst.Scan0.ToPointer();
        int offset = src.Stride - width;

        //steps through each pixel
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                pDst[0] = pSrc[0];
                pDst++;
                pSrc++;
            }
            pDst += offset;
            pSrc += offset;
        }

        //unlock the bitmaps
        img.UnlockBits(src);
        resultbmp.UnlockBits(dst);

        resultbmp.Save(outputFile, ImageFormat.Gif);

        img.Dispose();
        resultbmp.Dispose();
    }
}

请注意,在这里,我读图的时候和我之前推荐的方法不同。 我没有创建一个新的Bitmap,这是因为在创建新的Bitmap的时候,调色板信息会完全丢失,所以Indexed的格式不可以随意进行复制,否则将造成信息的丢失。这也就是为什么当时我说这是一个土办法的原因。真正的好办法是复制那个流,而不是直接去复制Bitmap。不过那是看需求的。在创建一个带透明颜色的GIF的时候,只要创建一个调色板,就一切OK了。这比Alpha通道修正要简单。还可以参考
KB 319061 http://support.microsoft.com/kb/319061/en-us

共有0个回答