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

本文介绍了一种使用C#生成GIF格式缩略图的方法,解决了透明背景问题,并提供了高质量的图片缩放功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文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其他格式的缩略图输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值