|
楼主 |
发表于 2005-8-23 02:08:35
|
来自 中国广西南宁
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'> </td><td bgcolor='#EFEFEF'> </td>";
- // 显示顶部坐标
- for( $i = 1; $i <= $this->imageInfo['Weight']; $i++ )
- echo "<td height='10' bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $i ) . "</td>";
- echo "<td bgcolor='#EFEFEF'> </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'> </td><td bgcolor='#EFEFEF'> </td>";
- // 显示底部坐标
- for( $i = 1; $i <= $this->imageInfo['Weight']; $i++ )
- echo "<td height='10' bgcolor='#EFEFEF'>" . sprintf( '%02.0f', $i ) . "</td>";
- echo "<td bgcolor='#EFEFEF'> </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;
- }
- }
- ?>
复制代码 |
|