简体   繁体   English

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

[英]Image resizing client-side with JavaScript before upload to the server

I am looking for a way to resize an image client-side with JavaScript (really resize, not just change width and height).我正在寻找一种使用 JavaScript 调整图像客户端大小的方法(真正调整大小,而不仅仅是更改宽度和高度)。
I know it's possible to do it in Flash but I would like to avoid it if possible.我知道可以在 Flash 中执行此操作,但如果可能,我想避免使用它。

Is there any open source algorithm somewhere on the web?网络上有什么开源算法吗?

Here's a gist which does this: https://gist.github.com/dcollien/312bce1270a5f511bf4a这是执行此操作的要点: https : //gist.github.com/dcollien/312bce1270a5f511bf4a

(an es6 version, and a .js version which can be included in a script tag) (一个 es6 版本和一个 .js 版本,可以包含在脚本标签中)

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.它包括一堆支持检测和 polyfills,以确保它在我能管理的尽可能多的浏览器上工作。

(it also ignores gif images - in case they're animated) (它也会忽略 gif 图像 - 如果它们是动画的)

The answer to this is yes - in HTML 5 you can resize images client-side using the canvas element.答案是肯定的 - 在 HTML 5 中,您可以使用 canvas 元素在客户端调整图像大小。 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/ http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/

If you were resizing before uploading I just found out this http://www.plupload.com/如果您在上传之前调整大小,我刚刚发现这个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.不幸的是,只有 Mozilla 浏览器支持 HTML5 调整大小,但您可以将其他浏览器重定向到 Flash 和 Silverlight。

I just tried it and it worked with my android!我刚刚尝试过,它与我的 android 一起工作!

I was using http://swfupload.org/ in flash, it does the job very well, but the resize size is very small.我在 flash 中使用http://swfupload.org/ ,它的工作非常好,但调整大小非常小。 (cannot remember the limit) and does not go back to html4 when flash is not available. (不记得限制了)并且在 flash 不可用时不会回到 html4。

http://nodeca.github.io/pica/demo/ 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).每个通道只有 8 位(jpeg 可以有更好的动态范围,大约 12 位)。 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.如果您希望重用原始元数据(exif 和其他) - 不要忘记去除颜色配置文件信息。 Because it's applied when you load image to 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.有一个关于如何使用画布旋转图像的博客here ,我想如果你可以旋转它,你可以调整它的大小。 Maybe it can be a starting point.也许它可以是一个起点。

See this library also.另请参阅此库

You can use a javascript image processing framework for client-side image processing before uploading the image to the server.在将图像上传到服务器之前,您可以使用 javascript 图像处理框架进行客户端图像处理。

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"下面我使用MarvinJ根据以下页面中的示例创建了一个可运行的代码: “在将图像上传到服务器之前在客户端处理图像”

Basically I use the method Marvin.scale(...) to resize the image.基本上我使用Marvin.scale(...)方法来调整图像大小。 Then, I upload the image as a blob (using the method image.toBlob() ).然后,我将图像作为 blob 上传(使用方法image.toBlob() )。 The server answers back providing a URL of the received image.服务器回复提供接收图像的 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>

In my experience, this example has been the best solution for uploading a resized picture: https://zocada.com/compress-resize-images-javascript-browser/根据我的经验,此示例是上传调整大小图片的最佳解决方案: https : //zocada.com/compress-resize-images-javascript-browser/

It uses the HTML5 Canvas feature.它使用 HTML5 Canvas 功能。

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.第一个与图像旋转有关,因为忽略了 EXIF 数据。 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.第二个缺点是缺乏对 IE/Edge 的支持(虽然不是基于 Chrome 的版本),我不会花时间在这上面。

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/ 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:请记住,在 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);

If one worries about Vitaly's point, you can try some of the cropping and resizing on the working jfiddle.如果有人担心 Vitaly 的观点,您可以尝试对工作 jfiddle 进行一些裁剪和调整大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM