我最近在实现我的WMS服务器的时候,发现了一个超级郁闷的问题,问题描述如下:客户需要动态叠加一个透明层到底图上,比如说公交线路层,这个层有透明背景,于是可以叠加到其他图层上去。使用openlayer动态叠加图层很方便,我想这还不容易,使用透明png不就OK了,测试结果表明,在我机器的IE8上,非常正常。我正暗自得意,另一位兄弟用IE6一看,完蛋了,IE6不支持透明PNG,汗,这下要了命了,赶紧翻openlayers的资料,发现可以针对IE6特别使用透明滤镜。使用方法很方便,只要设置要透明的层 属性 alpha=true即可。测试后发现,透明是透明了,但是由于图片瓦块数过多,导致IE6被拖得半死,反应缓慢。汗,于是我想,那就对路线层使用gif格式呗,gif不也可以透明背景么。于是,悲剧出现了。为了解说清楚,我以一个PLMM为模特,嘿嘿

              首先呢,我们准备一个PLMM,嘿嘿:asp.net生成透明gif的准完美方案

       大家看到PLMM帽子边上的那个黄色圆圈了吗?一会我们就要将它变成透明的,生成一张可以在IE6中透明的GIF图。

      首先呢,我们使用常规方式:

 1asp.net生成透明gif的准完美方案Dim gif1 As New Bitmap("plmm.jpg")
 2asp.net生成透明gif的准完美方案        gif1.MakeTransparent(Color.Yellow)
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif1
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '这里我将它保存为gif到流里,这里是内存流,在asp.net中则是outputstream ,再显示在picturebox2里
 6asp.net生成透明gif的准完美方案        Dim ms As New System.IO.MemoryStream()
 7asp.net生成透明gif的准完美方案        gif1.Save(ms, Imaging.ImageFormat.Gif)
 8asp.net生成透明gif的准完美方案
 9asp.net生成透明gif的准完美方案        Dim gif2 = Bitmap.FromStream(ms)
10asp.net生成透明gif的准完美方案        ms.Dispose()
11asp.net生成透明gif的准完美方案
12asp.net生成透明gif的准完美方案        PictureBox2.Image = gif2
13asp.net生成透明gif的准完美方案
14asp.net生成透明gif的准完美方案        '***变黑了****

 

这个结果是十分令人沮丧的:那个圆圈非但没透明,甚至还变成了黑色:

asp.net生成透明gif的准完美方案

那么如果我直接保存为文件呢?图我就不贴了,和上面一样,还是黑的。

 

1asp.net生成透明gif的准完美方案        Dim gif1 As New Bitmap("plmm.jpg")
2asp.net生成透明gif的准完美方案        gif1.MakeTransparent(Color.Yellow)
3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif1
4asp.net生成透明gif的准完美方案
5asp.net生成透明gif的准完美方案        '***直接保存为文件:***
6asp.net生成透明gif的准完美方案        gif1.Save("out1.gif", Imaging.ImageFormat.Gif)
7asp.net生成透明gif的准完美方案
8asp.net生成透明gif的准完美方案        '***还是黑的**********
9asp.net生成透明gif的准完美方案        PictureBox2.ImageLocation = "out1.gif"

 

 这是我网上进行了一番搜索,大致上可以搜到这么一个版本:先修改调色板,然后再另外拷贝数据。

大致原理是:GIF是一种索引图像,最大色彩数256色 (PS:其实这个色彩数不少了,想当年,我上学时候经常逃课去玩

世嘉五代 MD游戏机,那个同屏发色数才16色,同期的超级任天堂的同屏发色数也不过256色,呵呵,这些都是从<<电子游戏软件>>里看来的)

GIF有一个调色板,最大有256个颜色索引,然后每个像素保存的是调色板的颜色索引值。故此,只需修改调色板,即可调整

图像的颜色。

OK,那么我们来改下调色板:

 

 1asp.net生成透明gif的准完美方案        '***我们读取上一步生成的不透明gif
 2asp.net生成透明gif的准完美方案        Dim gif As New Bitmap("out1.gif")
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '***获取色板***
 6asp.net生成透明gif的准完美方案        Dim pal = gif.Palette
 7asp.net生成透明gif的准完美方案
 8asp.net生成透明gif的准完美方案        For i As Integer = 0 To pal.Entries.Length - 1
 9asp.net生成透明gif的准完美方案            Dim color = pal.Entries(i)
