返回列表 回复 发帖

[转]用XBM创建动态客户端图像

  作者: BUILDER.COM
  Wednesday, April 9 2003 11:23 AM
  X-Bitmap(XBM)是一种古老但通用的图像文件格式,它与现在的许多Web浏览器都兼容。X-Windows图形界面(UNIX和Linux常用的GUI)的C代码库xlib中有一个组件专门描述了它的规范。我将解释XBM格式的工作原理,然后向你展示一种更有趣的使用它的方法:在客户端创建动态图像。文章中的代码可以在此下载。
   
  XBM基础
   
  XBM格式本来是为存储单色的系统位图而设计的,比如图标和鼠标指针。XBM图形的实质上是使用16进制数组来表示二进制图像的C源代码文件。(16进制数组表示的二进制图像)
   
  这里你也许会问:这种文件格式与Web浏览器有什么关系?在上世纪九十年代早期,美国超级计算应用中心(NCSA)在伊利诺斯大学开发第一个被广泛使用的Web浏览器,名为Mosaic。这个浏览器的图形支持来自很多开放源码代码库,其中就包括xlib。因此,导致今天的许多浏览器能够处理XBM图形。
   
  Mosaic项目后来成为了Netscape浏览器的开发基础。微软也借用了一部分Mosaic代码来创建Internet Explorer。微软继而在网络信息服务器(IIS)中将XBM作为一个MIME类型注册而提供本地支持,并且在现有所有版本的Internet Explorer中将其作为一种可支持的图像。(浏览器的广泛支持)
   
  从一个程序员的角度来看,JPEG或GIF与XBM有着极大的不同。这两种文件格式都在位级别上操作并使用了压缩算法。它们可以支持很大的颜色深度范围。创建这些动态Web图形的唯一方法是使用服务器端的脚本,比如<a href=http://stein.cshl.org/WWW/software/GD/GD.pm和CGI/Perl脚本的结合,或者通过System.Drawing名字空间访问ASP.NET中的图形设计接口类库(GDI+)。(升级到ASP.NET有很多个理由。)
   
  XBM创建起来很有程序性。每个位都被一一指定,而结果图形被限制为两色(黑色和白色)。(局限性之一:让人不爽)X-Bitmap并不是必须服务器端脚本,可以在客户端用JavaScript实时创建它们。(增加了不少灵活性)
   
  X-Bitmap的实用程序包括动态生成的图、页面计数器、老式图形图标、以及统计图表。(就是通过位控制太麻烦了,有良好的包装就好了。另外:生成图片的大小,算法的强度,是否都达到了可用的要求?)给我印象最深的XMB应用是一个叫Wolfenstein 5k的游戏,它是一个纹理映射的第一视角射击游戏,用JavaScript编写,只有5KB大小。(不错啊,稍后爽一下)
通过使用IMG标识可以很容易地将XBM文件嵌入到一个Web页面中。其语法如下:
   
  <img src=”xbmsmill.xbm”>
   
  ----------------------------------------------------------------------
  注意
   
  这种格式不对Mac或相应的浏览器有效,比如Mozilla的早期版本。
   
   
  ----------------------------------------------------------------------
  典型的XBM源代码与列表A中显示的比较相像。
   
  &#35;define语句以像素点为单位设置了图像的宽度和高度。你也可以使用x_hot和y_hot命令来定义图像中的一个热点。我已经创建了一个X-Bitmap来描绘这个过程。为了设计它,我先将图像映射为二进制值,如果你仔细的看,在这里你会看到一张笑脸。
   
  我所创建的二进制图像宽16个数字高7个数字,在我们的源代码的XBM头中定义了相同大小的宽/高像素值。图像本身被存储在一个静态数组中,它包含一列二进制编码的十六进制(BCH)值——换句话说,每四位分成一组。
   
  计算出笑脸的十六进制值得最简单的方法是一次检验图像的一行,将二进制值分成四位一组的分段,将每个分段映射成二进制/十六进制表中对应的十六进制数。下面是第一行:
   
  0001100001100000
   
  下面两行分别表示四位的分段和其在表A中对应的十六进制数
   
  二进制: 0001  1000  0110  0000
   
  十六进制:  8   1   6   0
   
  表A
   
  XBM二/十六进制转换表
   
  二进制 十六进制
   
  0000 0
   
  1000 1
   
  0100 2
   
  1100 3
   
  0010 4
   
  1010 5
   
  0110 6
   
  1110 7
   
  0001 8
   
  1001 9
   
  0101 A
   
  1101 B
   
  0011 C
   
  1011 D
   
  0111 E
   
  1111 F
   
   
  请注意这些并不是标准的二/十六进制转换。它们是反向计算的(从左到右)而不是从右到左。把它颠倒是因为浏览器会从左到右来读图形,我们的代码必须与其一致。
   
  最后要把这些十六进制值转换成XBM的右格式。必须在每个十六进制值前加“0x”。这是标准C++表示十六进制的方法。然后将这些值从右到左输出(每个十六进制对表示八位二进制位)。请看列表B中的例子。
   
  因此,我们可以说:
   
  0001100001100000=0x18,0x06
   
  这些符合XBM的值可以很容易地插入到图像数组中:
   
  static unsigned char xbmsmile_bits[]=
   
  现在我们来看看格式本身,现在是时候来学习在客户端浏览器中动态创建X-Bitmap了。
