zoukankan      html  css  js  c++  java
  • GDI+中常见的几个问题(6)

    6.2 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标准所决定的。

     1         public static unsafe void ConvertTransparancyGif(int colorIndex, string baseFile, string outputFile)
     2         {
     3             using (FileStream fs = new FileStream(baseFile, FileMode.Open, FileAccess.Read))
     4             {
     5                 Bitmap img = (Bitmap)Image.FromStream(fs, falsefalse);
     6                 int width = img.Width;
     7                 int height = img.Height;
     8 
     9                 Bitmap resultbmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
    10                 ColorPalette palette = resultbmp.Palette;
    11                 int n = 0;
    12                 foreach (Color tc in img.Palette.Entries)
    13                 {
    14                     palette.Entries[n] = Color.FromArgb(255, tc);
    15                     n++;
    16                 }
    17 
    18                 palette.Entries[colorIndex] = Color.FromArgb(0, palette.Entries[colorIndex]);
    19                 resultbmp.Palette = palette;
    20 
    21                 //now to copy the actual bitmap data 
    22                 BitmapData src = img.LockBits(
    23                     new Rectangle(00, width, height),
    24                     ImageLockMode.ReadOnly,
    25                     img.PixelFormat);
    26 
    27                 BitmapData dst = resultbmp.LockBits(
    28                     new Rectangle(00, width, height),
    29                     ImageLockMode.WriteOnly,
    30                     resultbmp.PixelFormat);
    31 
    32                 byte* pSrc = (byte*)src.Scan0.ToPointer();
    33                 byte* pDst = (byte*)dst.Scan0.ToPointer();
    34                 int offset = src.Stride - width;
    35 
    36                 //steps through each pixel 
    37                 for (int y = 0; y < height; y++)
    38                 {
    39                     for (int x = 0; x < width; x++)
    40                     {
    41                         pDst[0= pSrc[0];
    42                         pDst++;
    43                         pSrc++;
    44                     }
    45                     pDst += offset;
    46                     pSrc += offset;
    47                 }
    48 
    49                 //unlock the bitmaps 
    50                 img.UnlockBits(src);
    51                 resultbmp.UnlockBits(dst);
    52 
    53                 resultbmp.Save(outputFile, ImageFormat.Gif);
    54 
    55                 img.Dispose();
    56                 resultbmp.Dispose();
    57             } 
    59         }

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


    最后提一句,Bitmap类还提供了一个MakeTransparent方法用于设置透明颜色,不过只对PNG有效。

  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/hotcan/p/1322360.html
Copyright © 2011-2022 走看看