web-dev-qa-db-fra.com

Redimensionner l'image avant le téléchargement

Je dois fournir à un utilisateur un moyen de télécharger des photos sur son site Web au format JPEG. Cependant, les photos sont très grandes en taille originale, et je voudrais rendre l'option de redimensionnement avant téléchargement très facile pour l'utilisateur. Il semble que mes seules options sont une application côté client qui redimensionne les photos avant de les télécharger via un service Web ou un hook JavaScript côté client sur l'opération de téléchargement qui redimensionne les images. La deuxième option est très provisoire car je n'ai pas de bibliothèque de redimensionnement d'images JavaScript et il sera difficile d'obtenir le JavaScript pour exécuter mon outil de redimensionnement actuel, ImageMagick. 

Je suis certain que ce scénario n’est pas si rare, et certaines suggestions ou indications à des sites qui le font seront appréciées.

51
ProfK

Vous avez plusieurs options:

  1. Java
  2. ActiveX (uniquement sur Windows)
  3. Silverlight
  4. Flash
  5. Flex
  6. Google Gears (la version la plus récente est capable de redimensionner et de glisser-déposer depuis votre bureau)

J'ai fait beaucoup de recherches pour trouver une solution similaire à ce que vous avez décrit et beaucoup de solutions qui varient beaucoup en qualité et en flexibilité.

Ma suggestion est de trouver une solution qui réponde à 80% de vos besoins et de la personnaliser en fonction de vos besoins.

7
digitalsanctum

En 2011, nous pouvons savoir le faire avec l'API de fichier, et avec canvas . Cela ne fonctionne pour l'instant que dans firefox et chrome . Voici un exemple:

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);
61
Nicolas BADIA

Il existe plusieurs outils technologiques Outil Plupload qui déclare qu’il peut redimensionner avant de télécharger, mais je ne l’ai pas encore essayé. J'ai également trouvé une réponse appropriée dans ma question sur la gestion des images binaires libav javascript .

12
calavera.info

Ce que jao et russau disent est vrai. La raison en est que JavaScript n'a pas accès au système de fichiers local pour des raisons de sécurité. Si JavaScript pouvait "voir" vos fichiers image, il pourrait voir n'importe quel fichier, ce qui est dangereux.

Vous avez besoin d'un contrôle au niveau de l'application pour pouvoir le faire, ce qui signifie Flash, Java ou Active-X.

Je pense que vous avez besoin de Java ou ActiveX pour cela. Par exemple Thin Image Upload

2
jao

Malheureusement, vous ne pourrez pas redimensionner les images en Javascript. C'est possible dans Silverlight 2 tho.

Si vous voulez acheter quelque chose de déjà fait: Aurigma Image Uploader est assez impressionnant - 250 USD pour les versions ActiveX et Java. Il y a quelques démos sur le site, je suis sûr que facebook utilise le même contrôle.

1
russau

Solution JavaScript pure. Mon code redimensionne JPEG par interpolation bilinéaire et il ne perd pas 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);
0
hMatoba

Vous pouvez redimensionner l'image côté client avant de la télécharger à l'aide d'un framework de traitement d'image.

Ci-dessous, j'ai utilisé MarvinJ pour créer un code exécutable basé sur l'exemple de la page suivante: "Traitement des images côté client avant de le télécharger sur un serveur"

Fondamentalement, j'utilise la méthode Marvin.scale (...) pour redimensionner l'image. Ensuite, je télécharge l’image sous forme de blob (en utilisant la méthode image.toBlob ()). Le serveur répond en fournissant une URL de l'image reçue.

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

Voici quelques modifications permettant d’alimenter tensorflow.js (donc trop vite !!) avec une image redimensionnée et recadrée (256x256px), ainsi que l’affichage de l’image originale sous une image recadrée, pour voir ce qui est coupé.

$("#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);});}); 

Implémentation 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> 

Également pas redimensionner à une largeur/hauteur maximale, mais au minimum. Nous obtenons une image carrée de 256x256px.

0
Tim Stieffenhofer