PHP 裁切问题,求大神指点指点,弄了一天了...

叫我梁大侠 2015-06-02 05:23:13
我前端用JCROP获取到x、y坐标、宽度、高度,传递到 uphoto.php处理,现在一切正常,但是如果前端用户选择的图片宽度过大(我用css样式控制用户选择的图片最大宽度为680px),裁切出来的就不正常了...我查阅了一些资料,说是需要按比例换算,但是是按什么比例换算啊,用户选择的图片的宽度(大于680px时)和680换算么?

这是 uphoto.php:




$x1 = $_POST["x1"];
$x2 = $_POST["x2"];
$y1 = $_POST["y1"];
$y2 = $_POST["y2"];
$targ_w = $_POST["w"];
$targ_h = $_POST["h"];


if ($_FILES["mfile"]["error"]){echo "error: " . $_FILES["file"]["error"];}
if (!empty($_FILES["mfile"]["name"])){ //提取文件域内容名称,并判断
$path = "/upload/user/photo/"; //上传路径
//检查是否有该文件夹,如果没有就创建,并给予最高权限
//if(!file_exists($path)){mkdir("$path", 0700);}
//允许上传的文件格式
$allow_type = array("image/gif","image/pjpeg","image/jpeg","image/png");
//检查上传文件是否在允许上传的类型
if(!in_array($_FILES["mfile"]["type"], $allow_type)){echo "error:格式有误,仅支持gif/jpg/png"; exit();}
//检测图片大小
if($_FILES["mfile"]["size"] > 5*1024*1024){echo "error:文件不得超过5M"; exit();}
$filetype = $_FILES["mfile"]["type"];
if($filetype == "image/jpeg"){
$img_type = ".jpg";
}
if ($filetype == "image/jpg") {
$img_type = ".jpg";
}
if ($filetype == "image/pjpeg") {
$img_type = ".jpg";
}
if($filetype == "image/gif"){
$img_type = ".gif";
}
if($filetype == "image/png"){
$img_type = ".png";
}
if($_FILES["mfile"]["name"])
{
$randstr = random_str().date("YmdHis"); //获取时间并赋值给变量
$saveto = $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type; //图片的完整路径
$newimg = $randstr.$img_type; //图片名称
$flag=1;
}
//END IF
if ($flag){$result = move_uploaded_file($_FILES["mfile"]["tmp_name"], $saveto);}
//特别注意这里传递给move_uploaded_file的第一个参数为上传到服务器上的临时文件
$src_file = $saveto;
}}


$type = exif_imagetype($src_file);

$support_type = array(IMAGETYPE_JPEG , IMAGETYPE_PNG , IMAGETYPE_GIF);
if(!in_array($type, $support_type, true)){echo "error:当前图片格式非JPG/PNG/GIF";exit();}
//Load image
switch($type) {
case IMAGETYPE_JPEG :
$src_img = imagecreatefromjpeg($src_file);
break;
case IMAGETYPE_PNG :
$src_img = imagecreatefrompng($src_file);
break;
case IMAGETYPE_GIF :
$src_img = imagecreatefromgif($src_file);
break;
default:
echo "Load image error!";
exit();
}

$dst_r = ImageCreateTrueColor($targ_w, $targ_h);
list($width_orig, $height_orig) = getimagesize($src_file);
//if ($width_orig > 680){
//$new_width_orig = 680;
//$new_height_orig = ($height_orig*680)/$width_orig;
//}
//else {
//$new_width_orig = $targ_w;
//$new_height_orig = $targ_h;
//}

//echo $new_width_orig."<br />";
//echo $new_height_orig."<br />";
//echo "x:".$x1."<br />";
//echo "y:".$y1;
//exit();

imagecopyresampled($dst_r, $src_img, 0, 0, $x1, $y1, $targ_w, $targ_h, $targ_w, $targ_h);
//imagecopyresampled($dst_r, $src_img, 0, 0, $x1, $y1, $targ_w, $targ_h, $targ_w, $targ_h);

switch($type) {
case IMAGETYPE_JPEG :
header('Content-type: image/jpeg');
imagejpeg($dst_r, null, 100);
break;
case IMAGETYPE_PNG :
header('Content-type: image/png');
imagepng($dst_r, null, 100);
break;
case IMAGETYPE_GIF :
header('Content-type: image/gif');
imagegif($dst_r, null, 100);
break;
default:
break;
}
echo "<img src='". $dst_r ."' />";
exit;




求大神指点指点
...全文
188 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
傲雪星枫 2015-06-03
  • 打赏
  • 举报
