| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2410 人关注过本帖
标题:C# 实现GIF图片水印效果
只看楼主 加入收藏
wangnannan
Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18
等 级:贵宾
威 望:87
帖 子:2546
专家分:9359
注 册:2007-11-3
结帖率:80.91%
收藏
 问题点数:0 回复次数:10 
C# 实现GIF图片水印效果
之前自己试过GIF实现水印效果 最理想的一个是水印效果实现了 但是没有帧动画了 资质不行写不出来
 所以在网上搜了下 codeproject 就是有能人啊 俺在这里借花献佛
主要有六个类 AnimatedGifEncoder Frame GifDecoder GifHelper LZWEncoder NeuQuant 有注释英文的 一看便知
Gif_Faster.rar (258.55 KB)

例如:

程序代码:
using System;
using System.Cousing System;
using System.Drawing;
using using System.Drawing.Imaging;

#region .NET Disclaimer/Info
//===============================================================================
//
// gOODiDEA, //===============================================================================
//
// $Header :        $ 
// $Author :        $
// $Date   :        $
// $Revision:        $
// $History:        $ 
// 
//===============================================================================
#endregion 

#region Java
/**

 * Class AnimatedGifEncoder - Encodes a GIF file consisting of one or

 * more frames.

 * <pre>

 * Example:

 *    AnimatedGifEncoder e = new AnimatedGifEncoder();

 *    e.start(outputFileName);

 *    e.setDelay(1000);   // 1 frame per sec

 *    e.addFrame(image1);

 *    e.addFrame(image2);

 *    e.finish();

 * </pre>

 * No copyright asserted on the source code of this class.  May be used

 * for any purpose, however, refer to the Unisys LZW patent for restrictions

 * on use of the associated LZWEncoder class.  Please forward any corrections

 * to kweiner@*

 * @author Kevin Weiner, FM Software

 * @version 1.03 November 2003

 *

 */
#endregion

namespace {
    public class AnimatedGifEncoder
    {
        protected int width; // image size
        protected int height;
        protected Color transparent = Color.Empty; // transparent color if given
        protected int transIndex; // transparent index in color table
        protected int repeat = -1; // no repeat
        protected int delay = 0; // frame delay (hundredths)
        protected bool started = false; // ready to output frames
        //    protected BinaryWriter bw;
        protected FileStream fs;

        protected Image image; // current frame
        protected byte[] pixels; // BGR byte array from frame
        protected byte[] indexedPixels; // converted frame indexed to palette
        protected int colorDepth; // number of bit planes
        protected byte[] colorTab; // RGB palette
        protected bool[] usedEntry = new bool[256]; // active palette entries
        protected int palSize = 7; // color table size (bits-1)
        protected int dispose = -1; // disposal code (-1 = use default)
        protected bool closeStream = false; // close stream when finished
        protected bool firstFrame = true;
        protected bool sizeSet = false; // if false, get size from first frame
        protected int sample = 10; // default sample interval for quantizer

        /**
         * Sets the delay time between each frame, or changes it
         * for subsequent frames (applies to last frame added).
         *
         * @param ms int delay time in milliseconds
         */
        public void SetDelay(int ms)
        {
            delay = ms;// (int)Math.Round(ms / 10.0f);
        }
   
        /**
         * Sets the GIF frame disposal code for the last added frame
         * and any subsequent frames.  Default is 0 if no transparent
         * color has been set, otherwise 2.
         * @param code int disposal code.
         */
        public void SetDispose(int code)
        {
            if (code >= 0)
            {
                dispose = code;
            }
        }
   
        /**
         * Sets the number of times the set of GIF frames
         * should be played.  Default is 1; 0 means play
         * indefinitely.  Must be invoked before the first
         * image is added.
         *
         * @param iter int number of iterations.
         * @return
         */
        public void SetRepeat(int iter)
        {
            if (iter >= 0)
            {
                repeat = iter;
            }
        }
   
        /**
         * Sets the transparent color for the last added frame
         * and any subsequent frames.
         * Since all colors are subject to modification
         * in the quantization process, the color in the final
         * palette for each frame closest to the given color
         * becomes the transparent color for that frame.
         * May be set to null to indicate no transparent color.
         *
         * @param c Color to be treated as transparent on display.
         */
        public void SetTransparent(Color c)
        {
            transparent = c;
        }
   
