【问题标题】:Image resize before upload上传前调整图像大小
【发布时间】:2009-06-07 13:49:32
【问题描述】:

我需要为用户提供一种将照片以 jpeg 格式上传到其网站的方法。但是,这些照片的原始尺寸非常大,我想让用户在上传前调整大小选项非常轻松。看来我唯一的选择是客户端应用程序在通过 Web 服务上传照片之前调整照片大小,或者在上传操作上使用客户端 JavaScript 挂钩来调整图像大小。第二个选项是非常试探性的,因为我没有 JavaScript 图像调整库,并且很难让 JavaScript 运行我当前的调整大小工具 ImageMagick。

我确信这种情况并不少见,我们将不胜感激一些建议或指向这样做的网站。

【问题讨论】:

    标签: javascript image-processing


    【解决方案1】:

    在 2011 年,我们可以知道使用 File API 和画布来做到这一点。 这目前仅适用于 Firefox 和 chrome。 这是一个例子:

    var file = YOUR_FILE,
        fileType = file.type,
        reader = new FileReader();
    
    reader.onloadend = function() {
      var image = new Image();
          image.src = reader.result;
    
      image.onload = function() {
        var maxWidth = 960,
            maxHeight = 960,
            imageWidth = image.width,
            imageHeight = image.height;
    
        if (imageWidth > imageHeight) {
          if (imageWidth > maxWidth) {
            imageHeight *= maxWidth / imageWidth;
            imageWidth = maxWidth;
          }
        }
        else {
          if (imageHeight > maxHeight) {
            imageWidth *= maxHeight / imageHeight;
            imageHeight = maxHeight;
          }
        }
    
        var canvas = document.createElement('canvas');
        canvas.width = imageWidth;
        canvas.height = imageHeight;
    
        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
    
        // The resized file ready for upload
        var finalFile = canvas.toDataURL(fileType);
      }
    }
    
    reader.readAsDataURL(file);
    

    【讨论】:

    • 您将如何发出正确的 ajax 发布请求,文件以常规形式出现?我想让更改对我的应用程序的其余部分透明。
    • 我写了一篇关于它的博文(法语)。这是谷歌翻译的:translate.google.fr/…
    • 我知道这有点老了,但从底部算起的第 5 行应该是 var file = canvas.toDataURL(fileType); 吗?否则,finalFile 会被遗忘。
    • 好吧,一旦你有了finalFile,你应该上传它(通过将finalFile 传递给上传函数)。这部分没有显示在那里,因为问题是关于如何调整图像大小。
    【解决方案2】:

    有多种技术支持Plupload tool 声明它可以在上传之前调整大小,但我还没有尝试过。我的question about binary image handling javascript libs也找到了合适的答案。

    【讨论】:

      【解决方案3】:

      您有多种选择:

      1. Java
      2. ActiveX(仅在 Windows 上)
      3. Silverlight
      4. Flash
      5. Flex
      6. Google Gears(最新版本能够调整大小并从您的桌面拖放)

      我进行了大量研究,寻找与您所描述的解决方案类似的解决方案,并且有很多解决方案在质量和灵活性方面存在很大差异。

      我的建议是找到一个解决方案,可以满足您 80% 的需求,并根据您的需求进行定制。

      【讨论】:

      • 是的,我对 google gears 的建议是在删除之前提出的(请注意我的回答日期)。
      • @digitalsanctum 5 年后有什么变化吗?
      • 从 2011 年开始,它可以在本地完成。请参阅下面的答案:stackoverflow.com/a/8397789/1689770
      【解决方案4】:

      我认为您需要 Java 或 ActiveX。例如Thin Image Upload

      【讨论】:

        【解决方案5】:

        jao 和 russau 说的是真的。原因是由于安全原因,JavaScript 无法访问本地文件系统。如果 JavaScript 可以“看到”您的图像文件,它就可以看到任何文件,这很危险。

        您需要一个应用程序级控件才能做到这一点,这意味着 Flash、Java 或 Active-X。

        【讨论】:

          【解决方案6】:

          很遗憾,您将无法在 Javascript 中调整图像大小。在 Silverlight 2 中是可能的。

          如果您想购买已经完成的东西:Aurigma Image Uploader 非常令人印象深刻 - ActiveX 和 Java 版本 250 美元。网站上有一些演示,我很确定 facebook 使用相同的控件。

          【讨论】:

            【解决方案7】:

            这里对 tensorflow.js 进行了一些修改(使用它太快了!!)调整大小和裁剪的图像 (256x256px),并在裁剪后的图像下显示原始图像,以查看被截断的内容。

            $("#image-selector").change(function(){
            
            
            var file = $("#image-selector").prop('files')[0];   
            
            var maxSize = 256;  // well now its minsize
            var reader = new FileReader();
            var image = new Image();
            var canvas = document.createElement('canvas');
            var canvas2 = document.createElement('canvas');     
            
            var dataURItoBlob = function (dataURI) {
                var bytes = dataURI.split(',')[0].indexOf('base64') >= 0 ?
                    atob(dataURI.split(',')[1]) :
                    unescape(dataURI.split(',')[1]);
                var mime = dataURI.split(',')[0].split(':')[1].split(';')[0];
                var max = bytes.length;
                var ia = new Uint8Array(max);
                for (var i = 0; i < max; i++)
                    ia[i] = bytes.charCodeAt(i);
                return new Blob([ia], { type: mime });
            };
            
            var resize = function () {
                var width = image.width;
                var height = image.height; 
            
                if (width > height) {           
                    if (width > maxSize) { 
                        width *= maxSize / height; 
                        height = maxSize;
                    }
                } else {
                    if (height > maxSize) {
                        height *= maxSize / width;
                        width = maxSize;
                    }           
                }
                if (width==height) { width = 256; height = 256; }
            
            
                var posiw = 0;
                var posih = 0;
                if (width > height) {posiw = (width-height)/2; }
                if (height > width) {posih = ((height - width) / 2);} 
                canvas.width = 256;
                canvas.height = 256;
                canvas2.width = width;
                canvas2.height = height;        
                 console.log('iw:'+image.width+' ih:'+image.height+' w:'+width+' h:'+height+' posiw:'+posiw+' posih:'+posih);
                canvas.getContext('2d').drawImage(image, (-1)*posiw, (-1)*posih, width, height); 
                canvas2.getContext('2d').drawImage(image, 0, 0, width, height); 
                var dataUrl = canvas.toDataURL('image/jpeg');
                var dataUrl2 = canvas2.toDataURL('image/jpeg');     
            
                    if ($("#selected-image").attr("src")) {
                        $("#imgspeicher").append('<div style="width:100%; border-radius: 5px; background-color: #eee; margin-top:10px;"><div style="position: relative; margin:10px auto;"><img id="selected-image6" src="'+$("#selected-image").attr("src")+'" style="margin: '+document.getElementById('selected-image').style.margin+';position: absolute; z-index: 999;" width="" height=""><img id="selected-image2" src="'+$("#selected-image2").attr("src")+'" style="margin: 10px; opacity: 0.4;"></div><div class="row" style="margin:10px auto; text-align: left;"> <ol>'+$("#prediction-list").html()+'</ol> </div></div>');
                    }
            
                $("#selected-image").attr("src",dataUrl);
                $("#selected-image").width(256);
                $("#selected-image").height(256);
                $("#selected-image").css('margin-top',posih+10+'px');
                $("#selected-image").css('margin-left',posiw+10+'px');      
                $("#selected-image2").attr("src",dataUrl2); 
                $("#prediction-list").empty();
                console.log("Image was loaded, resized and cropped");
                return dataURItoBlob(dataUrl);
            
            
            
            };
            
            return new Promise(function (ok, no) {
            
                reader.onload = function (readerEvent) {
                    image.onload = function () { return ok(resize()); };
                    image.src = readerEvent.target.result;
                };
            
            let file = $("#image-selector").prop('files')[0];       
            reader.readAsDataURL(file);});}); 
            

            HTML 实现:

            <input id ="image-selector" class="form-control border-0" type="file">
            
            <div style="position: relative; margin:10px auto; width:100%;" id="imgnow">
             <img id="selected-image" src="" style="margin: 10px; position: absolute; z-index: 999;">
             <img id="selected-image2" src="" style="margin: 10px; opacity: 0.4;">                       
            </div> 
            

            也不会调整到最大宽度/高度,而是调整到最小。我们得到一个 256x256px 的正方形图像。

            【讨论】:

              【解决方案8】:

              纯 JavaScript 解决方案。我的代码通过双线性插值调整JPEG大小,并且不会丢失exif。

              https://github.com/hMatoba/JavaScript-MinifyJpegAsync

              function post(data) {
                  var req = new XMLHttpRequest();
                  req.open("POST", "/jpeg", false);
                  req.setRequestHeader('Content-Type', 'image/jpeg');
                  req.send(data.buffer);
              }
              
              function handleFileSelect(evt) {
                  var files = evt.target.files;
              
                  for (var i = 0, f; f = files[i]; i++){
                      var reader = new FileReader();
                      reader.onloadend = function(e){
                          MinifyJpegAsync.minify(e.target.result, 1280, post);
                      };
                      reader.readAsDataURL(f);
                  }
              }
              
              document.getElementById('files').addEventListener('change', handleFileSelect, false);
              

              【讨论】:

                【解决方案9】:

                您可以在使用图像处理框架上传之前在客户端调整图像大小。

                下面我使用MarvinJ根据以下页面中的示例创建了一个可运行的代码: "Processing images in client-side before uploading it to a server"

                基本上我使用 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>

                【讨论】:

                  猜你喜欢
                  • 2015-06-19
                  • 2019-03-07
                  • 2015-08-06
                  • 2011-04-16
                  • 2014-07-19
                  • 2017-07-30
                  • 2017-06-26
                  相关资源
                  最近更新 更多