10asp.net生成透明gif的准完美方案            '***将黑色改为透明,并且玩个反色特效,嘿嘿***
11asp.net生成透明gif的准完美方案            If color.R = 0 And color.G = 0 And color.B = 0 Then
12asp.net生成透明gif的准完美方案                pal.Entries(i) = color.Transparent
13asp.net生成透明gif的准完美方案            Else
14asp.net生成透明gif的准完美方案                pal.Entries(i) = color.FromArgb(255, color.B, color.G, color.R)
15asp.net生成透明gif的准完美方案            End If
16asp.net生成透明gif的准完美方案
17asp.net生成透明gif的准完美方案        Next
18asp.net生成透明gif的准完美方案
19asp.net生成透明gif的准完美方案        Dim gif2 As Bitmap = gif.Clone()
20asp.net生成透明gif的准完美方案        gif2.Palette = pal
21asp.net生成透明gif的准完美方案
22asp.net生成透明gif的准完美方案        PictureBox2.Image = gif2

 

结果如图: asp.net生成透明gif的准完美方案 

 

看起来效果不错,纯黑色部分被透明了!而且么,还出来个反色特效,HOHO

不过你不要高兴得太早,如果这时候你保存的话,它还是黑的!!

这是我们需要使用拷贝位图数据的办法来处理:

 

 1asp.net生成透明gif的准完美方案'***我们读取上一步生成的不透明gif
 2asp.net生成透明gif的准完美方案        Dim gif As New Bitmap("out1.gif")
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '***获取色板***
 6asp.net生成透明gif的准完美方案        Dim pal = gif.Palette
 7asp.net生成透明gif的准完美方案
 8asp.net生成透明gif的准完美方案        For i As Integer = 0 To pal.Entries.Length - 1
 9asp.net生成透明gif的准完美方案            Dim color = pal.Entries(i)