        /**
         * Adds next GIF frame.  The frame is not written immediately, but is
         * actually deferred until the next frame is received so that timing
         * data can be inserted.  Invoking <code>finish()</code> flushes all
         * frames.  If <code>setSize</code> was not invoked, the size of the
         * first image is used for all subsequent frames.
         *
         * @param im BufferedImage containing frame to write.
         * @return true if successful.
         */
        public bool AddFrame(Image im)
        {
            if ((im == null) || !started)
            {
                return false;
            }
            bool ok = true;
            try
            {
                if (!sizeSet)
                {
                    // use first frame's size
                    SetSize(im.Width, im.Height);
                }
                image = im;
                GetImagePixels(); // convert to correct format if necessary
                AnalyzePixels(); // build color table & map pixels
                if (firstFrame)
                {
                    WriteLSD(); // logical screen descriptior
                    WritePalette(); // global color table
                    if (repeat >= 0)
                    {
                        // use NS app extension to indicate reps
                        WriteNetscapeExt();
                    }
                }
                WriteGraphicCtrlExt(); // write graphic control extension
                WriteImageDesc(); // image descriptor
                if (!firstFrame)
                {
                    WritePalette(); // local color table
                }
                WritePixels(); // encode and write pixel data
                firstFrame = false;
            }
            catch (IOException e)
            {
                ok = false;
            }

            return ok;
        }
   
        /**
         * Flushes any pending data and closes output file.
         * If writing to an OutputStream, the stream is not
         * closed.
         */
        public bool Finish()
        {
            if (!started) return false;
            bool ok = true;
            started = false;
            try
            {
                fs.WriteByte( 0x3b ); // gif trailer
                fs.Flush();
                if (closeStream)
                {
                    fs.Close();
                }
            }
            catch (IOException e)
            {
                ok = false;
            }

            // reset for subsequent use
            transIndex = 0;
            fs = null;
            image = null;
            pixels = null;
            indexedPixels = null;
            colorTab = null;
            closeStream = false;
            firstFrame = true;

            return ok;
        }
   
        /**
         * Sets frame rate in frames per second.  Equivalent to
         * <code>setDelay(1000/fps)</code>.
         *
         * @param fps float frame rate (frames per second)
         */
        public void SetFrameRate(float fps)
        {
            if (fps != 0f)
            {
                delay = ( int ) Math.Round(100f / fps);
            }
        }
   
        /**
         * Sets quality of color quantization (conversion of images
         * to the maximum 256 colors allowed by the GIF specification).
         * Lower values (minimum = 1) produce better colors, but slow
         * processing significantly.  10 is the default, and produces
         * good color mapping at reasonable speeds.  Values greater
         * than 20 do not yield significant improvements in speed.
         *
         * @param quality int greater than 0.
         * @return
         */
        public void SetQuality(int quality)
        {
            if (quality < 1) quality = 1;
            sample = quality;
        }
   
        /**
         * Sets the GIF frame size.  The default size is the
         * size of the first frame added if this method is
         * not invoked.
         *
         * @param w int frame width.
         * @param h int frame width.
         */
        public void SetSize(int w, int h)
        {
            if (started && !firstFrame) return;
            width = w;
            height = h;
            if (width < 1) width = 320;
            if (height < 1) height = 240;
            sizeSet = true;
        }
   
        /**
         * Initiates GIF file creation on the given stream.  The stream
         * is not closed automatically.
         *
         * @param os OutputStream on which GIF images are written.
         * @return false if initial write failed.
         */
        public bool Start( FileStream os)
        {
            if (os == null) return false;
            bool ok = true;
            closeStream = false;
            fs = os;
            try
            {
                WriteString("GIF89a"); // header
            }
            catch (IOException e)
            {
                ok = false;
            }
            return started = ok;
        }
   
        /**
         * Initiates writing of a GIF file with the specified name.
         *
         * @param file String containing output file name.
         * @return false if open or initial write failed.
         */
        public bool Start(String file)
        {
            bool ok = true;
            try
            {
                //            bw = new BinaryWriter( new FileStream( file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None ) );
                fs = new FileStream( file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None );
                ok = Start(fs);
                closeStream = true;
            }
            catch (IOException e)
            {
                ok = false;
            }
            return started = ok;
        }
   
