在上传到服务器之前使用 JavaScript 调整客户端的图像大小

我正在寻找一种方法来调整图像客户端与 JavaScript (真正的调整大小,而不只是改变宽度和高度)。
我知道这是可能的,在 Flash 中做到这一点,但我想避免它,如果可能的话。

网络上有没有什么开源算法?

196809 次浏览

也许可以使用画布标签(尽管它不可移植)。有一个博客关于如何旋转画布 给你的图像,我想如果你可以旋转它,你可以调整它的大小。也许这是个起点。

另见 这个图书馆

这个问题的答案是肯定的——在 HTML5中,您可以使用画布元素在客户端调整图像的大小。您还可以获取新数据并将其发送到服务器。看看这个教程:

Http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/

如果你在上传之前调整大小,我刚刚发现这个 http://www.plupload.com/

它能用任何你能想到的方法为你施展魔法。

不幸的是,只有 Mozilla 浏览器支持 HTML5调整大小,但是您可以将其他浏览器重定向到 Flash 和 Silverlight。

我刚试过了,我的机器人也能用!

我使用的是 http://swfupload.org/在闪光灯下,它做的工作非常好,但调整大小是非常小的。(不能记住的限制) ,并不会回到 html4时,闪光灯是不可用的。

这里有一个要点,做到这一点: Https://gist.github.com/dcollien/312bce1270a5f511bf4a

(一个 es6版本,一个.js 版本,可以包含在脚本标记中)

你可以这样使用:

<input type="file" id="select">
<img id="preview">
<script>
document.getElementById('select').onchange = function(evt) {
ImageTools.resize(this.files[0], {
width: 320, // maximum width
height: 240 // maximum height
}, function(blob, didItResize) {
// didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
document.getElementById('preview').src = window.URL.createObjectURL(blob);
// you can also now upload this blob using an XHR.
});
};
</script>

它包括一系列的支持检测和填充,以确保它可以在尽可能多的浏览器上工作。

(它还忽略了 gif 图像——以防它们是动画图像)

Http://nodeca.github.io/pica/demo/

在现代浏览器中,您可以使用画布来加载/保存图像数据。但是,如果你要调整客户端的图像大小,你应该记住以下几点:

  1. 每个通道只有8位(jpeg 可以有更好的动态范围,大约12位)。如果你不上传专业照片,这应该不是一个问题。
  2. 调整算法时要小心。大多数客户端调整器使用简单的数学运算,结果比实际情况更糟糕。
  3. 你可能需要锐化缩放图像。
  4. 如果您希望重用元数据(exif 和其他)从原来-不要忘记剥夺颜色配置文件信息。因为它是在你将图像加载到画布时应用的。

是的,对于现代浏览器来说,这是完全可行的。甚至可以上传文件,特别是作为一个二进制文件已经完成了任何数量的画布修改点。

Http://jsfiddle.net/bo40drmv/

(这个答案是对公认答案 给你的改进)

请记住,在 PHP 中使用类似于下面的内容来捕获结果提交过程:

//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);

如果有人担心维塔利的观点,你可以尝试一些裁剪和调整大小的工作 jfiddle。

在将图像上传到服务器之前,可以使用 javascript 图像处理框架进行客户端图像处理。

下面我使用 马文根据下面的示例创建了一个可运行的代码: “在将图像上传到服务器之前在客户端处理图像”

基本上,我使用 Marvin Scale (...)方法来调整图像的大小。然后,我将图像作为 blob (使用方法 ToBlob ())上传。服务器回答提供接收到的图像的 URL。

/***********************************************
* GLOBAL VARS
**********************************************/
var image = new MarvinImage();


/***********************************************
* FILE CHOOSER AND UPLOAD
**********************************************/
$('#fileUpload').change(function (event) {
form = new FormData();
form.append('name', event.target.files[0].name);
	

reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
	

reader.onload = function(){
image.load(reader.result, imageLoaded);
};
	

});


function resizeAndSendToServer(){
$("#divServerResponse").html("uploading...");
$.ajax({
method: 'POST',
url: 'https://www.marvinj.org/backoffice/imageUpload.php',
data: form,
enctype: 'multipart/form-data',
contentType: false,
processData: false,
		

	   

success: function (resp) {
$("#divServerResponse").html("SERVER RESPONSE (NEW IMAGE):<br/><img src='"+resp+"' style='max-width:400px'></img>");
},
error: function (data) {
console.log("error:"+error);
console.log(data);
},
		

});
};


/***********************************************
* IMAGE MANIPULATION
**********************************************/
function imageLoaded(){
Marvin.scale(image.clone(), image, 120);
form.append("blob", image.toBlob());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<form id="form" action='/backoffice/imageUpload.php' style='margin:auto;' method='post' enctype='multipart/form-data'>
<input type='file' id='fileUpload' class='upload' name='userfile'/>
</form><br/>
<button type="button" onclick="resizeAndSendToServer()">Resize and Send to Server</button><br/><br/>
<div id="divServerResponse">
</div>

根据我的经验,这个示例是上传调整大小的图片的最佳解决方案: https://zocada.com/compress-resize-images-javascript-browser/

它使用了 HTML5 Canvas 特性。

代码就是这么“简单”:

compress(e) {
const fileName = e.target.files[0].name;
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onload = event => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const elem = document.createElement('canvas');
const width = Math.min(800, img.width);
const scaleFactor = width / img.width;
elem.width = width;
elem.height = img.height * scaleFactor;


const ctx = elem.getContext('2d');
// img.width and img.height will contain the original dimensions
ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
ctx.canvas.toBlob((blob) => {
const file = new File([blob], fileName, {
type: 'image/jpeg',
lastModified: Date.now()
});
}, 'image/jpeg', 1);
},
reader.onerror = error => console.log(error);
};
}

这种解决方案有两个缺点。

第一个与图像旋转有关,因为忽略了 EXIF 数据。我无法解决这个问题,在我的用例中也没有那么重要,但是很高兴听到任何反馈。

第二个缺点是缺乏对 IE/Edge 的支持(尽管不是基于 Chrome 的版本) ,我不会在这个问题上花时间。