科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件256色BMP图片验证码识别脚本

256色BMP图片验证码识别脚本

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文提供256色BMP图片验证码识别脚本代码片段,可以是大家了解到:BMP的文件结构,存储方式和对于简单的图像验证码如何进行识别处理。

作者:walkerlee 来源:51cto.com整理 2007年9月15日

关键字: 软件

  • 评论
  • 分享微博
  • 分享邮件
NEATBMP256ValidPic.class.php
<?php

/*

* 本代码思路基于 NetDust <oy_@163.net> 的文章 “程序识别验证码图片” .

* 由NEATSTUDIO ( http://www.neatstudio.com ) 的 walkerlee <walker@neatstudio.com>用PHP重新描述, 并改进成半通用版本.

* 本代码片段遵循GPL许可协议发布. 您可以任意修改和传播本代码片段,但请保留我们的版权信息.

*/

/**

* 256色BMP图片校验码识别类

* Created / Modify : 2005-8-21 / 2005-8-22

* @name  NEATBMP256ValidPic

* @version  1.0.0

* @author  walkerlee <walker@neatstudio.com>

* @copyright  Powered by NEATSTUDIO 2002 - 2005 <neatstudio@qq.com>

* @link http://www.neatstudio.com NeatStudio

* @package NEATFramework

* @subpackage NEATImage

*/

/**

* TODO :

* 异常处理,比如,在处理前先判断图片是否是BMP格式。并且是256色。

*/

class NEATBMP256ValidPic

{

     

      /**

      * 待处理文件的绝对或者相对路径

      * @var string

      * @access private

      */

      var $bmpFile = '';

      /**

      * 前景色

      * @var string

      * @access private

      */

      var $frontColor = '#3399CC';

      /**

      * 背景色

      * @var string

      * @access private

      */

      var $backColor = '#FFFFFF';

      /**

      * 验证码颜色

      * @var integer

      * @access private

      */

      var $codeColor = '';

      /**

      * 表格绘图模式

      * @var string

      * @access private

      */

      var $drawMod = '';

      /**

      * 字体宽度

      * @var integer

      * @access private

      */

      var $fontWeight = '';

      /**

      * 字体高度

      * @var integer

      * @access private

      */

      var $fontHeight = '';

      /**

      * 字间距离

      * @var integer

      * @access private

      */

      var $fontSpace = '';

      /**

      * 待识别验证码字符个数

      * @var integer

      * @access private

      */

      var $codeTotal = '';

      /**

      * 第一个数字的左上角的数据偏移

      * @var integer

      * @access private

      */

      var $offSet = '';

      /**

      * 对比码数组

      * @var array

      * @access private

      */

      var $collateCode = array();

      //////////////////////////////////////////////////////////////////////////////

      /**

      * 图片信息数组

      * @var array

      * @access private

      */

      var $imageInfo = array();

      /**

      * 原始图像数据数组

      * @var array

      * @access private

      */

      var $buffer = array();

      /**

      * 图片数据数组

      * @var array

      * @access private

      */

      var $imgData = array();

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // communications function

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

     

      /**

      * 设置待处理的文件

      * @param string $file 文件绝对或者相对路径

      * @access public

      */

      function SetFile( $file )

      {

              $this->bmpFile = $file;

      }

      /**

      * 设置前景色

      * @param string $color 前景色 用于在表格上显示 16位格式 例:#FF0000

      * @access public

      */

      function SetFrontColor( $color )

      {

              $this->frontColor = $color;

      }

      /**

      * 设置背景色

      * @param string $color 背景色 用于在表格上显示 16位格式 例:#FF0000

      * @access public

      */

      function SetBackColor( $color )

      {

              $this->backColor = $color;

      }

     

      /**

      * 设置验证码颜色

      * @param string $color 验证码颜色 验证码的着色 范围在0-255

      * @access public

      */

      function SetCodeColor( $color )

      {

              $this->codeColor = $color;

      }

      /**

      * 设置表格绘图模式

      * @param string $mod 绘图模式 source 是直接显示出当前像素的颜色代码 0-255

      * @access public

      */