回复
可以参考一下我之前写的裁剪。因为你是要裁剪,所以宽和高有一个是和裁剪后的尺寸的宽和高一样,另一边会>=裁剪后的。 http://blog.csdn.net/fdipzone/article/details/9316385

    /** 获取目标图生成的size 
    * @return Array $width, $height 
    */  
    private function get_size(){  
        list($owidth, $oheight) = getimagesize($this->_source);  
        $width = (int)($this->_width);  
        $height = (int)($this->_height);  
          
        switch($this->_type){  
            case 'fit':  
                $pic_w = $width;  
                $pic_h = (int)($pic_w*$oheight/$owidth);  
                if($pic_h>$height){  
                    $pic_h = $height;  
                    $pic_w = (int)($pic_h*$owidth/$oheight);  
                }  
                break;  
            case 'crop':  
                $pic_w = $width;  
                $pic_h = (int)($pic_w*$oheight/$owidth);  
                if($pic_h<$height){  
                    $pic_h = $height;  
                    $pic_w = (int)($pic_h*$owidth/$oheight);  
                }  
                break;  
        }  
  
        return array($pic_w, $pic_h);  
    } 
叫我梁大侠 2015-06-03
  • 打赏
  • 举报
回复
引用 12 楼 xuzuning 的回复:
假定 $dst_r 是 image 资源 imagegif($dst_r); 就是输出图片数据流 imagegif($dst_r, '图片文件名'); 就是保存到文件 数据库保存图片文件名即可 如果数据库要保存图片数据,则应用合适的 blob 类型字段 数据从 图片文件 读取或拦截php的输出 用 bin2hex 函数转换成字符串,在前面加 ‘0x'
谢谢啊,怎么做到让它不输出图片流呢(输出图片流为的就是保存成新文件名),直接保存到文件夹,然后更新数据库呢?
xuzuning 2015-06-03
  • 打赏
  • 举报
回复
假定 $dst_r 是 image 资源 imagegif($dst_r); 就是输出图片数据流 imagegif($dst_r, '图片文件名'); 就是保存到文件 数据库保存图片文件名即可 如果数据库要保存图片数据,则应用合适的 blob 类型字段 数据从 图片文件 读取或拦截php的输出 用 bin2hex 函数转换成字符串,在前面加 ‘0x'
叫我梁大侠 2015-06-03
  • 打赏
  • 举报
回复
引用 10 楼 xuzuning 的回复:
图片的宽、高 应通过 imagesx($src_img)、imagesy($src_img) 取得,传入的可能不正确 imagedestory() 是释放资源,比如 imagedestory($src_img) 不写也可以,php 会替你释放的
谢谢啊 我现在想把裁切好的图片保存到数据库中,却出现 图像 ... 因存在错误而无法显示。 这是代码: $dst_r = ImageCreateTrueColor($targ_w, $targ_h); imagecopyresampled($dst_r, $src_img, 0, 0, $x1, $y1, $targ_w, $targ_h, $targ_w, $targ_h); $mphoto = $path.$uid.$randstr.$img_type; $mphoto_save = $_SERVER['DOCUMENT_ROOT'].$mphoto; //echo $mphoto_save; //exit(); switch($type) { case IMAGETYPE_JPEG : header('Content-type: image/jpeg'); imagejpeg($dst_r, $mphoto_save, 100); break; case IMAGETYPE_PNG : header('Content-type: image/png'); imagepng($dst_r, $mphoto_save, 100); break; case IMAGETYPE_GIF : header('Content-type: image/gif'); imagegif($dst_r, $mphoto_save, 100); break; default: break; } //echo "<img src='". $dst_r ."' />"; //exit(); imagedestory($dst_r); imagedestory($src_img); if (!mysqli_query($conn, "update dh_member set photo='". $mphoto ."' where id=". $uid ."")){die(mysqli_error($conn));} echo "<form action=\"modify.php\" method=\"post\" name=\"back_form\"><input name=\"id\" id=\"id\" value=\"". $uid ."\" type=\"hidden\"/></form><script>document.back_form.submit();</script>"; exit(); 是怎么回事啊,我都没有输出图片啊..
xuzuning 2015-06-03
  • 打赏
  • 举报
回复
图片的宽、高 应通过 imagesx($src_img)、imagesy($src_img) 取得,传入的可能不正确 imagedestory() 是释放资源,比如 imagedestory($src_img) 不写也可以,php 会替你释放的
叫我梁大侠 2015-06-03
  • 打赏
  • 举报
