验证码识别必备,c#分析bmp图形文件,一个有用的BMP图形分析类收藏

以前帮朋友写的代码,现在公布出来,道理很简单的,切割,提取验证码,因为验证码字体并未重合,所以切割起来相当的简单,如果您要做分类信息的网站,采集还是可取的,识别率100%

疯狂代码原创发布,转载请注明出处

C#代码如下:

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