      function SetDrawMod( $mod )

      {

              $this->drawMod = $mod;

      }

      /**

      * 设置字体宽度

      * @param integer $weight 字体宽度 以像素为单位

      * @access public

      */

      function SetFontWeight( $weight )

      {

              $this->fontWeight = $weight;

      }

      /**

      * 设置字体高度

      * @param integer $height 字体高度 以像素为单位

      * @access public

      */

      function SetFontHeight( $height )

      {

              $this->fontHeight = $height;

      }

      /**

      * 设置字间距离

      * @param integer $space 字间距离 以像素为单位

      * @access public

      */

      function SetFontSpace( $space )

      {

              $this->fontSpace = $space;

      }

      /**

      * 设置待识别的验证码字符个数

      * @param integer $total 字符个数

      * @access public

      */

      function SetCodeTotal( $total )

      {

              $this->codeTotal = $total;

      }

      /**

      * 设置第一个数字的左上角的数据偏移

      * @param integer $offset 偏移位置

      * @access public

      */

      function SetOffSet( $offset )

      {

              $this->offSet = $offset;

      }

      /**

      * 设置对比码

      * @param array $code 对比码数组

      * @access public

      */

      function SetCollateCode( $code )

      {

              $this->collateCode = $code;

      }

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // common operation function

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      /**

      * 打开文件

      * @return boolean

      * @access public

      */

      function Open()

      {

              return $this->fp = fopen( $this->bmpFile, "rb" );

      }

      /**

      * 关闭文件

      * @return boolean

      * @access public

      */

      function Close()

      {

              return fclose( $this->fp );

      }

      /**

      * 读取配置参数

      * @param array $config 配置参数数组

      * @access public

      */

      function LoadConfig( $config )

      {

              $this->codeColor        = $config['CodeColor'];

              $this->codeTotal        = $config['CodeTotal'        ];

              $this->fontWeight        = $config['FontWeight'];

              $this->fontHeight        = $config['FontHeight'];

              $this->fontSpace        = $config['FontSpace'];

              $this->offSet                        = $config['OffSet'];

              $this->collateCode = $config['CollateCode'];

      }

      /**

      * 返回已经获取的图片信息

      * @return array 图片信息数组

      * @access public

      */

      function GetInfo()

      {

              return $this->imageInfo;

      }

      /**

      * 获取原始的图片内容

      * @return array 原始图片内容数组

      * @access public

      */

      function GetBaseData()

      {               

              // 如果 $this->imageInfo 不存在 : 读取图片信息

              if ( !$this->imageInfo )

                      $this->Info();

             

              // 逐行读取

              for ( $i = $this->imageInfo['Height'] - 1; $i >= 0; $i-- )

              {

                      // 计算出数据偏移

                      $pos = $this->imageInfo['Offset'] + ( $this->imageInfo['Height'] - $i - 1 ) * $this->imageInfo['Weight'];

                     

                      // 移动指针

                      fseek ( $this->fp, $pos );

                      // 计算本行数据偏移

                      $line = $i * $this->imageInfo['Weight'];

                      // 初始化数组

                      $arr = array();

                      // 逐列读取

                      for ( $k = 0; $k < $this->imageInfo['Weight'] ; $k++ )

                      {

                              // 读取当前像素点的颜色数值,保存进本列数组

                              $arr[] = $this->_Bin2asc( fread( $this->fp, 1 ) );

                      }

                      // 构造数组

                      $this->buffer[$line] = $arr;

              }

              return $this->buffer;

      }

      /**

      * 获取图片内容

      * @param string $order 参数:shift 原始存储模式 图片是反着存储的。用于寻找第一个字符的数据偏移 参数:pop 显示模式 用于显示。

      * @return array 图片内容数组

      * @see GetBaseData

      * @access public

      */

      function GetData( $order = 'shift' )

