2016-02-24 133 views
2

我使用的裁剪工具,可以在这里找到:https://github.com/sconsult/croppicPHP上传导致图像模糊

我已经修改了它适合我的需要 - 对代码的数量道歉,但我不知道它的哪一部分可能会引起问题。

我第一次在5 - 6个月前实现了这个代码,它的工作完美无瑕。 85%的质量适合每个测试图像。 代码没有改变,因为它的原始实现,但图像出现非常明显模糊 - 他们只是不再看起来不错。我测试过以前上传过的相同图像进行比较,它们看起来与最初上传和裁剪的图像不一样。

我知道的唯一可能会影响到的主要事件是升级版本PHP。我相信它在执行时曾经是5.3xx或类似的,现在我们正在运行5.6.18。什么可能导致模糊? 5.6.185.3有什么明显的变化可以归因于此?

请注意,我试图改变$jpeg_quality = 85; 。不幸的是,所有这些都会增加文件的大小。同样的模糊发生。

<?php 
$image = $_POST['imgUrl']; 
// original sizes 
$img_init_w = $_POST['imgInitW']; 
$img_init_h = $_POST['imgInitH']; 
// resized sizes 
$img_w = $_POST['imgW']; 
$img_h = $_POST['imgH']; 
// offsets 
$imgY1 = $_POST['imgY1']; 
$imgX1 = $_POST['imgX1']; 
// crop box 
$cropW = $_POST['cropW']; 
$cropH = $_POST['cropH']; 
// rotation angle 
$angle = $_POST['rotation']; 

$id = $_POST['id']; 
$dtormob = $_POST['dtormob']; 

$jpeg_quality = 85; 



$original_filename = "../../..".WEB_ROOT."lib/img/$id-original"; 


// different filenames depending on whether this is for mobile or desktop 
switch ($dtormob) 
{ 
    case 'dt': 
     $cropped_lrg_filename = "../../..".WEB_ROOT."lib/img/$id-lrg-w"; // 1440 x 568 
     $cropped_sml_filename = "../../..".WEB_ROOT."lib/img/$id-med-w"; // 767 x 302 

     $lrg_resized_w = 1440; 
     $lrg_resized_h = 568; 

     $sml_resized_w = 767; 
     $sml_resized_h = 302; 
     break; 

    case 'mob': 
     $cropped_lrg_filename = "../../..".WEB_ROOT."lib/img/$id-med-s"; // 767 x 607 
     $cropped_sml_filename = "../../..".WEB_ROOT."lib/img/$id-sml-s"; // 480 x 380 

     $lrg_resized_w = 767; 
     $lrg_resized_h = 607; 

     $sml_resized_w = 480; 
     $sml_resized_h = 380; 
     break; 
} 



$what = getimagesize($image); 

switch(strtolower($what['mime'])) 
{ 
    case 'image/png': 
     $img_r = imagecreatefrompng($image); 
     $source_image = imagecreatefrompng($image); 
     $type = '.png'; 
     break; 
    case 'image/jpeg': 
     $img_r = imagecreatefromjpeg($image); 
     $source_image = imagecreatefromjpeg($image); 
     error_log('jpg'); 
     $type = '.jpeg'; 
     break; 
    case 'image/gif': 
     $img_r = imagecreatefromgif($image); 
     $source_image = imagecreatefromgif($image); 
     $type = '.gif'; 
     break; 
    default: die('image type not supported'); 
} 


