【发布时间】:2014-08-17 06:51:45
【问题描述】:
我正在尝试为更大的图像创建缩略图。我正在使用Jcrop 来获取裁剪的坐标,但我无法将其转换为正确裁剪的缩略图。我已经正确设置了 Jcrop,它通过 x-y 坐标以及框的大小发送,但我不知道如何从中裁剪。
我拥有的是服务器上图像的路径,以及它们创建的方形框的 4 个坐标和宽度和高度(我已将纵横比锁定为 1:1,因为我想要方形缩略图)。然后我通过 Ajax 将它发送到我的 PHP 裁剪脚本,但我无法让它根据设置来裁剪。
这是我目前所拥有的:
public function Crop($file, $crop) {
$height = $width = 180;
$ratio = $width / $height;
$pos = strrpos($file, '.');
$name = substr($file, 0, $pos);
$ext = strtolower(substr($file, $pos));
if( ! in_array($ext, array('.gif', '.jpg', '.jpeg', '.png'))) {
return 'INVALID_EXT';
}
// When loading the image we check to see if the first character in file is a slash, and if so remove it as the last character of root is a slash.
$src = ROOT . (in_array(substr($file, 0, 1), array('/', '\\')) ? substr($file, 1) : $file);
$srcRes = imagecreatefromstring(file_get_contents($src));
if( ! $srcRes) {
return 'INVALID_FILE';
}
$srcWidth = imagesx($srcRes);
$srcHeight = imagesy($srcRes);
$srcRatio = $srcWidth / $srcHeight;
$dstRes = imagecreatetruecolor($crop['w'], $crop['h']);
if($ext == '.gif') {
$dstBg = imagecolorallocate($dstRes, 0, 0, 0);
imagecolortransparent($dstRes, $dstBg);
} elseif($ext == '.png') {
$dstBg = imagecolorallocate($dstRes, 0, 0, 0);
imagecolortransparent($dstRes, $dstBg);
imagealphablending($dstRes, FALSE);
imagesavealpha($dstRes, TRUE);
}
$srcX = 0;
$srcY = 0;
if($srcRatio > $ratio) {
$tmpWidth = $srcHeight * $ratio;
$tmpHeight = $srcHeight;
$srcX = ($srcWidth - $tmpWidth) / 2;
$srcY = 0;
} else {
$tmpWidth = $srcWidth;
$tmpHeight = $srcWidth / $ratio;
$srcX = 0;
$srcY = ($srcHeight - $tmpHeight) / 2;
}
imagecopyresampled($dstRes, $srcRes, 0, 0, $crop['x'], $crop['y'], $crop['w'], $crop['h'], $tmpWidth, $tmpHeight);
$dst = ROOT . (in_array(substr($name, 0, 1), array('/', '\\')) ? substr($name, 1) : $name) . '-thumb' . $ext;
if($ext == '.gif') {
$try = imagegif($dstRes, $dst);
} elseif($ext == '.jpg' || $ext == '.jpeg') {
$try = imagejpeg($dstRes, $dst, 80);
} elseif($ext == '.png') {
$try = imagepng($newThumbImageResource, $dst);
}
if( ! $try) {
return 'CREATE_ERR';
}
return 'SUCCESS';
}
我已尝试更改 imagecopyresampled 中的各种内容,但无法按照 Jcrop 发送的内容对其进行裁剪。如果我使用$srcWidth 和$srcHeight,它会保持原始图像的纵横比并将其压缩到 180px 的正方形中。但它似乎没有调整它的大小或从正确的位置裁剪它。
谁能帮我弄清楚我应该在哪里使用哪些数字?我整天都在用头撞这个。
编辑
这是其余的代码。首先是运行 JCrop 的 JavaScript。它在 Ajax 文件上传后触发以创建该图像的缩略图:
这是最后调用cropper的Ajax函数上传。
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = '/eshop/library/ajax/ajax.file-upload.php';
var uploadDir = 'prodimages/';
$('.listing-image').fileupload({
url: url,
dataType: 'json',
autoUpload: true,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 1000000, // 1 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 120,
previewMaxHeight: 120,
previewCrop: true,
paramName: 'files[]',
formData: {uploadDir: uploadDir}
})/*.on('fileuploadprocessalways', function (e, data) {
var index = data.index;
var file = data.files[index];
$(this).html(file.preview);
})*/.on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.listing-progress', this).css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
var file = data.result.files[0];
var html = '<div class="listing-preview">\
<img src="' + file.thumbnailUrl + '" data-name="' + file.name + '">\
<div class="listing-preview-delete">Delete</div>\
</div>';
$(this).html(html).data('delete-url', file.deleteUrl).css('padding', 0);
Crop('/' + uploadDir + file.name, $(this).prop('id'));
});
});
这会通过 Ajax 将裁剪细节发送到上面的 PHP 脚本。
$(document).on('click', '.crop-btn', function() {
var data = {
file: $(this).data('src'),
crop: jcrop.tellSelect()
}
ShowLoadingById('crop-loading');
AjaxHandler('/eshop/library/ajax/ajax.product-crop-thumb.php', data, 'POST', true);
});
裁剪窗口是一个灯箱,此功能将其垂直居中并在图像垂直大于可用空间时调整图像大小。
function CentreCrop() {
var m = ($(window).height() - ($('.crop > div').height() + 60)) / 2;
$('.crop > div').css('margin-top', m);
if($('#crop-img').height() > $('.crop > div').height() - 30) {
$('#crop-img-container').height($('.crop > div').height() - 30);
}
}
这是存储要裁剪的文件并在工作程序未运行时调用的初始函数。
var toBeCropped = [];
var working = false;
function Crop(file, id) {
toBeCropped.push({path: file, id: id});
if( ! working) {
working = true;
CropWorker();
}
}
这是我在裁剪完成后运行的函数,用于销毁 jcrop 并清除裁剪灯箱,为下一张要裁剪的图像做好准备。
function CropSuccess() {
$('.crop').fadeOut(250, function() {
jcrop.destroy();
$(this).html('');
CropWorker();
});
}
这是实际在灯箱中创建内容并启动 jcrop 的工作人员。
function CropWorker() {
if(toBeCropped.length > 0) {
file = toBeCropped.shift();
html = '<div>\
<div id="crop-img-container" class="row-fluid">\
<img id="crop-img" src="' + file.path + '">\
</div>\
<div class="row-fluid">\
<div class="span3 offset9">\
<button class="span12 btn crop-btn" data-id="' + file.id + '" data-src="' + file.path + '">Create Thumb</button>\
</div>\
</div>\
<div class="row-fluid loading-screen" id="crop-loading">\
<div>\
<h4>Cropping...</h4>\
<img src="/img/loading.gif">\
</div>\
</div>\
</div>';
$('.crop').html(html);
$('.crop').fadeIn(250);
$('#crop-img').load(function() {
CentreCrop();
$('#crop-img').Jcrop({
aspectRatio: 1/1,
bgColor: 'black',
bgOpacity: 0.4,
boxWidth: $('#crop-img').width(), // Only just recently added boxWidth and height to see if that would fix it, no difference with or without.
boxHeight: $('#crop-img').height(),
//maxSize: [300,300],
minSize: [180,180]
}, function() {
jcrop = this;
jcrop.setSelect([0,0,180,180]);
});
});
} else {
working = false;
}
}
更新
部分问题似乎是图像大小调整。我正在更改图像大小以适应屏幕,虽然 JCrop 会为我处理这个问题,但似乎你必须告诉 JCrop 图像的原始尺寸。我在初始化 JCrop 时添加了真实大小选项,看起来我们快到了。
对于较小的图像,1000 像素以下的裁剪器似乎工作得很好。但是对于较大的(1000px +),它会产生黑色图像。当我将它与 JCrop 演示脚本一起使用时,它不会这样做,但两者之间的唯一区别是一个是将文件输出到屏幕,另一个是保存它。我看不出任何其他差异,也不知道为什么会发生这种情况。
更新 2 如果我通过 Ajax 运行代码,它似乎只会受到影响。如果我运行完全相同的功能,只是发布到页面并在顶部运行它,那么无论原始图像的大小或我绘制的框的大小如何,每次都会完美地创建缩略图。
【问题讨论】: