PHP 裁切問題,求大神指點指點,弄了一天了.

來源:互聯網
上載者:User
我前端用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 IFif ($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 imageswitch($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."
";//echo $new_height_orig."
";//echo "x:".$x1."
";//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 "";exit;


求大神指點指點


回複討論(解決方案)

用css樣式控制使用者選擇的圖片最大寬度為680px
就表示使用者看到的是經過動態縮放的副本
那麼你在傳遞裁剪地區座標的時候,還需傳遞圖片的原始大小
換算一下就可以了
X= x/680*圖片寬

用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);

你 y 方向沒有計算

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);

這樣計算麼,也還是不行..

$targ_w, $targ_h 這兩個是裁切的寬度和高度 會不會跟這兩個有關呢?

可以參考一下我之前寫的裁剪。因為你是要裁剪,所以寬和高有一個是和裁剪後的尺寸的寬和高一樣,另一邊會>=裁剪後的。
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);      } 

可以參考一下我之前寫的裁剪。因為你是要裁剪,所以寬和高有一個是和裁剪後的尺寸的寬和高一樣,另一邊會>=裁剪後的。
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,然後在裁切...

寬度大於680的圖片裁切成寬度680px
由 圖片寬 / 圖片高 = 680 / h
得 h = 680 / 圖片寬 * 圖片高

$targ_h = 680 / $pic_w * $pic_h;
$targ_w = 680;

寬度大於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 IFif ($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 "";exit;


其中那個紅色部分,我如果換成上傳的圖片的寬度和高度($width_orig,$height_orig),就會不正常...
按我現在這樣的方式,有沒辦法最佳化下?
我看好多使用裁切之後 都會 imagedestory() 這個是刪除圖片流,而不是原圖吧?

圖片的寬、高 應通過 imagesx($src_img)、imagesy($src_img) 取得,傳入的可能不正確
imagedestory() 是釋放資源,比如 imagedestory($src_img)
不寫也可以,php 會替你釋放的

圖片的寬、高 應通過 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 "";
//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 "";
exit();

是怎麼回事啊,我都沒有輸出圖片啊..

假定 $dst_r 是 image 資源
imagegif($dst_r); 就是輸出圖片資料流
imagegif($dst_r, '圖片檔案名稱'); 就是儲存到檔案

資料庫儲存圖片檔案名稱即可
如果資料庫要儲存圖片資料,則應用合適的 blob 類型欄位
資料從 圖片檔案 讀取或攔截php的輸出
用 bin2hex 函數轉換成字串,在前面加 ‘0x'

假定 $dst_r 是 image 資源
imagegif($dst_r); 就是輸出圖片資料流
imagegif($dst_r, '圖片檔案名稱'); 就是儲存到檔案

資料庫儲存圖片檔案名稱即可
如果資料庫要儲存圖片資料,則應用合適的 blob 類型欄位
資料從 圖片檔案 讀取或攔截php的輸出
用 bin2hex 函數轉換成字串,在前面加 ‘0x'



謝謝啊,怎麼做到讓它不輸出圖片流呢(輸出圖片流為的就是儲存成新檔案名稱),直接儲存到檔案夾,然後更新資料庫呢?
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.