回复
引用 8 楼 xuzuning 的回复:
宽度大于680的图片裁切成宽度680px 由 图片宽 / 图片高 = 680 / h 得 h = 680 / 图片宽 * 图片高 即 $targ_h = 680 / $pic_w * $pic_h; $targ_w = 680;
谢谢啊,我现在通过将用户选择的图片若超过680px就裁切成宽度680px(高度通过你那样的算法算的),然后再裁切成头像,测试是正常的,但还有几个细节我有点不明白,下面是源码:


$x1 = $_POST["x1"];
$x2 = $_POST["x2"];
$y1 = $_POST["y1"];
$y2 = $_POST["y2"];
$targ_w = $_POST["w"];
$targ_h = $_POST["h"];


if ($_FILES["mfile"]["error"]){echo "error: " . $_FILES["file"]["error"];}
if (!empty($_FILES["mfile"]["name"])){ //提取文件域内容名称,并判断
$path = "/upload/user/photo/"; //上传路径
//检查是否有该文件夹,如果没有就创建,并给予最高权限
//if(!file_exists($path)){mkdir("$path", 0700);}
//允许上传的文件格式
$allow_type = array("image/gif","image/pjpeg","image/jpeg","image/png");
//检查上传文件是否在允许上传的类型
if(!in_array($_FILES["mfile"]["type"], $allow_type)){echo "error:格式有误,仅支持gif/jpg/png"; exit();}
//检测图片大小
if($_FILES["mfile"]["size"] > 5*1024*1024){echo "error:文件不得超过5M"; exit();}
$filetype = $_FILES["mfile"]["type"];
if($filetype == "image/jpeg"){
$img_type = ".jpg";
}
if ($filetype == "image/jpg") {
$img_type = ".jpg";
}
if ($filetype == "image/pjpeg") {
$img_type = ".jpg";
}
if($filetype == "image/gif"){
$img_type = ".gif";
}
if($filetype == "image/png"){
$img_type = ".png";
}
if($_FILES["mfile"]["name"])
{
$randstr = random_str().date("YmdHis"); //获取时间并赋值给变量
$saveto = $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type; //图片的完整路径
$newimg = $randstr.$img_type; //图片名称
$flag=1;
}
//END IF
if ($flag){$result = move_uploaded_file($_FILES["mfile"]["tmp_name"], $saveto);}
//特别注意这里传递给move_uploaded_file的第一个参数为上传到服务器上的临时文件
$src_file = $saveto;
}}

list($width_orig, $height_orig) = getimagesize($src_file);
if ($width_orig > 680){
$tmp_type = exif_imagetype($src_file);
switch($tmp_type) {
case IMAGETYPE_JPEG :
$tmp_src_img = imagecreatefromjpeg($src_file);
break;
case IMAGETYPE_PNG :
$tmp_src_img = imagecreatefrompng($src_file);
break;
case IMAGETYPE_GIF :
$tmp_src_img = imagecreatefromgif($src_file);
break;
default:
echo "Load image error!";
exit();
}
$ntmp_width = 680;
$ntmp_height = $height_orig*$ntmp_width/$width_orig;
$ntmp_imgr = ImageCreateTrueColor($ntmp_width, $ntmp_height);
imagecopyresampled($ntmp_imgr, $tmp_src_img, 0, 0, 0, 0, $ntmp_width, $ntmp_height, $width_orig, $height_orig);
switch($tmp_type) {
case IMAGETYPE_JPEG :
header('Content-type: image/jpeg');
imagejpeg($ntmp_imgr, $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type, 100);
break;
case IMAGETYPE_PNG :
header('Content-type: image/png');
imagepng($ntmp_imgr, $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type, 100);
break;
case IMAGETYPE_GIF :
header('Content-type: image/gif');
imagegif($ntmp_imgr, $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type, 100);
break;
default:
break;
}
$src_file = $_SERVER['DOCUMENT_ROOT'].$path.$randstr.$img_type;
}

$type = exif_imagetype($src_file);
switch($type) {
case IMAGETYPE_JPEG :
$src_img = imagecreatefromjpeg($src_file);
break;
case IMAGETYPE_PNG :
$src_img = imagecreatefrompng($src_file);
break;
case IMAGETYPE_GIF :
$src_img = imagecreatefromgif($src_file);
break;
default:
echo "Load image error!";
exit();
}
$dst_r = ImageCreateTrueColor($targ_w, $targ_h);
imagecopyresampled($dst_r, $src_img, 0, 0, $x1, $y1, $targ_w, $targ_h, $targ_w, $targ_h);
switch($type) {
case IMAGETYPE_JPEG :
header('Content-type: image/jpeg');
imagejpeg($dst_r, null, 100);
break;
case IMAGETYPE_PNG :
header('Content-type: image/png');
imagepng($dst_r, null, 100);
break;
case IMAGETYPE_GIF :
header('Content-type: image/gif');
imagegif($dst_r, null, 100);
break;
default:
break;
}
echo "<img src='". $dst_r ."' />";
exit;
其中那个红色部分,我如果换成上传的图片的宽度和高度($width_orig,$height_orig),就会不正常... 按我现在这样的方式,有没办法优化下? 我看好多使用裁切之后 都会 imagedestory() 这个是删除图片流,而不是原图吧?
xuzuning 2015-06-03
  • 打赏
  • 举报
