C#中保存GIF文件后透明背景问题的最终解决方法

来源:互联网 发布:金山毒霸添加信任软件 编辑:程序博客网 时间:2024/05/20 23:12

前文C#中保存GIF文件后透明背景问题的一个解决方法有个较为明显的缺陷,就是调色板的固定,导致颜色显示不理想,现根据网友传来的另一版本,解决如下:

using System;using System.Drawing;using System.Drawing.Imaging;using System.Drawing.Drawing2D;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.IO;namespace Thumb{    public class ThumbMaker    {        Double xFactor;        Double yFactor;        System.IntPtr sourceScan0;        int sourceStride;        Bitmap scaledBitmap, bitmap;        public ThumbMaker(string fileName)        {            bitmap = new Bitmap(fileName);        }        public ThumbMaker(Stream stream)        {            bitmap = new Bitmap(stream);        }        void AdjustSizes(ref int xSize, ref int ySize)        {            if (xSize != 0 && ySize == 0)                ySize = Math.Abs((int)(xSize * bitmap.Height / bitmap.Width));            else if (xSize == 0 && ySize != 0)                xSize = Math.Abs((int)(ySize * bitmap.Width / bitmap.Height));            else if (xSize == 0 && ySize == 0)            {                xSize = bitmap.Width;                ySize = bitmap.Height;            }        }        void IndexedRezise(int xSize, int ySize)        {            BitmapData sourceData;            BitmapData targetData;            //AdjustSizes(ref xSize, ref ySize);            scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat);            scaledBitmap.Palette = bitmap.Palette;            sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),                ImageLockMode.ReadOnly, bitmap.PixelFormat);            try            {                targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize),                    ImageLockMode.WriteOnly, scaledBitmap.PixelFormat);                try                {                    xFactor = (Double)bitmap.Width / (Double)scaledBitmap.Width;                    yFactor = (Double)bitmap.Height / (Double)scaledBitmap.Height;                    sourceStride = sourceData.Stride;                    sourceScan0 = sourceData.Scan0;                    int targetStride = targetData.Stride;                    System.IntPtr targetScan0 = targetData.Scan0;                    unsafe                    {                        byte* p = (byte*)(void*)targetScan0;                        int nOffset = targetStride - scaledBitmap.Width;                        int nWidth = scaledBitmap.Width;                        for (int y = 0; y < scaledBitmap.Height; ++y)                        {                            for (int x = 0; x < nWidth; ++x)                            {                                p[0] = GetSourceByteAt(x, y);                                ++p;                            }                            p += nOffset;                        }                    }                }                finally                {                    scaledBitmap.UnlockBits(targetData);                }            }            finally            {                bitmap.UnlockBits(sourceData);            }        }        byte GetSourceByteAt(int x, int y)        {            unsafe            {                return ((byte*)((int)sourceScan0 + (int)(Math.Floor(y * yFactor) * sourceStride) +                    (int)Math.Floor(x * xFactor)))[0];            }        }        void RGBRezise(int xSize, int ySize)        {            //AdjustSizes(ref xSize, ref ySize);            scaledBitmap = new Bitmap(xSize, ySize, PixelFormat.Format24bppRgb);            Graphics g = Graphics.FromImage(scaledBitmap);            Rectangle destRect = new Rectangle(0, 0, xSize, ySize);            g.InterpolationMode = InterpolationMode.HighQualityBicubic;            g.SmoothingMode = SmoothingMode.AntiAlias;            g.DrawImage(bitmap, destRect, new Rectangle(100, 100, bitmap.Width - 100, bitmap.Height - 100), GraphicsUnit.Pixel);        }        void Save(string fileName, ImageFormat format)        {            scaledBitmap.Save(fileName, format);        }        void Save(string fileName, long jQuality, ImageFormat format)        {            ImageCodecInfo jpegCodecInfo = GetEncoderInfo("image/jpeg");            Encoder qualityEncoder = Encoder.Quality;            EncoderParameters encoderParams = new EncoderParameters(1);            EncoderParameter qualityEncoderParam = new EncoderParameter(qualityEncoder, jQuality);            encoderParams.Param[0] = qualityEncoderParam;            scaledBitmap.Save(fileName, jpegCodecInfo, encoderParams);        }        void Save(Stream stream, ImageFormat format)        {            scaledBitmap.Save(stream, format);        }        void Save(Stream stream, long jQuality, ImageFormat format)        {            ImageCodecInfo jpegCodecInfo = GetEncoderInfo("image/jpeg");            Encoder qualityEncoder = Encoder.Quality;            EncoderParameters encoderParams = new EncoderParameters(1);            EncoderParameter qualityEncoderParam = new EncoderParameter(qualityEncoder, jQuality);            encoderParams.Param[0] = qualityEncoderParam;            scaledBitmap.Save(stream, jpegCodecInfo, encoderParams);        }        ImageCodecInfo GetEncoderInfo(String mimeType)        {            int j;            ImageCodecInfo[] encoders;            encoders = ImageCodecInfo.GetImageEncoders();            for (j = 0; j < encoders.Length; ++j)            {                if (encoders[j].MimeType.ToUpper() == mimeType.ToUpper())                    return encoders[j];            }            return null;        }        public void ResizeToJpeg(int xSize, int ySize, string fileName)        {            this.RGBRezise(xSize, ySize);            this.Save(fileName, ImageFormat.Jpeg);        }        public void ResizeToJpeg(int xSize, int ySize, Stream stream)        {            this.RGBRezise(xSize, ySize);            this.Save(stream, ImageFormat.Jpeg);        }        public void ResizeToJpeg(int xSize, int ySize, long jQuality, string fileName)        {            this.RGBRezise(xSize, ySize);            this.Save(fileName, jQuality, ImageFormat.Jpeg);        }        public void ResizeToJpeg(int xSize, int ySize, long jQuality, Stream stream)        {            this.RGBRezise(xSize, ySize);            this.Save(stream, jQuality, ImageFormat.Jpeg);        }        public void ResizeToGif(int xSize, int ySize, string fileName)        {            this.IndexedRezise(xSize, ySize);            this.Save(fileName, ImageFormat.Gif);        }        public void ResizeToGif(int xSize, int ySize, Stream stream)        {            this.IndexedRezise(xSize, ySize);            this.Save(stream, ImageFormat.Gif);        }  public Bitmap ResizeToGif(int xSize, int ySize)        {            this.IndexedRezise(xSize, ySize);            return scaledBitmap;        }        public void ResizeToPng(int xSize, int ySize, string fileName)        {            this.IndexedRezise(xSize, ySize);            this.Save(fileName, ImageFormat.Png);        }        public void ResizeToPng(int xSize, int ySize, Stream stream)        {            this.IndexedRezise(xSize, ySize);            this.Save(stream, ImageFormat.Png);        }    }}// 以下是调用方法:Thumb.ThumbMaker thumbMaker = new Thumb.ThumbMaker("GIF源文件路径"); // 得到BMP对象Bitmap bmp = thumbMaker.ResizeToGif(100, 100);// 或:保存到文件thumbMaker.ResizeToGif(100,100,"缩略图文件路径");// 或:保存到输出流thumbMaker.ResizeToGif(100,100,流输出);

本程序也可以实现GIF、PNG其他格式的缩略图输出。