10asp.net生成透明gif的准完美方案            '***将黑色改为透明***
11asp.net生成透明gif的准完美方案            If color.R = 0 And color.G = 0 And color.B = 0 Then
12asp.net生成透明gif的准完美方案                pal.Entries(i) = color.Transparent 
13asp.net生成透明gif的准完美方案            End If
14asp.net生成透明gif的准完美方案        Next
15asp.net生成透明gif的准完美方案
16asp.net生成透明gif的准完美方案        '***另外创建一个位图,格式为8位索引色**
17asp.net生成透明gif的准完美方案        Dim gif2 As New Bitmap(gif.Width, gif.Height, Imaging.PixelFormat.Format8bppIndexed)
18asp.net生成透明gif的准完美方案        '***设置修改后的调色板***
19asp.net生成透明gif的准完美方案        gif2.Palette = pal
20asp.net生成透明gif的准完美方案        '***拷贝内存
21asp.net生成透明gif的准完美方案
22asp.net生成透明gif的准完美方案        Dim src = gif.LockBits(New Rectangle(00, gif.Width, gif.Height), Imaging.ImageLockMode.ReadOnly, gif.PixelFormat)
23asp.net生成透明gif的准完美方案        Dim trg = gif2.LockBits(New Rectangle(00, gif2.Width, gif2.Height), Imaging.ImageLockMode.WriteOnly, gif2.PixelFormat)
24asp.net生成透明gif的准完美方案
25asp.net生成透明gif的准完美方案        Dim bits(src.Stride * src.Height - 1As Byte
26asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(src.Scan0, bits, 0, bits.Length)
27asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(bits, 0, trg.Scan0, bits.Length)
28asp.net生成透明gif的准完美方案
29asp.net生成透明gif的准完美方案        gif.UnlockBits(src)
30asp.net生成透明gif的准完美方案        gif2.UnlockBits(trg)
31asp.net生成透明gif的准完美方案
32asp.net生成透明gif的准完美方案
33asp.net生成透明gif的准完美方案        '***这时再保存,看看吧!***
34asp.net生成透明gif的准完美方案        gif2.Save("out3.gif")
35asp.net生成透明gif的准完美方案
36asp.net生成透明gif的准完美方案        Me.PictureBox2.ImageLocation = "out3.gif"
37asp.net生成透明gif的准完美方案

这时,我们保存了一个透明背景的gif图像!这个out3.gif,是背景透明的!

不过,如果你这时候认为大功告成的话,那可就错了,嘿嘿,这事情就是这么麻烦,请看:

 

 1asp.net生成透明gif的准完美方案'***我们读取上一步生成的不透明gif
 2asp.net生成透明gif的准完美方案        Dim gif As New Bitmap("out1.gif")
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '***获取色板***
 6asp.net生成透明gif的准完美方案        Dim pal = gif.Palette
 7asp.net生成透明gif的准完美方案
 8asp.net生成透明gif的准完美方案        For i As Integer = 0 To pal.Entries.Length - 1
 9asp.net生成透明gif的准完美方案            Dim color = pal.Entries(i)
10asp.net生成透明gif的准完美方案            '***将黑色改为透明***
11asp.net生成透明gif的准完美方案            If color.R = 0 And color.G = 0 And color.B = 0 Then
12asp.net生成透明gif的准完美方案                pal.Entries(i) = color.Transparent
13asp.net生成透明gif的准完美方案            End If
14asp.net生成透明gif的准完美方案        Next
15asp.net生成透明gif的准完美方案
16asp.net生成透明gif的准完美方案        '***另外创建一个位图,格式为8位索引色**
17asp.net生成透明gif的准完美方案        Dim gif2 As New Bitmap(gif.Width, gif.Height, Imaging.PixelFormat.Format8bppIndexed)
18asp.net生成透明gif的准完美方案        '***设置修改后的调色板***
19asp.net生成透明gif的准完美方案        gif2.Palette = pal
20asp.net生成透明gif的准完美方案        '***拷贝内存
21asp.net生成透明gif的准完美方案
22asp.net生成透明gif的准完美方案        Dim src = gif.LockBits(New Rectangle(00, gif.Width, gif.Height), Imaging.ImageLockMode.ReadOnly, gif.PixelFormat)
23asp.net生成透明gif的准完美方案        Dim trg = gif2.LockBits(New Rectangle(00, gif2.Width, gif2.Height), Imaging.ImageLockMode.WriteOnly, gif2.PixelFormat)
24asp.net生成透明gif的准完美方案
25asp.net生成透明gif的准完美方案        Dim bits(src.Stride * src.Height - 1As Byte
26asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(src.Scan0, bits, 0, bits.Length)
27asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(bits, 0, trg.Scan0, bits.Length)
28asp.net生成透明gif的准完美方案
29asp.net生成透明gif的准完美方案        gif.UnlockBits(src)
30asp.net生成透明gif的准完美方案        gif2.UnlockBits(trg)
31asp.net生成透明gif的准完美方案
32asp.net生成透明gif的准完美方案
33asp.net生成透明gif的准完美方案        '***OK,这时候,我把它保存到流里***
34asp.net生成透明gif的准完美方案        Dim ms As New System.IO.MemoryStream()
35asp.net生成透明gif的准完美方案        gif2.Save(ms, Imaging.ImageFormat.Gif)
36asp.net生成透明gif的准完美方案
37asp.net生成透明gif的准完美方案        gif2.Dispose()
38asp.net生成透明gif的准完美方案
39asp.net生成透明gif的准完美方案        Dim gif3 As Bitmap = Bitmap.FromStream(ms)
40asp.net生成透明gif的准完美方案        ms.Dispose()
41asp.net生成透明gif的准完美方案
42asp.net生成透明gif的准完美方案        Me.PictureBox2.Image = gif3
43asp.net生成透明gif的准完美方案
44asp.net生成透明gif的准完美方案        '这时候你看到了,透明色又顽固地被去掉了,只是原来是黑色,现在成了白色
45asp.net生成透明gif的准完美方案

 透明色又消失了,只是这次变成了白色-_____________________-

asp.net生成透明gif的准完美方案

那么为啥保存为文件就可以,而保存到流却不行呢?

事情到了这一步,只好祭出Reflector了,看看M$到底是怎么保存的,实在不行我把保存为文件的代码拷贝一份出来再往流里写

按照Reflector的说法,M$在保存文件时,使用的是RawFormat:

1asp.net生成透明gif的准完美方案public void Save(string filename)
2}

好吧,那我也传个 RawFormat进去

 1asp.net生成透明gif的准完美方案'***我们读取上一步生成的不透明gif
 2asp.net生成透明gif的准完美方案        Dim gif As New Bitmap("out1.gif")
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '***获取色板***
 6asp.net生成透明gif的准完美方案        Dim pal = gif.Palette
 7asp.net生成透明gif的准完美方案
 8asp.net生成透明gif的准完美方案        For i As Integer = 0 To pal.Entries.Length - 1
 9asp.net生成透明gif的准完美方案            Dim color = pal.Entries(i)
10asp.net生成透明gif的准完美方案            '***将黑色改为透明***
11asp.net生成透明gif的准完美方案            If color.R = 0 And color.G = 0 And color.B = 0 Then
12asp.net生成透明gif的准完美方案                pal.Entries(i) = color.Transparent
13asp.net生成透明gif的准完美方案            End If
14asp.net生成透明gif的准完美方案        Next
15asp.net生成透明gif的准完美方案
16asp.net生成透明gif的准完美方案        '***另外创建一个位图,格式为8位索引色**
17asp.net生成透明gif的准完美方案        Dim gif2 As New Bitmap(gif.Width, gif.Height, Imaging.PixelFormat.Format8bppIndexed)
18asp.net生成透明gif的准完美方案        '***设置修改后的调色板***
19asp.net生成透明gif的准完美方案        gif2.Palette = pal
20asp.net生成透明gif的准完美方案        '***拷贝内存
21asp.net生成透明gif的准完美方案
22asp.net生成透明gif的准完美方案        Dim src = gif.LockBits(New Rectangle(00, gif.Width, gif.Height), Imaging.ImageLockMode.ReadOnly, gif.PixelFormat)
23asp.net生成透明gif的准完美方案        Dim trg = gif2.LockBits(New Rectangle(00, gif2.Width, gif2.Height), Imaging.ImageLockMode.WriteOnly, gif2.PixelFormat)
24asp.net生成透明gif的准完美方案
25asp.net生成透明gif的准完美方案        Dim bits(src.Stride * src.Height - 1As Byte
26asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(src.Scan0, bits, 0, bits.Length)
27asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(bits, 0, trg.Scan0, bits.Length)
28asp.net生成透明gif的准完美方案
29asp.net生成透明gif的准完美方案        gif.UnlockBits(src)
30asp.net生成透明gif的准完美方案        gif2.UnlockBits(trg)
31asp.net生成透明gif的准完美方案
32asp.net生成透明gif的准完美方案
33asp.net生成透明gif的准完美方案        '***按照reflector的说法,它使用的是RawFormat***
34asp.net生成透明gif的准完美方案        Dim ms As New System.IO.MemoryStream()
35asp.net生成透明gif的准完美方案        Try
36asp.net生成透明gif的准完美方案            gif2.Save(ms, gif2.RawFormat)
37asp.net生成透明gif的准完美方案        Catch ex As Exception
38asp.net生成透明gif的准完美方案            MsgBox(ex.ToString(), MsgBoxStyle.Critical)
39asp.net生成透明gif的准完美方案        Finally
40asp.net生成透明gif的准完美方案
41asp.net生成透明gif的准完美方案            gif2.Dispose()
42asp.net生成透明gif的准完美方案
43asp.net生成透明gif的准完美方案        End Try
44asp.net生成透明gif的准完美方案
45asp.net生成透明gif的准完美方案

结果如图:这真是太BT了,我受不了了!!!

 asp.net生成透明gif的准完美方案

经过比较发现,M$的两个保存是不一样的,保存为文件时,多了一个判断!保存到文件时,M$会调用png编码器,而保存到流则不会

 1asp.net生成透明gif的准完美方案public void Save(string filename, ImageFormat format)
 2

OK,既然是这样,那么我就在外面调用一下那个传说中的 ImageFormat.Png.FindEncoder();
不就得了吗?你要是这样想那就太天真了:

 1asp.net生成透明gif的准完美方案internal ImageCodecInfo FindEncoder()
 2}

看到了吧,FindEncoder()方法是internal的 -______-,瀑布汗啊瀑布汗

不过还好,天无绝人之路,Save还有一个重载:

public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
我们可以直接传Png的ImageCodecInfo进去,嘿嘿,我们可以把png的ImageCodeInfo给穷举找出来!

1End Function

至此,我们终于制作了一个可以在IE6中拥有透明背景色的"gif"图像,不过实际上,这个其实不是gif格式的,实际上

是8位色png格式的,不过不管怎么说,这个好歹可以在IE6里透明了,而且使用上没有区别。除了不能动画,汗。

最后的实现代码:

 

 1asp.net生成透明gif的准完美方案'***我们读取上一步生成的不透明gif
 2asp.net生成透明gif的准完美方案        Dim gif As New Bitmap("out1.gif")
 3asp.net生成透明gif的准完美方案        PictureBox1.Image = gif
 4asp.net生成透明gif的准完美方案
 5asp.net生成透明gif的准完美方案        '***获取色板***
 6asp.net生成透明gif的准完美方案        Dim pal = gif.Palette
 7asp.net生成透明gif的准完美方案
 8asp.net生成透明gif的准完美方案        For i As Integer = 0 To pal.Entries.Length - 1
 9asp.net生成透明gif的准完美方案            Dim color = pal.Entries(i)
10asp.net生成透明gif的准完美方案            '***将黑色改为透明***
11asp.net生成透明gif的准完美方案            If color.R = 0 And color.G = 0 And color.B = 0 Then
12asp.net生成透明gif的准完美方案                pal.Entries(i) = color.Transparent
13asp.net生成透明gif的准完美方案            End If
14asp.net生成透明gif的准完美方案        Next
15asp.net生成透明gif的准完美方案
16asp.net生成透明gif的准完美方案        '***另外创建一个位图,格式为8位索引色**
17asp.net生成透明gif的准完美方案        Dim gif2 As New Bitmap(gif.Width, gif.Height, Imaging.PixelFormat.Format8bppIndexed)
18asp.net生成透明gif的准完美方案        '***设置修改后的调色板***
19asp.net生成透明gif的准完美方案        gif2.Palette = pal
20asp.net生成透明gif的准完美方案        '***拷贝内存
21asp.net生成透明gif的准完美方案
22asp.net生成透明gif的准完美方案        Dim src = gif.LockBits(New Rectangle(00, gif.Width, gif.Height), Imaging.ImageLockMode.ReadOnly, gif.PixelFormat)
23asp.net生成透明gif的准完美方案        Dim trg = gif2.LockBits(New Rectangle(00, gif2.Width, gif2.Height), Imaging.ImageLockMode.WriteOnly, gif2.PixelFormat)
24asp.net生成透明gif的准完美方案
25asp.net生成透明gif的准完美方案        Dim bits(src.Stride * src.Height - 1As Byte
26asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(src.Scan0, bits, 0, bits.Length)
27asp.net生成透明gif的准完美方案        System.Runtime.InteropServices.Marshal.Copy(bits, 0, trg.Scan0, bits.Length)
28asp.net生成透明gif的准完美方案
29asp.net生成透明gif的准完美方案        gif.UnlockBits(src)
30asp.net生成透明gif的准完美方案        gif2.UnlockBits(trg)
31asp.net生成透明gif的准完美方案
32asp.net生成透明gif的准完美方案
33asp.net生成透明gif的准完美方案
34asp.net生成透明gif的准完美方案        Dim ms As New System.IO.MemoryStream()
35asp.net生成透明gif的准完美方案
36asp.net生成透明gif的准完美方案        gif2.Save(ms, GetEncoderInfo("image/png"), Nothing)
37asp.net生成透明gif的准完美方案        gif2.Dispose()
38asp.net生成透明gif的准完美方案
39asp.net生成透明gif的准完美方案        Dim gif3 = Bitmap.FromStream(ms)
40asp.net生成透明gif的准完美方案
41asp.net生成透明gif的准完美方案        Me.PictureBox2.Image = gif3
42asp.net生成透明gif的准完美方案

最终正确的结果:

asp.net生成透明gif的准完美方案

 代码下载

最后,这就是我开发的山寨WMS生成的透明gif图层+openlayers的效果,哈哈,上次是

谁说最低限度也要supmap,山寨一定是不可能完成的任务来着?这是啥咧,HOHO,纯VB.NET的WMS哦,呵呵

学GIS,还是要自己做东西提高的才快,用商业的东西,又贵,还没啥提高,不就是用人家的组件么.

asp.net生成透明gif的准完美方案

 

 

相关文章:

  • 2021-06-16
  • 2022-02-13
  • 2021-10-08
  • 2022-01-24
  • 2021-12-07
  • 2022-12-23
  • 2022-01-26
猜你喜欢
  • 2021-12-16
  • 2022-12-23
  • 2021-12-04
  • 2021-06-13
  • 2022-03-05
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案