      {

             

              // 如果 $this->buffer 不存在 : 获取图片原始内容

              if ( !$this->buffer )

                      $this->GetBaseData();

              // 判断数据构造模式

              if ( $order == 'shift' )

                      $handleMod = 'array_shift'; // 存储模式 图像倒置

              else

                      $handleMod = 'array_pop'; // 显示模式 图像正置

             

              // 获取原始图片内容数组的行数

              $arrayNum = count( $this->buffer );

              // 逐行处理

              for( $i = 1; $i <= $arrayNum; $i++ )

              {

                      // 重建数组

                      $this->imgData[$i] = $handleMod( $this->buffer );

              }

              return $this->imgData;

      }

/**

      * 取得图片信息

      * @return array 图片信息数组

      * @access public

      */

      function Info()

      {

              // 读取图片格式

              $this->imageInfo['Type'] = fread( $this->fp, 2 );

              // 读取图片尺寸

              $this->imageInfo['Size'] = $this->_ReadInt();

              // 保留地址

              $this->imageInfo['Reserved'] = $this->_ReadInt();

              // 获取数据偏移

              $this->imageInfo['Offset'] = $this->_ReadInt();

              // 获取头信息

              $this->imageInfo['Header'] = dechex( $this->_ReadInt() ) . 'H';

              // 获取图片的宽度

              $this->imageInfo['Weight'] =  $this->_ReadInt();

              // 获取图片的高度

              $this->imageInfo['Height'] =  $this->_ReadInt();

              // 获取图片的位面数

              $this->imageInfo['Planes'] =  $this->_Bin2asc( fread( $this->fp, 2 ) );

              // 获取图片的每个象素的位数

              $this->imageInfo['Bits Per Pixel'] =  $this->_Bin2asc( fread( $this->fp, 2 ) );

              // 获取图片的压缩说明

              $this->imageInfo['Compression'] =  $this->_ReadInt();

              // 用字节数表示的位图数据的大小。该数必须是4的倍数

              $this->imageInfo['Bitmap Data Size'] =  $this->_ReadInt();

              // 用象素/米表示的水平分辨率

              $this->imageInfo['HResolution'] =  $this->_ReadInt();

              // 用象素/米表示的垂直分辨率

              $this->imageInfo['VResolution'] =  $this->_ReadInt();

              // 位图使用的颜色数。如8-比特/象素表示为100h或者 256.

              $this->imageInfo['Colors'] =  $this->_ReadInt();

              // 指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要

              $this->imageInfo['Important Colors'] =  $this->_ReadInt();

      }

      /**

      * 绘出坐标表

      * @access public

      */

      function Draw()

      {

              // 如果 $this->imgData 不存在 : 获取图片内容

              if ( !$this->imgData )

                      $this->GetData();

             

              // 显示表格以及样式

              echo "<table border=1 style=\"border-collapse: collapse;font-size : 8pt; font-family : 'verdana'\">";

              echo "<tr align=center><td bgcolor='#EFEFEF'>&nbsp;</td><td bgcolor='#EFEFEF'>&nbsp;</td>";

              // 显示顶部坐标

              for( $i = 1; $i <= $this->imageInfo['Weight']; $i++ )

                      echo "<td height='10' bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $i ) . "</td>";

              echo "<td bgcolor='#EFEFEF'>&nbsp;</td></tr>";

             

              // 逐行绘制表格

              for( $I = 1; $I <= count( $this->imgData ); $I++ )

              {

                      // 获取本行数据

                      $line = $this->imgData[$I];

                      // 显示本行数据偏移

                      echo "<tr align=center><td height=10><font color=#CC3366>" . ( ( $I - 1 ) * $this->imageInfo['Weight'] ) . "</font></td><td bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $I ) . "</td>";

                      // 逐一绘制表格

                      for ( $i = 0; $i < count( $line ); $i++ )

                      {

                              // 获取当前像素点的颜色数值

                              $data = $line[$i];

                              // 判断绘制模式

                              if ( $this->drawMod == 'source' ) // 原始数据模式

                                      echo "<td>" . $data . "</td>";

                              else // 观察模式

                              {

                                      // 如果本像素点颜色是校验码颜色 设置本表格颜色为前景色

                                      if ( in_array( $data, $this->codeColor ) )

                                              $color = $this->frontColor;

                                      else // 如果本像素点颜色不是校验码颜色 设置本表格颜色为背景色

                                              $color = $this->backColor;

                                      // 获取当前像素的数据偏移

                                      $pos = ( $I - 1 ) * $this->imageInfo['Weight'] + $i + 1;

                                      // 显示表格

                                      echo "<td bgcolor=" . $color . " title='" . $pos . "'></td>";

                              }

                      }

                      echo "<td bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $I ) . "</td></tr>";

              }

              echo "<tr align=center><td bgcolor='#EFEFEF'>&nbsp;</td><td bgcolor='#EFEFEF'>&nbsp;</td>";

              // 显示底部坐标

              for( $i = 1; $i <= $this->imageInfo['Weight']; $i++ )

                      echo "<td height='10' bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $i ) . "</td>";

              echo "<td bgcolor='#EFEFEF'>&nbsp;</td></tr>";

              echo "</table>";

      }

