最近在做网页拖拽验证码的开源项目,需要在服务端生成图片对应的可移动的色块,但是网上的资源都是做缩略图,对整个图片进行缩放的,所以自己动手,完成了对图片进行裁剪小块的工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
<?php
namespace app\libs;
/**
* 2016-01-07 15:54:58
* lixiaoyu
*
* mode 1 : 强制裁剪,生成图片严格按照需要,不足放大,超过裁剪,图片始终铺满
* mode 2 : 和1类似,但不足的时候 不放大 会产生补白,可以用png消除。
* mode 3 : 只缩放,不裁剪,保留全部图片信息,会产生补白,
* mode 4 : 只缩放,不裁剪,保留全部图片信息,生成图片大小为最终缩放后的图片有效信息的实际大小,不产生补白
* 默认补白为白色,如果要使补白成透明像素,请使用savealpha()方法代替saveimage()方法
*/
class imagecrop{
var $simage ;
var $dimage ;
var $src_file ;
var $dst_file ;
var $src_width ;
var $src_height ;
var $src_ext ;
var $src_type ;
function __construct( $src_file , $dst_file = '' ){
$this ->src_file= $src_file ;
$this ->dst_file= $dst_file ;
$this ->loadimage();
}
function setsrcfile( $src_file ){
$this ->src_file= $src_file ;
}
function setdstfile( $dst_file ){
$this ->dst_file= $dst_file ;
}
function loadimage(){
list( $this ->src_width, $this ->src_height, $this ->src_type) = getimagesize ( $this ->src_file);
switch ( $this ->src_type) {
case imagetype_jpeg :
$this ->simage=imagecreatefromjpeg( $this ->src_file);
$this ->ext= 'jpg' ;
break ;
case imagetype_png :
$this ->simage=imagecreatefrompng( $this ->src_file);
$this ->ext= 'png' ;
break ;
case imagetype_gif :
$this ->simage=imagecreatefromgif( $this ->src_file);
$this ->ext= 'gif' ;
break ;
default :
exit ();
}
}
function saveimage( $filename = '' ){
$this ->dst_file= $filename ? $filename : $this ->dst_file;
switch ( $this ->src_type) {
case imagetype_jpeg :
imagejpeg( $this ->dimage, $this ->dst_file,100);
break ;
case imagetype_png :
imagepng( $this ->dimage, $this ->dst_file);
break ;
case imagetype_gif :
imagegif( $this ->dimage, $this ->dst_file);
break ;
default :
break ;
}
}
function outimage(){
switch ( $this ->src_type) {
case imagetype_jpeg :
header( 'content-type: image/jpeg' );
imagejpeg( $this ->dimage);
break ;
case imagetype_png :
header( 'content-type: image/png' );
imagepng( $this ->dimage);
break ;
case imagetype_gif :
header( 'content-type: image/gif' );
imagegif( $this ->dimage);
break ;
default :
break ;
}
}
function savealpha( $filename = '' ){
$this ->dst_file= $filename ? $filename . '.png' : $this ->dst_file . '.png' ;
imagesavealpha( $this ->dimage, true);
imagepng( $this ->dimage, $this ->dst_file);
}
function outalpha(){
imagesavealpha( $this ->dimage, true);
header( 'content-type: image/png' );
imagepng( $this ->dimage);
}
function destory(){
imagedestroy( $this ->simage);
imagedestroy( $this ->dimage);
}
function crop( $dst_width , $dst_height , $mode =1, $dst_file = '' ){
if ( $dst_file ) $this ->dst_file= $dst_file ;
$this ->dimage = imagecreatetruecolor( $dst_width , $dst_height );
$bg = imagecolorallocatealpha( $this ->dimage,255,255,255,127);
imagefill( $this ->dimage, 0, 0, $bg );
imagecolortransparent( $this ->dimage, $bg );
$ratio_w =1.0 * $dst_width / $this ->src_width;
$ratio_h =1.0 * $dst_height / $this ->src_height;
$ratio =1.0;
switch ( $mode ){
case 1: // always crop
if ( ( $ratio_w < 1 && $ratio_h < 1) || ( $ratio_w > 1 && $ratio_h > 1)){
$ratio = $ratio_w < $ratio_h ? $ratio_h : $ratio_w ;
$tmp_w = (int)( $dst_width / $ratio );
$tmp_h = (int)( $dst_height / $ratio );
$tmp_img =imagecreatetruecolor( $tmp_w , $tmp_h );
$src_x = (int) (( $this ->src_width- $tmp_w )/2) ;
$src_y = (int) (( $this ->src_height- $tmp_h )/2) ;
imagecopy( $tmp_img , $this ->simage, 0,0, $src_x , $src_y , $tmp_w , $tmp_h );
imagecopyresampled( $this ->dimage, $tmp_img ,0,0,0,0, $dst_width , $dst_height , $tmp_w , $tmp_h );
imagedestroy( $tmp_img );
} else {
$ratio = $ratio_w < $ratio_h ? $ratio_h : $ratio_w ;
$tmp_w = (int)( $this ->src_width * $ratio );
$tmp_h = (int)( $this ->src_height * $ratio );
$tmp_img =imagecreatetruecolor( $tmp_w , $tmp_h );
imagecopyresampled( $tmp_img , $this ->simage,0,0,0,0, $tmp_w , $tmp_h , $this ->src_width, $this ->src_height);
$src_x = (int)( $tmp_w - $dst_width ) / 2 ;
$src_y = (int)( $tmp_h - $dst_height ) / 2 ;
imagecopy( $this ->dimage, $tmp_img , 0,0, $src_x , $src_y , $dst_width , $dst_height );
imagedestroy( $tmp_img );
}
break ;
case 2: // only small
if ( $ratio_w < 1 && $ratio_h < 1){
$ratio = $ratio_w < $ratio_h ? $ratio_h : $ratio_w ;
$tmp_w = (int)( $dst_width / $ratio );
$tmp_h = (int)( $dst_height / $ratio );
$tmp_img =imagecreatetruecolor( $tmp_w , $tmp_h );
$src_x = (int) ( $this ->src_width- $tmp_w )/2 ;
$src_y = (int) ( $this ->src_height- $tmp_h )/2 ;
imagecopy( $tmp_img , $this ->simage, 0,0, $src_x , $src_y , $tmp_w , $tmp_h );
imagecopyresampled( $this ->dimage, $tmp_img ,0,0,0,0, $dst_width , $dst_height , $tmp_w , $tmp_h );
imagedestroy( $tmp_img );
} elseif ( $ratio_w > 1 && $ratio_h > 1){
$dst_x = (int) abs ( $dst_width - $this ->src_width) / 2 ;
$dst_y = (int) abs ( $dst_height - $this ->src_height) / 2;
imagecopy( $this ->dimage, $this ->simage, $dst_x , $dst_y ,0,0, $this ->src_width, $this ->src_height);
} else {
$src_x =0; $dst_x =0; $src_y =0; $dst_y =0;
if (( $dst_width - $this ->src_width) < 0){
$src_x = (int) ( $this ->src_width - $dst_width )/2;
$dst_x =0;
} else {
$src_x =0;
$dst_x = (int) ( $dst_width - $this ->src_width)/2;
}
if ( ( $dst_height - $this ->src_height) < 0){
$src_y = (int) ( $this ->src_height - $dst_height )/2;
$dst_y = 0;
} else {
$src_y = 0;
$dst_y = (int) ( $dst_height - $this ->src_height)/2;
}
imagecopy( $this ->dimage, $this ->simage, $dst_x , $dst_y , $src_x , $src_y , $this ->src_width, $this ->src_height);
}
break ;
case 3: // keep all image size and create need size
if ( $ratio_w > 1 && $ratio_h > 1){
$dst_x = (int)( abs ( $dst_width - $this ->src_width )/2) ;
$dst_y = (int)( abs ( $dst_height - $this ->src_height)/2) ;
imagecopy( $this ->dimage, $this ->simage, $dst_x , $dst_y ,0,0, $this ->src_width, $this ->src_height);
} else {
$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w ;
$tmp_w = (int)( $this ->src_width * $ratio );
$tmp_h = (int)( $this ->src_height * $ratio );
$tmp_img =imagecreatetruecolor( $tmp_w , $tmp_h );
imagecopyresampled( $tmp_img , $this ->simage,0,0,0,0, $tmp_w , $tmp_h , $this ->src_width, $this ->src_height);
$dst_x = (int)( abs ( $tmp_w - $dst_width )/2) ;
$dst_y = (int)( abs ( $tmp_h - $dst_height )/2) ;
imagecopy( $this ->dimage, $tmp_img , $dst_x , $dst_y ,0,0, $tmp_w , $tmp_h );
imagedestroy( $tmp_img );
}
break ;
case 4: // keep all image but create actually size
if ( $ratio_w > 1 && $ratio_h > 1){
$this ->dimage = imagecreatetruecolor( $this ->src_width, $this ->src_height);
imagecopy( $this ->dimage, $this ->simage,0,0,0,0, $this ->src_width, $this ->src_height);
} else {
$ratio = $ratio_w > $ratio_h ? $ratio_h : $ratio_w ;
$tmp_w = (int)( $this ->src_width * $ratio );
$tmp_h = (int)( $this ->src_height * $ratio );
$this ->dimage = imagecreatetruecolor( $tmp_w , $tmp_h );
imagecopyresampled( $this ->dimage, $this ->simage,0,0,0,0, $tmp_w , $tmp_h , $this ->src_width, $this ->src_height);
}
break ;
}
} // end crop
/**
*
* 裁切方法
* 2016-01-07 15:05:44
* lixiaoyu
*
* @param $dst_width 目标长
* @param $dst_height 目标高
* @param $dst_x 裁剪部分和原图左侧的距离
* @param $dst_y 裁剪部分和原图右侧的距离
* @param int $mode 模式
* @param string $dst_file 目标文件路径
*/
function cut( $dst_width , $dst_height , $dst_x , $dst_y , $dst_file = '' )
{
if ( $dst_file ) $this ->dst_file = $dst_file ; //设置目标文件位置
$this ->dimage = imagecreatetruecolor( $dst_width , $dst_height ); //创建了目标文件的大小的画布
$bg = imagecolorallocatealpha( $this ->dimage, 255, 255, 255, 127); //给画布分配颜色
imagefill( $this ->dimage, 0, 0, $bg ); //给图像用颜色进行填充
imagecolortransparent( $this ->dimage, $bg ); //背景定义成透明色
$ratio_w = 1.0 * $dst_width / $this ->src_width; //横向缩放的比例
$ratio_h = 1.0 * $dst_height / $this ->src_height; //纵向缩放的比例
//var_dump($this);
//不进行缩放,直接对图像进行裁剪
$ratio = 1.0;
$tmp_w = (int)( $dst_width / $ratio );
$tmp_h = (int)( $dst_height / $ratio );
$tmp_img = imagecreatetruecolor( $dst_width , $dst_height ); //创建暂时保存的画布
imagecopy( $tmp_img , $this ->simage, 0,0, $dst_x , $dst_y , $dst_width , $dst_height ); //拷贝出图像的一部分,进行裁切
imagecopyresampled( $this ->dimage, $tmp_img ,0,0,0,0, $dst_width , $dst_height , $tmp_w , $tmp_h ); //把暂时缓存的图片,放到目标文件里面
imagedestroy( $tmp_img );
}
}
?>
|
use
裁剪图像
1
2
3
4
5
|
$ic = new imagecrop( $pathtofile , './pic/aftercrop' .time(). '.jpg' );
$ic ->cut(40,30,120,130);
$ic ->saveimage();
//$ic->savealpha();将补白变成透明像素保存
$ic ->destory();
|
实现效果
原图
裁剪之后的图
缩放图像
原图
缩略图
本文重点在于使用图像处理函数 imagecopy 和 imagecopyresampled
bool imagecopy ( resource dstim,resourcesrc_im , int dstx,intdst_y , int srcx,intsrc_y , int srcw,intsrc_h )
将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。