提问人:geraud 提问时间:3/13/2010 最后编辑:Adrianogeraud 更新时间:11/11/2020 访问量:200793
在上传到服务器之前,使用 JavaScript 调整客户端图像大小
Image resizing client-side with JavaScript before upload to the server
问:
我正在寻找一种使用 JavaScript 在客户端调整图像大小的方法(真正调整大小,而不仅仅是更改宽度和高度)。
我知道在Flash中可以做到这一点,但如果可能的话,我想避免它。
网络上有没有开源算法?
答:
也许带有 canvas 标签(尽管它不是便携式的)。这里有一个关于如何使用画布旋转图像的博客,我想如果你可以旋转它,你可以调整它的大小。也许它可以成为一个起点。
另请参阅此库。
评论
答案是肯定的 - 在 HTML 5 中,您可以使用 canvas 元素在客户端调整图像大小。您还可以获取新数据并将其发送到服务器。请参阅此教程:
http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
评论
如果您在上传之前调整大小,我刚刚发现了这个 http://www.plupload.com/
它以任何可以想象的方法为您完成所有魔术。
不幸的是,Mozilla浏览器仅支持HTML5调整大小,但您可以将其他浏览器重定向到Flash和Silverlight。
我刚刚尝试过,它适用于我的 android!
我在闪存中使用 http://swfupload.org/,它做得很好,但调整大小非常小。(不记得限制),并且在 Flash 不可用时不会返回 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>
它包括一堆支持检测和 polyfills,以确保它可以在我能管理的尽可能多的浏览器上运行。
(它还会忽略 GIF 图像 - 以防它们被动画化)
评论
imageSmoothingEnabled
imageSmoothingQuality
high
const ctx = canvas.getContext('2d'); ctx.imageSmoothingEnabled = true; (ctx as any).imageSmoothingQuality = 'high'; ctx.drawImage(image, 0, 0, width, height);
http://nodeca.github.io/pica/demo/
在现代浏览器中,您可以使用画布来加载/保存图像数据。但是,如果您在客户端上调整图像大小,您应该记住几件事:
- 每个通道只有 8 位(jpeg 可以有更好的动态范围,大约 12 位)。如果您不上传专业照片,那应该不是问题。
- 注意调整大小算法。大多数客户端调整器都使用琐碎的数学运算,结果比可能更糟糕。
- 您可能需要锐化缩小的图像。
- 如果您愿意,请重用原始元数据(exif 和其他) - 不要忘记剥离颜色配置文件信息。因为它是在将图像加载到画布时应用的。
是的,使用现代浏览器,这是完全可行的。甚至可以将文件专门上传为二进制文件,并进行了任意数量的画布更改。
(这个答案是对这里接受的答案的改进)
请记住,在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);
如果有人担心 Vitaly 的观点,您可以尝试在工作 jfiddle 上进行一些裁剪和调整大小。
在将图像上传到服务器之前,您可以使用 javascript 图像处理框架进行客户端图像处理。
下面我使用 MarvinJ 根据以下页面中的示例创建了一个可运行的代码:“在将图像上传到服务器之前在客户端处理图像”
基本上,我使用Marvin.scale(...)方法来调整图像大小。然后,我将图像上传为 blob(使用方法 image.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 的版本),我不会花时间在上面。
评论