回复
宽度大于680的图片裁切成宽度680px 由 图片宽 / 图片高 = 680 / h 得 h = 680 / 图片宽 * 图片高 即 $targ_h = 680 / $pic_w * $pic_h; $targ_w = 680;
叫我梁大侠 2015-06-03
  • 打赏
  • 举报
回复
引用 6 楼 fdipzone 的回复:
可以参考一下我之前写的裁剪。因为你是要裁剪,所以宽和高有一个是和裁剪后的尺寸的宽和高一样,另一边会>=裁剪后的。 http://blog.csdn.net/fdipzone/article/details/9316385

    /** 获取目标图生成的size 
    * @return Array $width, $height 
    */  
    private function get_size(){  
        list($owidth, $oheight) = getimagesize($this->_source);  
        $width = (int)($this->_width);  
        $height = (int)($this->_height);  
          
        switch($this->_type){  
            case 'fit':  
                $pic_w = $width;  
                $pic_h = (int)($pic_w*$oheight/$owidth);  
                if($pic_h>$height){  
                    $pic_h = $height;  
                    $pic_w = (int)($pic_h*$owidth/$oheight);  
                }  
                break;  
            case 'crop':  
                $pic_w = $width;  
                $pic_h = (int)($pic_w*$oheight/$owidth);  
                if($pic_h<$height){  
                    $pic_h = $height;  
                    $pic_w = (int)($pic_h*$owidth/$oheight);  
                }  
                break;  
        }  
  
        return array($pic_w, $pic_h);  
    } 
谢谢啊 , 按你那样调整了,还是不正常的额: list($width_orig, $height_orig) = getimagesize($src_file); $pic_w = $targ_w; $pic_h = (int)($pic_w*$height_orig/$width_orig); if($pic_h < $targ_h){ $pic_h = $targ_h; $pic_w = (int)($pic_h*$width_orig/$height_orig); } imagecopyresampled($dst_r, $src_img, 0, 0, $x1, $y1, $targ_w, $targ_h, $pic_w, $pic_h); 我现在是想把宽度680的图片裁切成宽度680px,然后在裁切...
叫我梁大侠 2015-06-02
  • 打赏
  • 举报
回复
$targ_w, $targ_h 这两个是裁切的宽度和高度 会不会跟这两个有关呢?
叫我梁大侠 2015-06-02
  • 打赏
  • 举报
回复
list($width_orig, $height_orig) = getimagesize($src_file); if ($width_orig > 680){ $nx = $x1/680 * $width_orig; $new_height = $height_orig*680/$width_orig; $ny = $y1/$new_height * $height_orig; } else { $nx = $x1; $ny = $y1; } imagecopyresampled($dst_r, $src_img, 0, 0, $nx, $ny, $targ_w, $targ_h, $targ_w, $targ_h); 这样计算么,也还是不行..
xuzuning 2015-06-02
  • 打赏
  • 举报
回复
你 y 方向没有计算
叫我梁大侠 2015-06-02
  • 打赏
  • 举报
回复
引用 1 楼 xuzuning 的回复:
用css样式控制用户选择的图片最大宽度为680px 就表示用户看到的是经过动态缩放的副本 那么你在传递裁剪区域坐标的时候,还需传递图片的原始尺寸 换算一下就可以了 X= x/680*图片宽
谢谢啊,按你那样换算了 还是不正常.. list($width_orig, $height_orig) = getimagesize($src_file); if ($width_orig > 680){ $nx = $x1/680 * $width_orig; } else { $nx = $x1; } imagecopyresampled($dst_r, $src_img, 0, 0, $nx, $y1, $targ_w, $targ_h, $targ_w, $targ_h);
xuzuning 2015-06-02
  • 打赏
  • 举报
回复
用css样式控制用户选择的图片最大宽度为680px 就表示用户看到的是经过动态缩放的副本 那么你在传递裁剪区域坐标的时候,还需传递图片的原始尺寸 换算一下就可以了 X= x/680*图片宽

21,873

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