JCrop 和 PHP GD return 带有黑条的图像

JCrop and PHP GD return an image with a black bar

请帮帮我,这让我抓狂。

所以我正在使用最新版本的 JCrop 以及最新版本的 JQuery。

我的目标是允许用户上传大于 550x550 像素的图像,然后选择不大于 550x825 像素的方形或纵向选区。

我的实施是将上传的图像调整为 550x550+ 或 550+x550 的文件,具体取决于原始上传的 x 或 y 是否较大。 新图像存储在我的服务器上时,此代码工作得很好。

我遇到的问题是,除非裁剪选择的起始坐标为 [0,0],否则调用裁剪代码时返回的图像将向上移动,看起来与开始坐标成比例,而图像的其余部分将是黑色 space。 我试图包含图像来演示,但不允许,因为我对这个网站还是新手。 我会尝试用文字来证明。 当使用 [0,0] 的起始坐标裁剪尺寸为 [550, 828] 的图像时,裁剪成功。 当用从大约 [0, 100] 开始的坐标裁剪同一图像时,裁剪不成功。选区显示 ~90%,向上移动 ~10%,其余 ~10% 为黑色 当用从大约 [0, 278] 开始的坐标裁剪同一图像时,裁剪不成功。选区显示了 ~50%,向上移动了 ~50%,剩下的 ~50% 是黑色

此外,我检查了 JCrop 返回的坐标,它们是正确的。

这是我用来初始化 JCrop 的 Javascript var TARGET_W = 550; var TARGET_H = 825; // 更改裁剪的照片源 jQuery('#cropbox').attr('src', url[1]);

// Initialize the Jcrop using the TARGET_W and TARGET_H that initialized before
jQuery('#cropbox').Jcrop({
     minSize : [TARGET_W, TARGET_W ],
     maxSize : [TARGET_W, TARGET_H ],
     setSelect: [TARGET_W, TARGET_W, 0, 0],
     onSelect: updateCoords
});

// store the current uploaded photo url in a hidden input to use it later
jQuery('#photo_url').val(url[0]);
jQuery('#photo_src').val(url[1]);

这是将坐标发送到 PHP

的 Javascript 函数
function crop_photo() {
//declare co-ords
var x_ = jQuery('#x').val();
var y_ = jQuery('#y').val();
var w_ = jQuery('#w').val();
var h_ = jQuery('#h').val();
var photo_url_ = jQuery('#photo_url').val();
var photo_src_ = jQuery('#photo_src').val();

// crop photo with a php file using ajax call
jQuery.ajax({
    url: ajaxurl,
    type: 'POST',
    data: {x:x_, y:y_, w:w_, h:h_, photo_url:photo_url_, photo_src:photo_src_},
    success:function(data){
        // display the croped photo
        d = new Date();
        jQuery("#featured-image-preview").attr("src", photo_src_ + "?timestamp=" + d.getTime());
        jQuery('#featured_image').val(photo_src_);
        jQuery('#featured_image_src').val(photo_url_);

        jQuery('#recipe-details-form').show(500);   
        if (jQuery('#cropbox').data('Jcrop')) {
            jQuery('#cropbox').data('Jcrop').destroy();
            jQuery('#cropbox').removeAttr('style');
            jQuery('#cropbox').removeAttr('src');
        }
        jQuery('.loading_progress_final').html('');
    }
});

这是我的PHP作物

//CROP IMAGE
if(isset($_POST['photo_url']) && !empty($_POST['photo_url'])) {
// quality
$jpeg_quality = 90;
$png_quality = 9;
// photo path
$src = $_POST['photo_url'];
$split_name = explode('.',$src);
if ($split_name[1] == 'jpg'){
    // create new jpeg image based on the target sizes
    $img_r = imagecreatefromjpeg($src);
    $dst_r = imagecreatetruecolor($_POST['w'], $_POST['h']);
    // crop photo   
    imagecopyresampled($dst_r,$img_r,0,0, (int)$_POST['x'], (int)$_POST['y'], (int)$_POST['w'], (int)$_POST['h'], (int)$_POST['w'], (int)$_POST['h']);
    // create the physical photo
    header('Content-type: image/jpeg');
    imagejpeg($dst_r,$src,$jpeg_quality);
}
else if ($split_name[1] == 'png') {
    // create new jpeg image based on the target sizes
    $img_r = imagecreatefrompng($src);
    $dst_r = ImageCreateTrueColor( (int)$_POST['w'], (int)$_POST['h'] );
    // crop photo
    imagecopyresampled($dst_r,$img_r,0,0, (int)$_POST['x'], (int)$_POST['y'], (int)$_POST['w'], (int)$_POST['h'], (int)$_POST['w'], (int)$_POST['h']);
    // create the physical photo
    imagepng($dst_r,$src,$png_quality);
}

//$src = resize_image($src, 550);
return $_POST['photo_src'];

我使用标准的 vanilla Jcrop CSS 除了以下

.jcrop-holder img,
img.jcrop-preview,
.crop-wrapper img,
{
    max-width: none !important;
    max-height: none !important;
}
.jcrop-holder {
    display: inline-block;
    max-width: none !important;
    max-height: none !important;
}

这是因为当最大宽度设置为 100% 时,预览图像真的被拉伸了,不能轻易地显示在屏幕上以供用户裁剪。

我已经查看我的代码 100 遍了,但没有发现任何明显的错误。就像我提到的,当从 [0,0] 裁剪图像时,它工作得很好。是否可能是 CSS 问题导致 JCr​​op 返回的坐标不准确,即使这些值看起来正确?

您可能想看看 imagecopyresampled http://php.net/manual/en/function.imagecopyresampled.php

如果您从 gif 和 png 创建,您可能需要额外的选项,例如 colorallocate

想法是调整图像大小并用正确的像素填充该图像,这样 gd 就不需要用黑色像素(黑条)来完成图像。

希望对您有所帮助。

不管怎样,我设法解决了我自己的问题。

问题是,当我使用 imagejpeg/imagepng 输出最终文件时,我覆盖了原始文件。我将输出更改为类似 $src + '_cropped' 的内容,现在它工作正常。

我真的不明白为什么这是个问题。但无论如何,它有效。