PHP按目标比例和尺寸缩小并裁切图片
重点是关于图片翻转、旋转部分的处理
/** * 按目标比例和尺寸缩小并裁切图片,如果原图尺寸小于目标尺寸,则只按比例裁切 * @param $img_name 原图片名称(不是路径) * @param $width 目标图片宽度,如果原图宽度不等于目标宽度,则原图按目标比例缩放后再裁切 * @param $width 目标图片高度 */ private function img_convert_do($img_name, $width, $height){ //$new_name=date('YmdHis').my_str_shuffle(5,'number,lower').substr($img_name,strrpos($img_name,'.')); $new_name=date('YmdHis').my_str_shuffle(5,'number,lower').'.jpg'; $old_img=SRC_PATH.$img_name; $new_img=DST_PATH.$new_name; /* exif_read_data($old_img)结果如下: Array ( [FileName] => a.jpg [FileDateTime] => 1750318340 [FileSize] => 17175 [FileType] => 2 [MimeType] => image/jpeg [SectionsFound] => ANY_TAG, IFD0, EXIF [COMPUTED] => Array ( [html] => width="536" height="404" [Height] => 404 [Width] => 536 [IsColor] => 1 [ByteOrderMotorola] => 1 ) [Orientation] => 8 [Exif_IFD_Pointer] => 318 [UndefinedTag:0xEA1C] => ) */ $exif_res=@exif_read_data($old_img); if($exif_res===false){ $size_arr = @getimagesize($old_img); if(!is_array($size_arr)){ exit('图片尺寸获取失败:'.$img_name); } $w = $size_arr[0]; $h= $size_arr[1]; //printr($size_arr); }else{ $w=$exif_res['COMPUTED']['Width']; $h=$exif_res['COMPUTED']['Height']; //printr($exif_res); } $source = imagecreatefromstring(file_get_contents($old_img)); switch(array_item($exif_res,'Orientation')){ case 1: //无翻转 break; case 2: //水平翻转 imageflip($source,IMG_FLIP_HORIZONTAL); break; case 3: //旋转180度 $source = imagerotate($source,180,0); break; case 4: //垂直翻转 imageflip($source,IMG_FLIP_VERTICAL); break; case 5: //顺时针旋转90度+水平翻转 $source = imagerotate($source,-90,0); imageflip($source,IMG_FLIP_HORIZONTAL); break; case 6: //顺时针旋转90度 $source = imagerotate($source,-90,0); break; case 7: //逆时针旋转90度+水平翻转 $source = imagerotate($source,90,0); imageflip($source,IMG_FLIP_HORIZONTAL); break; case 8: //逆时针旋转90度 $source = imagerotate($source,90,0); break; default: //png等无方向属性 } switch(array_item($exif_res,'Orientation')){ case 5: case 6: case 7: case 8: //旋转90度的图片扶正后要宽高值要互换 $tmp=$w; $w=$h; $h=$tmp; unset($tmp); break; } $src_w=$w; $src_h=$h; if($w/$h < $width/$height){ $h=ceil($w*$height/$width); }else if($w/$h > $width/$height){ $w=ceil($width*$h/$height); }else{ //比例一致时,如果原图小于100K则直接复制 if(filesize($old_img)<100*1024){ copy($old_img,$new_img); return $new_name; } } if($w<$width){ $width=$w; $height=$h; } //echo $w,'x',$h,'<br>',$width,'x',$height,'<br>';return; //新建真彩色图像 $im = imagecreatetruecolor($width, $height); //为图像分配颜色 //$color = imagecolorallocate($im, 255,255,255); //从指定坐标开始填充颜色 //imagefill($im, 0,0, $color); //从字符串的图像流中新建图像,可以自动识别文件类型,但是比 imagecreatefromjpeg 等多消耗内存 //totxt($old_img, FCPATH.'photo.txt', true); //$source = imagecreatefromstring(file_get_contents($old_img)); /* 从 x、y 坐标 src_x、src_y 开始,将 src_image 的一部分复制到 dst_image 上, 宽度为 src_width,高度为 src_height。定义的部分将被复制到 x,y 坐标 dst_x 和 dst_y 上。 imagecopy( GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height ): bool 从 src_image 位置(src_x、src_y)开始取出一个宽度为 src_width 高度为 src_height 的矩形区域, 并将其放置在 dst_image 中位置从(dst_x、dst_y)开始宽度为 dst_width 高度为 dst_height 的矩形区域中。 imagecopyresampled( GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height ): bool 输出图象到浏览器或文件 image 由图象创建函数(例如imagecreatetruecolor())返回的 GdImage 对象。 file 文件保存的路径或者已打开的流资源(此方法返回后自动关闭该流资源),如果未设置或为 null,将会直接输出原始图象流。 quality 为可选项,范围从 0(最差质量,文件最小)到 100(最佳质量,文件最大)。默认值(-1)使用 IJG 默认的质量值(大约 75)。 imagejpeg(GdImage $image, resource|string|null $file = null, int $quality = -1): bool */ //执行剪裁(高质量重采样) //($src_h-$h)/4 此处是4而不是2的原因:尽量从上边开始剪裁,避免上边剪裁过大,导致头到照片顶部留白太小甚至剪到头 imagecopyresampled($im, $source, 0,0, $src_w>$w?($src_w-$w)/2:0,$src_h>$h?($src_h-$h)/3:0, $width,$height, $w,$h); imagedestroy($source); //保存到文件 imagejpeg($im, $new_img, 90); imagedestroy($im); //exit('ok'); return $new_name; }