// Error checking 
if (!is_writable(dirname($cropped_lrg_filename))) { 
    $response = array(
     'status' => 'error', 
     'message' => "Can't write cropped File, directory inaccesible" 
    ); 
} 
else if ($what[0] > 2000 || $what[1] > 2000) { 
    $response = array(
     'status' => 'error', 
     'message' => '<strong>Image too large</strong>, please upload an image <strong>2000 x 2000px</strong> or less.<br /><em>(No smaller than '.$lrg_resized_w.' x '.$lrg_resized_h.'px)</em>' 
    ); 
} 
else if ($what[0] < $lrg_resized_w || $what[1] < $lrg_resized_h) { 
    $response = array(
     'status' => 'error', 
     'message' => '<strong>Image too small</strong>, please upload an image <strong>'.$lrg_resized_w.' x '.$lrg_resized_h.'px</strong> or more.<br /><em>(No bigger than 2000 x 2000px)</em>' 
    ); 
} 
else if ($what['channels'] > 3) { 
    $response = array(
     'status' => 'error', 
     'message' => '<strong>Image format error</strong>, this image is in CMYK format, please convert it to <strong>RGB</strong> first.' 
    ); 
} 
else 
{ 
    $original_filename_absolute = PROTOCOL.SUB_DOMAIN.DOMAIN.str_replace('../../..', '', $original_filename).$type; 
    $cropped_lrg_filename_absolute = PROTOCOL.SUB_DOMAIN.DOMAIN.str_replace('../../..', '', $cropped_lrg_filename).$type; 
    $cropped_sml_filename_absolute = PROTOCOL.SUB_DOMAIN.DOMAIN.str_replace('../../..', '', $cropped_sml_filename).$type; 

    // remove any images that already exist 
    if (file_exists($original_filename.$type)) { 
     unlink($original_filename.$type); 
    } 
    if (file_exists($cropped_lrg_filename.$type)) { 
     unlink($cropped_lrg_filename.$type); 
    } 
    if (file_exists($cropped_sml_filename.$type)) { 
     unlink($cropped_sml_filename.$type); 
    } 


    // lets make a copy of the original 
    // ==================================================================================== 
    $original_img = imagecreatetruecolor($img_init_w, $img_init_h); 
    imagecopyresampled($original_img, $source_image, 0, 0, 0, 0, $img_init_w, $img_init_h, $img_init_w, $img_init_h); 
    imagejpeg($original_img, $original_filename.$type, 100); 




    // create large crop first - then resize after as it should be the same aspect ratio 
    // ==================================================================================== 
    // resize the original image to size of editor 
    $lrg_resized_image = imagecreatetruecolor($img_w, $img_h); 
    imagecopyresampled($lrg_resized_image, $source_image, 0, 0, 0, 0, $img_w, $img_h, $img_init_w, $img_init_h); 

    // rotate the rezized image 
    $rotated_image = imagerotate($lrg_resized_image, -$angle, 0); 

    // find new width & height of rotated image 
    $rotated_width = imagesx($rotated_image); 
    $rotated_height = imagesy($rotated_image); 

    // diff between rotated & original sizes 
    $dx = $rotated_width - $img_w; 
    $dy = $rotated_height - $img_h; 

    // crop rotated image to fit into original rezized rectangle 
    $cropped_rotated_image = imagecreatetruecolor($img_w, $img_h); 
    imagecolortransparent($cropped_rotated_image, imagecolorallocate($cropped_rotated_image, 0, 0, 0)); 
    imagecopyresampled($cropped_rotated_image, $rotated_image, 0, 0, $dx/2, $dy/2, $img_w, $img_h, $img_w, $img_h); 

    // crop image into selected area 
    $final_image = imagecreatetruecolor($cropW, $cropH); 
    imagecolortransparent($final_image, imagecolorallocate($final_image, 0, 0, 0)); 
    imagecopyresampled($final_image, $cropped_rotated_image, 0, 0, $imgX1, $imgY1, $cropW, $cropH, $cropW, $cropH); 

    // finally output image 
    imagejpeg($final_image, $cropped_lrg_filename.$type, $jpeg_quality); 







    // now create smaller crop - same aspect ratio just smaller 
    // ==================================================================================== 
    $sml_resized_image = imagecreatetruecolor($sml_resized_w, $sml_resized_h); 
    imagecopyresampled($sml_resized_image, $final_image, 0, 0, 0, 0, $sml_resized_w, $sml_resized_h, $cropW, $cropH); 
    // save it 
    imagejpeg($sml_resized_image, $cropped_sml_filename.$type, $jpeg_quality); 




    $response = array(
     'status' => 'success', 
     'url' => $cropped_lrg_filename.$type 
    ); 
} 
echo json_encode($response); 

UPDATE

下面是2的示例图像,所述第一被调整大小后的版本(质量差,但设定为100%JPEG画质输出),第二个是原始图像。看看墙上的石头,质量的下降非常明显。

裁剪

enter image description here

enter image description here

回答

1

问题是imagerotate()功能。即使没有应用旋转,我的脚本也被告知要旋转图像。这导致图像质量下降。我修改了脚本以读取;

$rotated_image = $angle == 0 ? $lrg_resized_image : imagerotate($lrg_resized_image, -$angle, 0); 

这里还有轻微的未知数,为什么这开始发生,当它是不是一个问题之前,另外如果我做旋转图像,它仍然不是很大,但幸运的是这种使用这种情况不太可能需要。

感谢Golden_flash帮我调试这个

+1

通过这篇文章了解了很多 –

0

添加

imageconvolution($original_img,array(array(-1,-1,-1),array(-1,16,-1),array(-1,-1,-1)),8,0); 

imagecopyresample后imagejpeg

Imageconvolution之前用于此锐化图像

+0

但这小幅增加清晰度,但是还是有图像的可见的降解。这至少告诉我,它不仅仅是模糊的......图像失去了很多细节。我已经更新了我的问题以示例。这个例子是使用你的调整,没有它,图像有点恶化。 – Novocaine

+0

图像质量下降的原因可能是由于通过imagecopyresampled制作大量副本,尝试在每次调用imagecopyresampled后添加imageconvolution。可以告诉我您通过代码实现的目标,以便我们可以减少一些代码? –

+0

这个过程是; 1图像被选择为通过允许旋转,缩放和拖拽以适合裁剪框的界面来上传,它指示这是用于桌面还是移动Uplon上传。然后,我需要以两种不同的分辨率(无论是移动还是台式机,它们只是具有不同的分辨率标准)以完整质量和裁剪版保存原件。除了一些基本的错误检查就是这样。我现在试试你的建议。 – Novocaine