        /**
         * Analyzes image colors and creates color map.
         */
        protected void AnalyzePixels()
        {
            int len = pixels.Length;
            int nPix = len / 3;
            indexedPixels = new byte[nPix];
            NeuQuant nq = new NeuQuant(pixels, len, sample);
            // initialize quantizer
            colorTab = nq.Process(); // create reduced palette
            // convert map from BGR to RGB
//            for (int i = 0; i < colorTab.Length; i += 3)
//            {
//                byte temp = colorTab[i];
//                colorTab[i] = colorTab[i + 2];
//                colorTab[i + 2] = temp;
//                usedEntry[i / 3] = false;
//            }
            // map image pixels to new palette
            int k = 0;
            for (int i = 0; i < nPix; i++)
            {
                int index =
                    nq.Map(pixels[k++] & 0xff,
                    pixels[k++] & 0xff,
                    pixels[k++] & 0xff);
                usedEntry[index] = true;
                indexedPixels[i] = (byte) index;
            }
            pixels = null;
            colorDepth = 8;
            palSize = 7;
            // get closest match to transparent color if specified
            if (transparent != Color.Empty )
            {
                transIndex = FindClosest(transparent);
            }
        }
   
        /**
         * Returns index of palette color closest to c
         *
         */
        protected int FindClosest(Color c)
        {
            if (colorTab == null) return -1;
            int r = c.R;
            int g = c.G;
            int b = c.B;
            int minpos = 0;
            int dmin = 256 * 256 * 256;
            int len = colorTab.Length;
            for (int i = 0; i < len;)
            {
                int dr = r - (colorTab[i++] & 0xff);
                int dg = g - (colorTab[i++] & 0xff);
                int db = b - (colorTab[i] & 0xff);
                int d = dr * dr + dg * dg + db * db;
                int index = i / 3;
                if (usedEntry[index] && (d < dmin))
                {
                    dmin = d;
                    minpos = index;
                }
                i++;
            }
            return minpos;
        }
   
        /**
         * Extracts image pixels into byte array "pixels"
         */
        protected void GetImagePixels()
        {
            int w = image.Width;
            int h = image.Height;
            //        int type = image.GetType().;
            if ((w != width)
                || (h != height)
                )
            {
                // create new image with right size/format
                Image temp =
                    new Bitmap(width, height );
                Graphics g = Graphics.FromImage( temp );
                g.DrawImage(image, 0, 0);
                image = temp;
                g.Dispose();
            }
            /*
                ToDo:
                improve performance: use unsafe code
            */
            pixels = new Byte [ 3 * image.Width * image.Height ];
            int count = 0;
            Bitmap tempBitmap = new Bitmap( image );
            int wh = image.Width;
            int he = image.Height;
            BitmapData bmpData = tempBitmap.LockBits(new Rectangle(0, 0, wh, he), ImageLockMode.ReadWrite, image.PixelFormat);
            unsafe
            {
                byte* p = (byte*)bmpData.Scan0.ToPointer();
                for (int i = 0; i < 4 * wh * he; i += 4)
                {
                    pixels[count] = *(p + i + 2);
                    count++;
                    pixels[count] = *(p + i + 1);
                    count++;
                    pixels[count] = *(p + i);
                    count++;
                }
            }
            tempBitmap.UnlockBits(bmpData);
            //for (int th = 0; th < image.Height; th++)
            //{
            //    for (int tw = 0; tw < image.Width; tw++)
            //    {
            //        Color color = tempBitmap.GetPixel(tw, th);
            //        pixels[count] = color.R;
            //        count++;
            //        pixels[count] = color.G;
            //        count++;
            //        pixels[count] = color.B;
            //        count++;
            //    }
            //}

            //        pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        }
   
        /**
         * Writes Graphic Control Extension
         */
        protected void WriteGraphicCtrlExt()
        {
            fs.WriteByte(0x21); // extension introducer
            fs.WriteByte(0xf9); // GCE label
            fs.WriteByte(4); // data block size
            int transp, disp;
            if (transparent == Color.Empty )
            {
                transp = 0;
                disp = 0; // dispose = no action
            }
            else
            {
                transp = 1;
                disp = 2; // force clear if using transparent color
            }
            if (dispose >= 0)
            {
                disp = dispose & 7; // user override
            }
            disp <<= 2;

            // packed fields
            fs.WriteByte( Convert.ToByte( 0 | // 1:3 reserved
                disp | // 4:6 disposal
                0 | // 7   user input - 0 = none
                transp )); // 8   transparency flag

            WriteShort(delay); // delay x 1/100 sec
            fs.WriteByte( Convert.ToByte( transIndex)); // transparent color index
            fs.WriteByte(0); // block terminator
        }
   
        /**
         * Writes Image Descriptor
         */
        protected void WriteImageDesc()
        {
            fs.WriteByte(0x2c); // image separator
            WriteShort(0); // image position x,y = 0,0
            WriteShort(0);
            WriteShort(width); // image size
            WriteShort(height);
            // packed fields
            if (firstFrame)
            {
                // no LCT  - GCT is used for first (or only) frame
                fs.WriteByte(0);
            }
            else
            {
                // specify normal LCT
                fs.WriteByte( Convert.ToByte( 0x80 | // 1 local color table  1=yes
                    0 | // 2 interlace - 0=no
                    0 | // 3 sorted - 0=no
                    0 | // 4-5 reserved
                    palSize ) ); // 6-8 size of color table
            }
        }
   
        /**
         * Writes Logical Screen Descriptor
         */
        protected void WriteLSD() 
        {
            // logical screen size
            WriteShort(width);
            WriteShort(height);
            // packed fields
            fs.WriteByte( Convert.ToByte (0x80 | // 1   : global color table flag = 1 (gct used)
                0x70 | // 2-4 : color resolution = 7
                0x00 | // 5   : gct sort flag = 0
                palSize) ); // 6-8 : gct size

            fs.WriteByte(0); // background color index
            fs.WriteByte(0); // pixel aspect ratio - assume 1:1
        }
   
        /**
         * Writes Netscape application extension to define
         * repeat count.
         */
        protected void WriteNetscapeExt()
        {
            fs.WriteByte(0x21); // extension introducer
            fs.WriteByte(0xff); // app extension label
            fs.WriteByte(11); // block size
            WriteString("NETSCAPE" + "2.0"); // app id + auth code
            fs.WriteByte(3); // sub-block size
            fs.WriteByte(1); // loop sub-block id
            WriteShort(repeat); // loop count (extra iterations, 0=repeat forever)
            fs.WriteByte(0); // block terminator
        }
   
        /**
         * Writes color table
         */
        protected void WritePalette()
        {
            fs.Write(colorTab, 0, colorTab.Length);
            int n = (3 * 256) - colorTab.Length;
            for (int i = 0; i < n; i++)
            {
                fs.WriteByte(0);
            }
        }
   
        /**
         * Encodes and writes pixel data
         */
        protected void WritePixels()
        {
            LZWEncoder encoder =
                new LZWEncoder(width, height, indexedPixels, colorDepth);
            encoder.Encode( fs );
        }
   
        /**
         *    Write 16-bit value to output stream, LSB first
         */
        protected void WriteShort(int value)
        {
            fs.WriteByte( Convert.ToByte( value & 0xff));
            fs.WriteByte( Convert.ToByte( (value >> 8) & 0xff ));
        }
   
        /**
         * Writes string to output stream
         */
        protected void WriteString(String s)
        {
            char[] chars = s.ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                fs.WriteByte((byte) chars[i]);
            }
        }
    }

}
很多代码啊 就不全贴出来了 大家慢慢看吧 效果还行 只是可惜小的GIF图片有延迟

