您的位置:首页 > 编程语言 > ASP

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

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

首先呢,我们准备一个PLMM,嘿嘿:Dim gif1 As New Bitmap("plmm.jpg")
2 gif1.MakeTransparent(Color.Yellow)
3 PictureBox1.Image = gif1
4
5 '这里我将它保存为gif到流里,这里是内存流,在asp.net中则是outputstream ,再显示在picturebox2里
6 Dim ms As New System.IO.MemoryStream()
7 gif1.Save(ms, Imaging.ImageFormat.Gif)
8
9 Dim gif2 = Bitmap.FromStream(ms)
10 ms.Dispose()
11
12 PictureBox2.Image = gif2
13
14 '***变黑了****

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

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

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

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

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

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

图像的颜色。

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

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

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

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

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

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

public void Save(string filename, ImageFormat format)
2
15public void Save(Stream stream, ImageFormat format)
16
27
28
29
30
OK,既然是这样,那么我就在外面调用一下那个传说中的 ImageFormat.Png.FindEncoder();
不就得了吗?你要是这样想那就太天真了:

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



代码下载

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

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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: