php 剪裁背景图,滑动图片,滑动验证
tp6使用方法:
getOkPng();
$temp = array_chunk($data['data'],20);
session("XSVer_VAL_SUM",1);
$arr = [
'status' => 0,
'left_pic'=>$temp[0],
'right_pic'=>$temp[1],
'pg_bg'=>$data['bg_pic'],
'ico_pic'=>$data['ico_pic'],
'y_point'=>$data['y_point']
];
echo json_encode($arr);
}
public function vaile(\think\Request $request){
static $v_num=1;
$ret = XSVerification::checkData($request->request('post.point'),session('XSVer'));
$v_num += session("XSVer_VAL_SUM");
if( $v_num > 6 ) {
session("XSVer_SUM",null);
exit(json_encode(array('state'=>4603,'data'=>'验证码失效')));
} else {
session("XSVer_VAL_SUM",$v_num);
}
if( $ret['state'] == 0 ) {
session("XSVer_VAL_SUM",0x111);
exit(json_encode(array('state'=>0,'data'=>session('XSVer'))));
} else {
session("XSVer_VAL_SUM",null);
exit(json_encode(array('state'=>603,'data'=>'错误'.$v_num)));
}
}
}
剪裁图片,滑动验证文件:
注意:图片存储目录 -- 自己对应下
XSVerification.php
tailoring_w = mt_rand(30,40);
$this->tailoring_h = mt_rand(30,40);
$this->ResourcesPath = APP_PATH.'Common/Resources/Admin/Code/'; //背景图片存放目录 (Resources)
$dir = './pic_temp/code/'.date('YmdH'); //被处理图片 存放目录(裁剪小图,错位背景图)
$this->tailoring_big_save_path = $dir.'/big/';
$this->tailoring_small_save_path = $dir.'/small/';
$this->getRandomPng();
$this->smallPicName = $this->tailoring_small_save_path.md5(uniqid()).$this->picSuffix;
$this->bigPicName = $this->tailoring_big_save_path.md5(uniqid().time()).$this->picSuffix;
//检查目录是否存在
if( !file_exists( $this->tailoring_big_save_path) ){
mkdir($this->tailoring_big_save_path,0777,true);
}
if(!file_exists( $this->tailoring_small_save_path) ) {
mkdir($this->tailoring_small_save_path,0777,true);
}
//删除过时资源图片
$this->PicSavePath = dirname($dir);
$this->delete_1hour_XSVerification($this->PicSavePath);
}
public function __construct()
{
$this->init();
$this->pic_info = $this->get_pic_wide_height($this->srcPic); // 获取原图的 宽高
$this->setRandomLocation( $this->pic_info);
$this->tailoring($this->srcPic,$this->smallPicName,$this->location_x, $this->location_y,$this->tailoring_w,$this->tailoring_h);
$this->mergePic($this->srcPic,$this->smallPicName,$this->bigPicName,$this->location_x, $this->location_y);
}
public function getOkPng()
{
return $this->RestructuringCutting($this->bigPicName,$this->bigPicName, $this->pic_info['w'], $this->pic_info['h']);
}
/**
* @name 设置随机 X,Y位置
* @param $pic_info
*/
public function setRandomLocation($pic_info)
{
$this->location_x = mt_rand(30,$pic_info['w']-$this->tailoring_w);
$this->location_y = mt_rand(5,$pic_info['h']-$this->tailoring_h);
}
/**
* @name 随机小数点
* @param int $min
* @param int $max
* @return int
*/
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
/**
* @name 随机获取参照图片
* @return string
* @throws \Exception
*/
private function getRandomPng(){
$this->srcPic = $this->ResourcesPath.$this->bigPicName.mt_rand(1,4).'.png';
if(!file_exists($this->srcPic )) {
throw new \Exception('图片资源不存在!!!');
} else {
return $this->srcPic;
}
}
/**
* @name 检查路径存在
* @param $filePath
*/
public function check_path_exists($filePath)
{
if( !file_exists(dirname($filePath)) ) {
@mkdir(dirname($filePath),0777,true);
}
}
/**
* @name 获取图片宽、高
* @param $pic_path
* @return array
*/
public function get_pic_wide_height( $pic_path )
{
$lim_size = getimagesize($pic_path);
return array('w'=> $lim_size[0], 'h'=> $lim_size[1]);
}
/**
* @name 删除一小时之前的 验证码图片
*/
public function delete_1hour_XSVerification($dir)
{
$op = dir($dir);
$time = date("YmdH",strtotime("-1 hours"));
$i=0;
while(false != ($item = $op->read()) && $i<=10) {
$i++;
if($item == '.' || $item == '..') {
continue;
}
if( (is_numeric($item) && $item<=$time) || !is_numeric($item) ) {
if (is_dir($op->path.'/'.$item) && rmdir($op->path . '/'.$item)==false ) {
$this->delete_1hour_XSVerification($op->path.'/'.$item);
} else {
unlink($op->path . '/' . $item);
}
}
}
}
/**
* @NAME 调整图像的宽高 ,看情况才有。减少系统开销
* @param $picFile
* @param $saveFile
* @param $thumbnailWide
* @param $thumbnailHeight
*/
public function Adjust_pic_wide_height($picFile,$saveFile,$thumbnailWide,$thumbnailHeight)
{
$imgStream = file_get_contents($picFile);
$im = imagecreatefromstring($imgStream);
$x = imagesx($im);//获取图片的宽
$y = imagesy($im);//获取图片的高
$xx = $thumbnailHeight;
$yy = $thumbnailWide;
if( $x > $y ){
$sy = 0;
$sx = 0;
$thumbw = $thumbnailWide;
$thumbh = $thumbnailHeight;
} else {
$sx = abs(($y-$x)/2);
$sy = 0;
$thumbw = $y;
$thumbh = $y;
}
if(function_exists("imagecreatetruecolor")) {
$dim = imagecreatetruecolor($yy, $xx); //创建目标图gd2 高清
} else {
$dim = imagecreate($yy, $xx); //创建目标图gd1,失色
}
imageCopyreSampled($dim,$im,0,0,$sx,$sy,$yy,$xx,$thumbw,$thumbh);
imagejpeg ($dim, $saveFile, 100);
imagedestroy($dim);
}
/**
* @name 裁剪小图
* @param $srcFile
* @param $picName
* @param $tailoring_x
* @param $tailoring_y
* @param $PicW
* @param $PicH
*/
private function tailoring($srcFile,$picName,$tailoring_x,$tailoring_y,$PicW,$PicH)
{
if( $this->picSuffix == '.webp' ) {
$imgStream = file_get_contents($srcFile);
$srcIm = imagecreatefromstring($imgStream);
} else {
$srcIm = @imagecreatefrompng($srcFile);
}
$dstIm = @imagecreatetruecolor($PicW,$PicH) or die("Cannot Initialize new GD image stream");
$dstImBg = @imagecolorallocate($dstIm,255,255,255);
imagefill($dstIm,0,0,$dstImBg); //创建背景为白色的图片
imagecopy($dstIm,$srcIm,0,0,$tailoring_x,$tailoring_y,$PicW,$PicH);
//imagewebp($dstIm,$picName,100);
imagepng($dstIm,$picName);
imagedestroy($dstIm);
imagedestroy($srcIm);
}
/**
* @name 去色合并块状,指定位置
* @param $srcFile
* @param $smallPicName
* @param $picName
* @param $tailoring_x
* @param $tailoring_y
*/
private function mergePic($srcFile,$smallPicName,$picName,$tailoring_x,$tailoring_y)
{
$src_lim = imagecreatefrompng($srcFile);
$lim_size = getimagesize($smallPicName); //取得水印图像尺寸,信息
$border = imagecolorat ($src_lim,5, 5);
$red = imagecolorallocate($src_lim, 0, 0, 0);
imagefilltoborder($src_lim, 0, 0, $border, $red);
$im_size = getimagesize($srcFile);
$src_w = $im_size[0];
$src_h = $im_size[1];
$src_im = imagecreatefrompng($srcFile);
$dst_im = imagecreatetruecolor($src_w,$src_h);
//根据原图尺寸创建一个相同大小的真彩色位图
$white = imagecolorallocate($dst_im,255,255,255);//白
//给新图填充背景色
$black = imagecolorallocate($dst_im,0,0,0);//黑
$red = imagecolorallocate($dst_im,255,0,0);//红
$orange = imagecolorallocate($dst_im,255,85,0);//橙
imagefill($dst_im,0,0,$black);
imagecopymerge($dst_im,$src_im,0,0,0,0,$src_w,$src_h,100);//原图图像写入新建真彩位图中
$src_lw = $tailoring_x; //水印位于背景图正中央width定位
$src_lh = $tailoring_y; //height定位
imagecopymerge($dst_im,$src_lim,$src_lw,$src_lh,0,0,$lim_size[0],$lim_size[1],66);// 合并两个图像,设置水印透明度$waterclearly
imagecopymerge($dst_im,$src_lim,$src_lw+2,$src_lh+2,0,0,$lim_size[0]-4,$lim_size[1]-4,33);
imagepng($dst_im,$picName); //生成图片 定义命名规则
imagedestroy($src_lim);
imagedestroy($src_im);
imagedestroy($dst_im);
}
//图片切割,打乱,重组
public function RestructuringCutting($srcFile,$bigPicName,$thumbnailWide,$thumbnailHeight)
{
$num_w = 20;
$num_h = 2;
//每张小图宽度,高度
$number_wide = $thumbnailWide/$num_w;
$number_height = $thumbnailHeight/$num_h;
$p_x =0;
$p_y =0;
for($y=0;$y<$num_h;$y++) {
for($x=0;$x<$num_w;$x++) {
if( $p_x >= $thumbnailWide ) {
$p_x = 0;
}
$data_source[] = array('x'=>$p_x,'y'=>$p_y);
$p_x +=$number_wide;
}
$p_y +=$number_height;
}
if( empty($data_source) ) {
return false;
}
shuffle($data_source);
$target_imgA = imagecreatetruecolor($thumbnailWide, $thumbnailHeight);
$dstImBg = @imagecolorallocate($target_imgA,255,255,255);
imagefill($target_imgA,0,0,$dstImBg); //创建背景为白色的图片
$srcIm = @imagecreatefrompng($srcFile); //截取指定区域
$p_x =0;
$p_y =0;
$dataV = array();
foreach($data_source as $key=>$val) {
imagecopy($target_imgA,$srcIm,$p_x,$p_y,$val['x'],$val['y'],$number_wide,$number_height);
$dataV[$val['x'].'_'.$val['y']] = array('X'=>$p_x.'_'.$p_y , 'Y'=>$val['x'].'_'.$val['y']);
$p_x +=$number_wide;
if( $p_x >= $thumbnailWide ) {
$p_x = 0;
$p_y = $number_height;
}
}
imagepng($target_imgA,$bigPicName);
imagedestroy($target_imgA);
imagedestroy($srcIm);
$_temp_xy_data = array();
foreach( $dataV as $key=>$val) {
if( $val['X'] != $val['Y'] ) {
$vv=explode('_', $dataV[$val['X']]['X'] );
$_temp_xy_data[] = $vv;
} else {
$vv=explode('_', $val['X'] );
$_temp_xy_data[] = $vv;
}
}
session($this->session_name,$this->location_x);
return array(
'session_name' => $this->session_name,
'data' => $_temp_xy_data,
'bg_pic' => ltrim($bigPicName,'.'),
'ico_pic' => array('url'=> ltrim($this->smallPicName,'.'),'w'=> $this->tailoring_w ,'h'=>$this->tailoring_h),
'x_point' => $this->location_x,
'y_point' => $this->location_y
);
}
/**
* @nmae 校验数据合法性
* @param $val
* @param $rules
* @return array
*/
public static function checkData($val,$rules)
{
if( empty($val) || !is_numeric($val) || empty($rules) || !is_numeric($rules) ) {
exit(json_encode(array('state'=>402,'info'=>'抱歉错误')));
}
$max = $rules+6;
$min = $rules-6;
if( $val <= $max && $val >= $min ) {
return array('state'=>0,'info'=>'正确','data'=>$rules);
} else {
return array('state'=>401,'info'=>'抱歉错误');
}
}
}