[ 本帖最后由 wangnannan 于 2010-12-20 13:16 编辑 ]
搜索更多相关主题的帖子: 效果 GIF 水印 
2010-12-20 13:14
cccool
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:268
专家分:555
注 册:2007-5-1
收藏
得分:0 
好东西,楼主辛苦了

[fly]让心情飞一会[/fly]
">Email to Me     
2010-12-20 13:51
wang8031817
Rank: 1
等 级:新手上路
帖 子:18
专家分:1
注 册:2010-12-18
收藏
得分:0 
偶像啊~
2010-12-20 18:29
test1021
Rank: 1
等 级:新手上路
帖 子:16
专家分:3
注 册:2008-10-21
收藏
得分:0 
真是好东东啊
感谢 
2010-12-21 08:58
道道追求
Rank: 1
等 级:新手上路
帖 子:4
专家分:2
注 册:2010-4-1
收藏
得分:0 
东西挺好,就是英文的,还得去查词典,囧~
2010-12-22 13:16
caotie1986
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2010-12-15
收藏
得分:0 
谢谢了楼主
2010-12-23 11:07
sfhnsoft
Rank: 1
等 级:新手上路
帖 子:13
专家分:0
注 册:2011-10-14
收藏
得分:0 
谢谢了楼主
2011-10-20 10:13
lins2011
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2011-11-30
收藏
得分:0 
谢谢了,可惜背景透明的GIF图片,生成的GIF图片背景不透明~
2011-11-30 00:16
erton_zyh
Rank: 2
等 级:论坛游民
帖 子:27
专家分:15
注 册:2011-11-4
收藏
得分:0 
学习。。。
2011-12-04 18:15
monsterty
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2018-3-1
收藏
得分:0 
学习。。。
2018-03-01 14:29
快速回复:C# 实现GIF图片水印效果
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.084177 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved