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

发布于 2024-08-24 13:11:38 字数 119 浏览 3 评论 0原文

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

网络上有开源算法吗?

I am looking for a way to resize an image client-side with JavaScript (really resize, not just change width and height).
I know it's possible to do it in Flash but I would like to avoid it if possible.

Is there any open source algorithm somewhere on the web?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一腔孤↑勇 2024-08-31 13:11:38

这是执行此操作的要点:
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 图像 - 如果它们是动画的)

Here's a gist which does this:
https://gist.github.com/dcollien/312bce1270a5f511bf4a

(an es6 version, and a .js version which can be included in a script tag)

You can use it as follows:

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

It includes a bunch of support detection and polyfills to make sure it works on as many browsers as I could manage.

(it also ignores gif images - in case they're animated)

涫野音 2024-08-31 13:11:38

答案是肯定的 - 在 HTML 5 中,您可以使用 canvas 元素在客户端调整图像大小。您还可以获取新数据并将其发送到服务器。请参阅本教程:

http://hacks.mozilla.org/2011 /01/如何开发-html5-image-uploader/

The answer to this is yes - in HTML 5 you can resize images client-side using the canvas element. You can also take the new data and send it to a server. See this tutorial:

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

⒈起吃苦の倖褔 2024-08-31 13:11:38

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

它确实以任何可以想象的方式为您提供所有魔力。

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

我刚刚尝试了一下,它可以在我的 Android 上运行!

我在Flash中使用http://swfupload.org/,它做得很好,但是调整大小非常小。 (不记得限制)并且当flash不可用时不会返回到html4。

If you were resizing before uploading I just found out this http://www.plupload.com/

It does all the magic for you in any imaginable method.

Unfortunately HTML5 resize only is supported with Mozilla browser, but you can redirect other browsers to Flash and Silverlight.

I just tried it and it worked with my android!

I was using http://swfupload.org/ in flash, it does the job very well, but the resize size is very small. (cannot remember the limit) and does not go back to html4 when flash is not available.

半窗疏影 2024-08-31 13:11:38

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

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

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

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

In modern browser you can use canvas to load/save image data. But you should keep in mind several things if you resize image on the client:

  1. You will have only 8bits per channel (jpeg can have better dynamic range, about 12 bits). If you don't upload professional photos, that should not be a problem.
  2. Be careful about resize algorithm. The most of client side resizers use trivial math, and result is worse than it could be.
  3. You may need to sharpen downscaled image.
  4. If you wish do reuse metadata (exif and other) from original - don't forget to strip color profile info. Because it's applied when you load image to canvas.
扶醉桌前 2024-08-31 13:11:38

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

另请参阅此库

Perhaps with the canvas tag (though it's not portable). There's a blog about how to rotate an image with canvas here, I suppose if you can rotate it, you can resize it. Maybe it can be a starting point.

See this library also.

仙气飘飘 2024-08-31 13:11:38

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

You can use a javascript image processing framework for client-side image processing before uploading the image to the server.

Below I used MarvinJ to create a runnable code based on the example in the following page:
"Processing images in client-side before uploading it to a server"

Basically I use the method Marvin.scale(...) to resize the image. Then, I upload the image as a blob (using the method image.toBlob()). The server answers back providing a URL of the received image.

/***********************************************
 * 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>

夏の忆 2024-08-31 13:11:38

根据我的经验,此示例是上传调整大小的图片的最佳解决方案: 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 的版本),我不会在这上面花任何时间。

In my experience, this example has been the best solution for uploading a resized picture: https://zocada.com/compress-resize-images-javascript-browser/

It uses the HTML5 Canvas feature.

The code is as 'simple' as this:

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

There are two downsides with this solution.

The first one is related with the image rotation, due to ignoring EXIF data. I couldn't tackle this issue, and wasn't so important in my use case, but will be glad to hear any feedback.

The second downside is the lack of support foe IE/Edge (not the Chrome based version though), and I won't put any time on that.

娇纵 2024-08-31 13:11:38

是的,对于现代浏览器来说这是完全可行的。甚至可以将文件专门作为二进制文件上传,并进行任意数量的画布更改。

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 上进行一些裁剪和调整大小。

Yes, with modern browsers this is totally doable. Even doable to the point of uploading the file specifically as a binary file having done any number of canvas alterations.

http://jsfiddle.net/bo40drmv/

(this answer is a improvement of the accepted answer here)

Keeping in mind to catch process the result submission in the PHP with something akin to:

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

If one worries about Vitaly's point, you can try some of the cropping and resizing on the working jfiddle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文