验证码识别最重要的就是对BMP文件进行分析,发布一个常用的BMP图形分析类
using System; 2using CrazyCoder.Commom.IO; 3namespace CrazyCoder.Common.Image 4{ 5 /**//// <summary> 6 /// BMP 的摘要说明。 7 /// </summary> 8 public class BMP 9 { 10 11 public BMP() 12 { 13 // 14 //TODO: 在此处添加构造函数逻辑 15 16 17 //功能:分析bmp文件格式 18 //本文参考了林福宗老师的有关BMP文件格式的文章 19 20 21 // 22 } 23 /**//*BMP(BitMap-File)图形文件是Windows采用的图形文件格式,在Windows环境 24 * 下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各 25 * 图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与 26 * 显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB 27 * (device-dependent BitMap)文件格式。Windows 3.0以后的BMP图象文件与 28 * 显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB 29 * (device-independent BitMap)格式(注:Windows 3.0以后,在系统中仍 30 * 然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将 31 * 图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的 32 * 是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件 33 * 默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。 34 * */ 35 public struct StructBMP 36 { 37 public BMPHeader Header; 38 public BMPPalette Palette; 39 public BMPData Data; 40 } 41 public struct BMPHeader 42 { 43 /**//*位图文件可看成由4个部分组成:位图文件头(BitMap-file header)、 44 * 位图信息头(BitMap-information header)、彩色表(color table)和 45 * 定义位图的字节阵列, 46 * */ 47 public string Identifier;/**//*2 bytes,识别位图的类型: 48 ‘BM’ : Windows 3.1x, 95, NT, … 49 ‘BA’ :OS/2 BitMap Array 50 ‘CI’ :OS/2 Color Icon 51 ‘CP’ :OS/2 Color Pointer 52 ‘IC’ : OS/2 Icon 53 ‘PT’ :OS/2 Pointer 54 注:因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行。 55 */ 56 public System.Int32 FileSize;//1 dword,用字节表示的整个文件的大小 57 public byte[] Reserved;//1 dword,保留,必须设置为0 58 public System.Int32 BitMapDataOffset;//1 dword,从文件开始到位图数据开始之间的数据(BitMap data)之间的偏移量 59 public System.Int32 BitMapHeaderSize;/**//*1 dword 60 位图信息头(BitMap Info Header)的长度,用来描述位图的颜色、压缩方法等。下面的长度表示: 61 28h - windows 3.1x, 95, nt, … 62 0ch - os/2 1.x 63 f0h - os/2 2.x 64 注: 在Windows95、98、2000等操作系统中,位图信息头的长度并不一定是28h,因为微软已经制定出了新的BMP文件格式,其中的信息头结构变化 比较大,长度加长。所以最好不要直接使用常数28h,而是应该从具体的文件中读取这个值。这样才能确保程序的兼容性。 65 */ 66 public System.Int32 Width;//1 dword,位图的宽度,以象素为单位 67 public System.Int32 Height;//1 dword,位图的高度,以象素为单位 68 public System.Int16 Planes;//1 word,位图的位面数(注:该值将总是1) 69 public System.Int16 BitsPerPixel; 70 /**//*1 word 71 每个象素的位数 72 1 - 单色位图(实际上可有两种颜色,缺省情况下是黑色和白色。你可以自己定义这两种颜色) 73 4 - 16 色位图 74 8 - 256 色位图 75 16 - 16bit 高彩色位图 76 24 - 24bit 真彩色位图 77 32 - 32bit 增强型真彩色位图 78 */ 79 public System.Int32 Compression; 80 /**//*1 dword 81 压缩说明: 82 0 - 不压缩 (使用BI_RGB表示) 83 1 - RLE 8-使用8位RLE压缩方式(用BI_RLE8表示) 84 2 - RLE 4-使用4位RLE压缩方式(用BI_RLE4表示) 85 3 - Bitfields-位域存放方式(用BI_BITFIELDS表示) 86 */ 87 public System.Int32 BitMapDataSize;//1 dword,用字节数表示的位图数据的大小。该数必须是4的倍数 88 public System.Int32 HResolution;//1 dword,用象素/米表示的水平分辨率 89 public System.Int32 VResolution;//1 dword,用象素/米表示的垂直分辨率 90 public System.Int32 Colors;//1 dword,位图使用的颜色数。如8-比特/象素表示为100h或者 256. 91 public System.Int32 ImportantColors; 92 /**//*1 dword,指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要 93 */ 94 } 95 public struct BMPPalette 96 { 97 public byte[] Palette;//new byte[8192];//bmp规范没有规定调色板最大81926字节,此处可以根据程序需要调节 98 /**//*调色板数据根据BMP版本的不同而不同PaletteN * 4 byte调色板规范。 99 对于调色板中的每个表项,这4个字节用下述方法来描述RGB的值: 1字节用于蓝色分量 100 1字节用于绿色分量 101 1字节用于红色分量 102 1字节用于填充符(设置为0) 103 */ 104 } 105 public struct BMPData 106 { 107 public byte[] BitMapData;//=new byte[1024000];//bmp规范没有规定bmp数据最多为1024000,此处可以根据需要调整 108 /**//* 109 图象数据根据BMP版本及调色板尺寸的不同而不同BitMap Dataxxx bytes该域的大小取决 110 于压缩方法及图像的尺寸和图像的位深度,它包含所有的位图数据字节,这些数据可能是 111 彩色调色板的索引号,也可能是实际的RGB值,这将根据图像信息头中的位深度值来决定。 112 */ 113 } 114 public void ProcessBMP(ref StructBMP sbmp,byte[] bytesFile) 115 { 116 byte[] word1=new byte[2]; 117 byte[] word2=new byte[4]; 118 System.Int32 result; 119 string str=""; 120 word1[0]=bytesFile[0]; 121 word1[1]=bytesFile[1]; 122 str=FromBytesToString(word1); 123 sbmp.Header.Identifier=str; 124 word2[0]=bytesFile[2]; 125 word2[1]=bytesFile[3]; 126 word2[2]=bytesFile[4]; 127 word2[3]=bytesFile[5]; 128 result=this.FromBytesToInt32(word2); 129 sbmp.Header.FileSize=result; 130 word2[0]=bytesFile[10]; 131 word2[1]=bytesFile[11]; 132 word2[2]=bytesFile[12]; 133 word2[3]=bytesFile[13]; 134 result=this.FromBytesToInt32(word2); 135 sbmp.Header.BitMapDataOffset=result; 136 word2[0]=bytesFile[14]; 137 word2[1]=bytesFile[15]; 138 word2[2]=bytesFile[16]; 139 word2[3]=bytesFile[17]; 140 result=this.FromBytesToInt32(word2); 141 sbmp.Header.BitMapHeaderSize=result; 142 word2[0]=bytesFile[18]; 143 word2[1]=bytesFile[19]; 144 word2[2]=bytesFile[20]; 145 word2[3]=bytesFile[21]; 146 sbmp.Header.Width=result; 147 word2[0]=bytesFile[22]; 148 word2[1]=bytesFile[23]; 149 word2[2]=bytesFile[24]; 150 word2[3]=bytesFile[25]; 151 result=this.FromBytesToInt32(word2); 152 sbmp.Header.Height =result; 153 word1[0]=bytesFile[26]; 154 word1[1]=bytesFile[27]; 155 sbmp.Header.Planes=(System.Int16)FromBytesToInt32(word1); 156 word1[0]=bytesFile[28]; 157 word1[1]=bytesFile[29]; 158 sbmp.Header.BitsPerPixel=(System.Int16)FromBytesToInt32(word1); 159 word2[0]=bytesFile[30]; 160 word2[1]=bytesFile[31]; 161 word2[2]=bytesFile[32]; 162 word2[3]=bytesFile[33]; 163 result=this.FromBytesToInt32(word2); 164 sbmp.Header.Compression =result; 165 word2[0]=bytesFile[34]; 166 word2[1]=bytesFile[35]; 167 word2[2]=bytesFile[36]; 168 word2[3]=bytesFile[37]; 169 result=this.FromBytesToInt32(word2); 170 sbmp.Header.BitMapDataSize =result; 171 word2[0]=bytesFile[38]; 172 word2[1]=bytesFile[39]; 173 word2[2]=bytesFile[40]; 174 word2[3]=bytesFile[41]; 175 result=this.FromBytesToInt32(word2); 176 sbmp.Header.HResolution =result; 177 word2[0]=bytesFile[42]; 178 word2[1]=bytesFile[43]; 179 word2[2]=bytesFile[44]; 180 word2[3]=bytesFile[45]; 181 result=this.FromBytesToInt32(word2); 182 sbmp.Header.VResolution =result; 183 word2[0]=bytesFile[46]; 184 word2[1]=bytesFile[47]; 185 word2[2]=bytesFile[48]; 186 word2[3]=bytesFile[49]; 187 result=this.FromBytesToInt32(word2); 188 sbmp.Header.Colors =result; 189 word2[0]=bytesFile[50]; 190 word2[1]=bytesFile[51]; 191 word2[2]=bytesFile[52]; 192 word2[3]=bytesFile[53]; 193 result=this.FromBytesToInt32(word2); 194 sbmp.Header.ImportantColors =result; 195 //计算位图数据的开始位置 196 //sbmp.Header.BitMapDataSize是位图数据的大小,sbmp.Header.FileSize是整个文件的大小 197 //sbmp.Header.FileSize-sbmp.Header.BitMapDataSize-1就是位图数据的开始位置 198 //0x36到sbmp.Header.FileSize-sbmp.Header.BitMapDataSize-2就是调色板数据 199 result=sbmp.Header.FileSize-sbmp.Header.BitMapDataSize; 200 int j=0; 201 byte[] b=new byte[sbmp.Header.BitMapDataSize]; 202 for(int i=result;i<sbmp.Header.FileSize;i++) 203 { 204 b[j]=bytesFile[i];j++; 205 } 206 sbmp.Data.BitMapData=b; 207 j=0; 208 b=new byte[result-sbmp.Header.BitMapDataOffset]; 209 for(int i=sbmp.Header.BitMapDataOffset;i<result;i++) 210 { 211 b[j]=bytesFile[i];j++; 212 } 213 sbmp.Palette.Palette=b; 214 } 215 public void ProcessBMP(ref StructBMP sbmp,string File) 216 { 217 //先读取文件成字节数组,统一由ProcessBMP(StructBMP sbmp,byte[] bytesFile)处理 218 JJBase.FILE.ReadAndWrite f=new ReadAndWrite(); 219 byte[] result=f.ReadBytesFromFile(File); 220 ProcessBMP(ref sbmp,result); 221 } 222 private System.Int32 FromBytesToInt32(byte[] b) 223 { 224 System.Int32 result=0; 225 System.Int32 t=0; 226 for(int i=b.Length-1;i>=0;i--) 227 { 228 229 if((int)b[i]!=0) 230 { 231 t=(int)Math.Pow(256,i); 232 result+=(int)b[i]*t; 233 } 234 235 } 236 return result; 237 } 238 private string FromBytesToString(byte[] b) 239 { 240 string result=""; 241 for(int i=0;i<b.Length;i++) 242 { 243 result+=Convert.ToChar((int)(b[i])).ToString(); 244 } 245 return result; 246 } 247 248 } 249}