      /**

      * 识别位图

      * @return string 识别后的字串

      * @access public

      */

      function Valid()

      {

              // 如果 $this->imgData 不存在 : 获取图片内容

              if ( !$this->imgData )

                      $this->GetData();

             

              // 根据校验码个数逐一识别

              for ( $i = 0; $i < $this->codeTotal; $i++)

              {

                      // 计算数字左上数据偏移

                      $bp = $this->offSet + ( $this->fontWeight + $this->fontSpace ) * $i;

                      // 获取对比特征码

                      $tmp = $this->_GetBound( $bp );

                      // 设置当前字符默认识别结果 * 代表无法识别

                      $c = '*';

                      // 遍历对比码,检查匹配情况

                      foreach ( $this->collateCode as $k => $v )

                      {

                              // 匹配

                              if ( $tmp === $v )

                              {

                                      // 设置当前字符识别结果

                                      $c = $k;

                                      break;

                              }

                      }

                      // 组合结果

                      $rs .= $c;

              }

              return $rs;

      }

      /**

      * 初始化数据状态

      * @access public

      */

      function Init()

      {

              $this->imageInfo = array();

              $this->buffer = array();

              $this->imgData = array();

      }

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // private function

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      /**

      * 读取INT

      * @return integer 数字

      * @access private

      */

      function _ReadInt()

      {

         return $this->_Bin2asc( fread ( $this->fp, 4 ) );

      }

      /**

      * 二进制转ASCII

      * @return string 转换后的内容

      * @access private

      */

      function _Bin2asc ( $binary )

      {

              $val = 0;

              for ($i = strlen( $binary ) - 1; $i >= 0; $i--)

              {

                 $ch = substr( $binary, $i, 1 );

                 $val = ( $val << 8 ) | ord( $ch );

         }

         return $val;

      }

      /**

      * 获取数据区域特征码

      * @return string 特征码

      * @access private

      */

      function _GetBound( $bp )

      {

              // 移动指针

              fseek( $this->fp, $bp );

              // 按照矩形图形从左到右、从上到下的方向进行提取

              for ( $i = 1; $i <= $this->fontHeight; $i++  )

              {

                      for ( $ii = 1; $ii <= $this->fontWeight; $ii++ )

                      {

                              // 获取当前像素点颜色数值

                              $data = $this->_Bin2asc( fread( $this->fp, 1 ) );

                              // 如该像素颜色数值和校验码颜色匹配则表示为1, 否则为0

                              if (  in_array( $data, $this->codeColor ) )

                                      $rs .= 1;

                              else

                                      $rs .= 0;

                      }

                      // 指针移动到下一校验码区域

                      fseek( $this->fp, $bp - $i * $this->imageInfo['Weight'] );

              }

              return $rs;

      }

}

?>

例四 识别3721验证码 ( 通过逐一设置参数的方式 )

识别结果:90849

例五 识别CSDN验证码 ( 通过装载配置参数的方式 )

识别结果:2293

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章