驗證碼識別最重要的就是對BMP文件進行分析,發(fā)布一個常用的BMP圖形分析類
using System;
using CrazyCoder.Commom.IO;
namespace CrazyCoder.Common.Image
{
/**//// <summary>
/// BMP 的摘要說明。
/// </summary>
public class BMP
{
10
11 public BMP()
12 {
13 //
14 //TODO: 在此處添加構造函數(shù)邏輯
15
16
17 //功能:分析bmp文件格式
18 //本文參考了林福宗老師的有關BMP文件格式的文章
19
20
21 //
22 }
23 /**//*BMP(BitMap-File)圖形文件是Windows采用的圖形文件格式,在Windows環(huán)境
24 * 下運行的所有圖象處理軟件都支持BMP圖象文件格式。Windows系統(tǒng)內(nèi)部各
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以后,在系統(tǒng)中仍
30 * 然存在DDB位圖,象BitBlt()這種函數(shù)就是基于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 * 定義位圖的字節(jié)陣列,
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系統(tǒng)并沒有被普及開,所以在編程時,你只需判斷第一個標識“BM”就行。
55 */
56 public System.Int32 FileSize;//1 dword,用字節(jié)表示的整個文件的大小
57 public byte[] Reserved;//1 dword,保留,必須設置為0
58 public System.Int32 BitMapDataOffset;//1 dword,從文件開始到位圖數(shù)據(jù)開始之間的數(shù)據(jù)(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等操作系統(tǒng)中,位圖信息頭的長度并不一定是28h,因為微軟已經(jīng)制定出了新的BMP文件格式,其中的信息頭結構變化 比較大,長度加長。所以最好不要直接使用常數(shù)28h,而是應該從具體的文件中讀取這個值。這樣才能確保程序的兼容性。
65 */
66 public System.Int32 Width;//1 dword,位圖的寬度,以象素為單位
67 public System.Int32 Height;//1 dword,位圖的高度,以象素為單位
68 public System.Int16 Planes;//1 word,位圖的位面數(shù)(注:該值將總是1)
69 public System.Int16 BitsPerPixel;
70 /**//*1 word
71 每個象素的位數(shù)
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,用字節(jié)數(shù)表示的位圖數(shù)據(jù)的大小。該數(shù)必須是4的倍數(shù)
88 public System.Int32 HResolution;//1 dword,用象素/米表示的水平分辨率
89 public System.Int32 VResolution;//1 dword,用象素/米表示的垂直分辨率
90 public System.Int32 Colors;//1 dword,位圖使用的顏色數(shù)。如8-比特/象素表示為100h或者 256.
91 public System.Int32 ImportantColors;
92 /**//*1 dword,指定重要的顏色數(shù)。當該域的值等于顏色數(shù)時(或者等于0時),表示所有顏色都一樣重要
93 */
94 }
95 public struct BMPPalette
96 {
97 public byte[] Palette;//new byte[8192];//bmp規(guī)范沒有規(guī)定調(diào)色板最大81926字節(jié),此處可以根據(jù)程序需要調(diào)節(jié)
98 /**//*調(diào)色板數(shù)據(jù)根據(jù)BMP版本的不同而不同PaletteN * 4 byte調(diào)色板規(guī)范。
99 對于調(diào)色板中的每個表項,這4個字節(jié)用下述方法來描述RGB的值: 1字節(jié)用于藍色分量
100 1字節(jié)用于綠色分量
101 1字節(jié)用于紅色分量
102 1字節(jié)用于填充符(設置為0)
103 */
104 }
105 public struct BMPData
106 {
107 public byte[] BitMapData;//=new byte[1024000];//bmp規(guī)范沒有規(guī)定bmp數(shù)據(jù)最多為1024000,此處可以根據(jù)需要調(diào)整
108 /**//*
109 圖象數(shù)據(jù)根據(jù)BMP版本及調(diào)色板尺寸的不同而不同BitMap Dataxxx bytes該域的大小取決
110 于壓縮方法及圖像的尺寸和圖像的位深度,它包含所有的位圖數(shù)據(jù)字節(jié),這些數(shù)據(jù)可能是
111 彩色調(diào)色板的索引號,也可能是實際的RGB值,這將根據(jù)圖像信息頭中的位深度值來決定。
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 //計算位圖數(shù)據(jù)的開始位置
196 //sbmp.Header.BitMapDataSize是位圖數(shù)據(jù)的大小,sbmp.Header.FileSize是整個文件的大小
197 //sbmp.Header.FileSize-sbmp.Header.BitMapDataSize-1就是位圖數(shù)據(jù)的開始位置
198 //0x36到sbmp.Header.FileSize-sbmp.Header.BitMapDataSize-2就是調(diào)色板數(shù)據(jù)
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 //先讀取文件成字節(jié)數(shù)組,統(tǒng)一由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}
聯(lián)系客服