图片用点阵的形式表示,比如2:
   
  00111100 0011为3 1100为C 即0x3c
  01100110 0110为6 0110为6 0x66
  01100000 ....... 0x表示十六进制数。
  01100000 依此类推
  00110000 这是用二进制数得到的点阵,其中的1为显示一黑点,0不显示
  00011000 是一个反着看的2
  00001100 其余数字可自已排列点阵再二进制化为十六进制数
  00000110 缺点是只有黑白两种颜色
  00000110 显示出来是白底黑字,要显示黑底白字的话,对其取反就行了
  01111110
   
  下面是我"画"的0-9的数字
   
  num.asp
   
  <%
  Dim a(10,10)
   
  a(0,1) = "0x3c" ';数字0
  a(0,2) = "0x66"
  a(0,3) = "0xc3"
  a(0,4) = "0xc3"
  a(0,5) = "0xc3"
  a(0,6) = "0xc3"
  a(0,7) = "0xc3"
  a(0,8) = "0xc3"
  a(0,9) = "0x66"
  a(0,10)= "0x3c"
   
  a(1,1) = "0x18" ';数字1
  a(1,2) = "0x1c"
  a(1,3) = "0x18"
  a(1,4) = "0x18"
  a(1,5) = "0x18"
  a(1,6) = "0x18"
  a(1,7) = "0x18"
  a(1,8) = "0x18"
  a(1,9) = "0x18"
  a(0,10)= "0x7e"
   
   
  a(2,1) = "0x3c" ';数字2
  a(2,2) = "0x66"
  a(2,3) = "0x60"
  a(2,4) = "0x60"
  a(2,5) = "0x30"
  a(2,6) = "0x18"
  a(2,7) = "0x0c"
  a(2,8) = "0x06"
  a(2,9) = "0x06"
  a(2,10)= "0x7e"
   
  a(3,1) = "0x3c" ';数字3
  a(3,2) = "0x66"
  a(3,3) = "0xc0"
  a(3,4) = "0x60"
  a(3,5) = "0x1c"
  a(3,6) = "0x60"
  a(3,7) = "0xc0"
  a(3,8) = "0xc0"
  a(3,9) = "0x66"
  a(3,10)= "0x38"
   
  a(4,1) = "0x38" ';数字4
  a(4,2) = "0x3c"
  a(4,3) = "0x36"
  a(4,4) = "0x33"
  a(4,5) = "0x33"
  a(4,6) = "0x33"
  a(4,7) = "0xff"
  a(4,8) = "0x30"
  a(4,9) = "0x30"
  a(4,10)= "0xfe"
   
  a(5,1) = "0xfe" ';数字5
  a(5,2) = "0xfe"
  a(5,3) = "0x06"
  a(5,4) = "0x06"
  a(5,5) = "0x3e"
  a(5,6) = "0x60"
  a(5,7) = "0xc0"
  a(5,8) = "0xc3"
  a(5,9) = "0x66"
  a(5,10)= "0x3c"
   
  a(6,1) = "0x60" ';数字6
  a(6,2) = "0x30"
  a(6,3) = "0x18"
  a(6,4) = "0x0c"
  a(6,5) = "0x3e"
  a(6,6) = "0x63"
  a(6,7) = "0xc3"
  a(6,8) = "0xc3"
  a(6,9) = "0x66"
  a(6,10) ="0x3c"
   
  a(7,1) = "0xff" ';数字7
  a(7,2) = "0xc0"
  a(7,3) = "0x60"
  a(7,4) = "0x30"
  a(7,5) = "0x18"
  a(7,6) = "0x18"
  a(7,7) = "0x18"
  a(7,8) = "0x18"
  a(7,9) = "0x18"
  a(7,10)= "0x18"
   
  a(8,1) = "0x3c" ';数字8
  a(8,2) = "0x66"
  a(8,3) = "0xc3"
  a(8,4) = "0x66"
  a(8,5) = "0x3c"
  a(8,6) = "0x66"
  a(8,7) = "0xc3"
  a(8,8) = "0xc3"
  a(8,9) = "0x66"
  a(8,10)= "0x3c"
   
  a(9,1) = "0x3c" ';数字9
  a(9,2) = "0x66"
  a(9,3) = "0xc3"
  a(9,4) = "0xc3"
  a(9,5) = "0x66"
  a(9,6) = "0x3c"
  a(9,7) = "0x18"
  a(9,8) = "0x0c"
  a(9,9) = "0x06"
  a(9,10)= "0x03"
   
  %>
   
  显示的方法是:
   
  1.先传出一个MIME:
  Response.ContentType = "image/x-xbitmap"
  2.再传出一个c++的源程序,如显示2:
  &#35;define counter_width 8
  &#35;define counter_height 10
  static unsigned char counter_bits[] = {
  0x3c,0x66,0x60,0x60,0x30,0x18,0x0c,0x06,0x06,0x7e
  };
  这样在浏览器上就显示出来一个8*10像素的2了
   
  要显示两个或以上的数字的时候,须改动宽度的值(必须是图像点阵宽度的整数倍),在count_bits[]数组的值排序如下:
  比如显示 12
  a(1,1), a(2,1), a(1,2), a(2,2)... a(1,10), a(2,10)
  下面是具体计数器的例子:
   
  count.asp
   
  <!--&#35;include file="num.asp"-->
  <%
  Dim Image
  Dim Width, Height
  Dim num
  Dim digtal
  Dim Length
  Dim sort
  Length = 10 ';自定计数器长度
   
  Redim sort( Length )
   
   
  num = 62275 ';计数器的值
  digital = ""
  For I = 1 To Length -Len( num ) ';补0
  digital = digital & "0"
  Next
  For I = 1 To Len( num )
  digital = digital & Mid( num, I, 1 )
  Next
  For I = 1 To Len( digital )
  sort(I) = Mid( digital, I, 1 )
  Next
  Width = 8 * Len( digital ) ';图像的宽度
  Height = 10 ';图像的高度,在本例中为固定值
   
   
  Response.ContentType="image/x-xbitmap"
   
  hc=chr(13) & chr(10)
   
  Image = "&#35;define counter_width " & Width & hc
  Image = Image & "&#35;define counter_height " & Height & hc
  Image = Image & "static unsigned char counter_bits[]={" & hc
   
  For I = 1 To Height
  For J = 1 To Length
  Image = Image & a(sort(J),I) & ","
  Next
  Next
   
  Image = Left( Image, Len( Image ) - 1 ) ';去掉最后一个逗号
  Image = Image & "};" & hc
   
  Response.Write Image
   
  %>

  &#35;define counter_width 8
  &#35;define counter_height 10
  static unsigned char counter_bits[] = {
    0x3c,0x66,0x60,0x60,0x30,0x18,0x0c,0x06,0x06,0x7e
    };
  保存为 xbm 文件就可以得到一张显示为 2 的图片
   
   
  &#35;define counter_width 80
  &#35;define counter_height 10
  static unsigned char counter_bits[]={
  0x3c,0x3c,0x3c,0x3c,0x3c,0x60,0x3c,0x3c,0xff,0xfe,0x66,0x66,0x66,0x66,0x66,0x30,0x66,0x66,0xc0,0xfe,0xc3,0xc3,0xc3,0xc3,0xc3,0x18,0x60,0x60,0x60,0x06,0xc3,0xc3,0xc3,0xc3,0xc3,0x0c,0x60,0x60,0x30,0x06,0xc3,0xc3,0xc3,0xc3,0xc3,0x3e,0x30,0x30,0x18,0x3e,0xc3,0xc3,0xc3,0xc3,0xc3,0x63,0x18,0x18,0x18,0x60,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x0c,0x0c,0x18,0xc0,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x06,0x06,0x18,0xc3,0x66,0x66,0x66,0x66,0x66,0x66,0x06,0x06,0x18,0x66,0x7e,0x7e,0x7e,0x7e,0x7e,0x3c,0x7e,0x7e,0x18,0x3c};
  保存为 xbm文件则显示为 0000062275 。
返回列表