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


147

我正在寻找一种使用JavaScript调整图像客户端大小的方法(真正调整大小,而不仅仅是更改宽度和高度)。
我知道可以在Flash中进行此操作,但如果可能的话,我想避免这样做。

网络上是否有任何开源算法?


对于仍然想知道答案的人,可以做到这一点,但是您需要对图像处理进行一些ajax调用。
多面体

1
“需要制造”吗?那么,您毕竟可以在服务器上解决它,并通过AJAX调用透明地获取数据。但是,整个尝试都是在客户端进行,正如Jeremy指出的那样,可以做到。我认为这是一个很好的例子:github.com/rossturner/HTML5-ImageUploader
Bart

2
在最新版本中,Dropzone.js支持在上传之前调整客户端图像的大小。
user1666456

Answers:


111

这是执行此操作的要点: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>

它包括许多支持检测和polyfill,以确保它在我能管理的尽可能多的浏览器上运行。

(它也会忽略gif图像-如果它们是动画的)


2
我觉得您对此还没有获得足够的赞赏-我认为它很棒,而且非常容易。感谢分享!
马特2015年

4
嗯..我在这方面取得了不错的成功,但是我发现我的图像(除了调整大小)还遭受了质量的巨大损失(严重像素化),尽管它以正确的分辨率输出。
鲁宾·马丁内斯(Ruben Martinez)2015年

1
嗨,我需要一个像这样使用的代码段,而且我认为这很好。文件为“ blob”)document.getElementById('preview')。src = window.URL.createObjectURL(blob); //您现在也可以使用XHR上传该Blob。我有一个问题..我如何只提交表单就可以在表单中发送此图像。我的意思是,就像由“提交”按钮触发的发帖请求一样。你知道,通常的方式。谢谢您的要旨!
iedmrc's

3
对于具有质量(重采样)损失任何人,更新画布上下文设定imageSmoothingEnabled为TRUE;和imageSmoothingQualityhigh。在打字稿中,该块看起来像: const ctx = canvas.getContext('2d'); ctx.imageSmoothingEnabled = true; (ctx as any).imageSmoothingQuality = 'high'; ctx.drawImage(image, 0, 0, width, height);
Sean Perkins

1
是否有可能使它成为npm软件包?会很棒!
erksch


12

如果您在上载之前要调整大小,我只是发现了这个 http://www.plupload.com/

它以任何可以想象的方法为您解决所有难题。

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

我只是尝试了一下,它与我的android一起工作了!

我在Flash 中使用的是http://swfupload.org/,效果很好,但调整大小的尺寸很小。(无法记住该限制),并且当Flash不可用时不会返回html4。


44
当用户尝试上传10mb的照片(仅存储为小得多的照片)时,最好对客户端进行大小调整。这样可以更快地上传。
凯尔

同样的情况,只要您输入了文件,并且用户使用了智能手机并使用相机拍摄了图像,那么在现代智能手机上,图像大小约为10 mb。如果您在服务器端无论如何都在调整其大小并仅存储它的较小版本,则可以在客户端中预先进行调整大小时节省大量蜂窝数据和加载时间。
亚历克斯(Alex)

1
请小心,因为plupload是AGPL。
亚历克斯(Alex)

11

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

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

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

6

也许带有canvas标签(尽管它不是便携式的)。有一个关于如何旋转用帆布图像博客在这里,我想如果你可以旋转它,你可以调整它的大小。也许这可以作为一个起点。

另请参见此库


2
非常有用的例子。您可能想在答案中添加一两个片段,以防这些链接中断。
Trevor 2014年

4

在将图像上传到服务器之前,可以使用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>


这看起来弗里金很棒!
pimbrouwers

2

是的,对于现代浏览器,这是完全可行的。甚至可以将文件专门作为二进制文件上传,完成了许多画布更改。

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);

如果您担心Vitaly的观点,您可以尝试在正在使用的jfiddle上进行一些裁剪和调整大小。


0

以我的经验,此示例是上传已调整大小的图片的最佳解决方案: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的支持,我也正在对此进行努力。虽然上面的链接中有信息。对于这两个问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.