J'utilise les éléments html5 canvas pour redimensionner les images dans mon navigateur. Il s'avère que la qualité est très faible. J'ai trouvé ceci : Désactiver l'interpolation lors de la mise à l'échelle d'un <canvas> mais cela ne permet pas d'améliorer la qualité.
Vous trouverez ci-dessous mon code css et js ainsi que l'image mise à l'échelle avec Photoshop et mise à l'échelle dans l'API canvas.
Que dois-je faire pour obtenir une qualité optimale lors de la mise à l'échelle d'une image dans le navigateur ?
Note : Je veux réduire une grande image à une petite, modifier la couleur dans un canevas et envoyer le résultat du canevas au serveur.
CSS :
canvas, img {
image-rendering: optimizeQuality;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
-ms-interpolation-mode: nearest-neighbor;
}
JS :
var $img = $('<img>');
var $originalCanvas = $('<canvas>');
$img.load(function() {
var originalContext = $originalCanvas[0].getContext('2d');
originalContext.imageSmoothingEnabled = false;
originalContext.webkitImageSmoothingEnabled = false;
originalContext.mozImageSmoothingEnabled = false;
originalContext.drawImage(this, 0, 0, 379, 500);
});
L'image a été redimensionnée avec photoshop :
L'image redimensionnée sur la toile :
Edit :
J'ai essayé de faire la réduction d'échelle en plusieurs étapes comme proposé dans le document :
Redimensionnement d'une image dans un canevas HTML5 y Html5 canvas drawImage : comment appliquer l'anticrénelage ?
C'est la fonction que j'ai utilisée :
function resizeCanvasImage(img, canvas, maxWidth, maxHeight) {
var imgWidth = img.width,
imgHeight = img.height;
var ratio = 1, ratio1 = 1, ratio2 = 1;
ratio1 = maxWidth / imgWidth;
ratio2 = maxHeight / imgHeight;
// Use the smallest ratio that the image best fit into the maxWidth x maxHeight box.
if (ratio1 < ratio2) {
ratio = ratio1;
}
else {
ratio = ratio2;
}
var canvasContext = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
var canvasCopy2 = document.createElement("canvas");
var copyContext2 = canvasCopy2.getContext("2d");
canvasCopy.width = imgWidth;
canvasCopy.height = imgHeight;
copyContext.drawImage(img, 0, 0);
// init
canvasCopy2.width = imgWidth;
canvasCopy2.height = imgHeight;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
var rounds = 2;
var roundRatio = ratio * rounds;
for (var i = 1; i <= rounds; i++) {
console.log("Step: "+i);
// tmp
canvasCopy.width = imgWidth * roundRatio / i;
canvasCopy.height = imgHeight * roundRatio / i;
copyContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvasCopy.width, canvasCopy.height);
// copy back
canvasCopy2.width = imgWidth * roundRatio / i;
canvasCopy2.height = imgHeight * roundRatio / i;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
} // end for
// copy back to canvas
canvas.width = imgWidth * roundRatio / rounds;
canvas.height = imgHeight * roundRatio / rounds;
canvasContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvas.width, canvas.height);
}
Voici le résultat si j'utilise une taille inférieure de 2 pas :
Voici le résultat si j'utilise un dimensionnement en 3 étapes :
Voici le résultat si j'utilise un dimensionnement en 4 étapes :
Voici le résultat si j'utilise une taille inférieure de 20 :
Remarque : il s'avère que de 1 à 2 étapes, la qualité de l'image s'améliore considérablement, mais plus vous ajoutez d'étapes au processus, plus l'image devient floue.
Existe-t-il un moyen de résoudre le problème de l'image qui devient plus floue au fur et à mesure que l'on ajoute des étapes ?
Edit 2013-10-04 : J'ai essayé l'algorithme de GameAlchemist. Voici le résultat par rapport à Photoshop.
Image PhotoShop :
Algorithme de l'alchimiste du jeu :
2 votes
Vous pouvez essayer de mettre votre image à l'échelle de manière incrémentielle : stackoverflow.com/questions/18761404/
1 votes
Duplicata possible de Html5 canvas drawImage : comment appliquer l'anticrénelage ? . Voir si cela ne fonctionne pas. Si les images sont grandes et réduites à une petite taille, vous devrez le faire par étapes (voir les exemples d'images dans le lien).
0 votes
Vous avez réglé le rendu d'image sur "optimizeSpeed". On dirait que ça va donner un redimensionnement plus moche. Avez-vous essayé de le régler sur "optimizeQuality" ?
0 votes
Vous devez également conserver l'option de lissage de l'image pour la toile.
0 votes
@Ken-AbdiasSoftware Je veux avoir la meilleure qualité disponible.
0 votes
@ScottMermelstein bon point mais ne résout pas le problème.
2 votes
@confile désactiver l'interpolation rendra la situation pire. Vous devez garder cette option activée. Regardez le lien que j'ai fourni ci-dessus. J'y montre comment utiliser des étapes pour réduire des images plus grandes et conserver la qualité. Et comme le dit Scott, il faut privilégier la qualité à la vitesse.
1 votes
@Ken-AbdiasSoftware J'ai essayé votre approche mais le problème est que le problème s'aggrave avec le nombre de tours que j'utilise pour la mise à l'échelle progressive. Avez-vous une idée de la façon de résoudre ce problème ?
0 votes
@Ken-AbdiasSoftware J'ai mis à jour mon post. L'image devient de plus en plus floue au fur et à mesure que j'utilise des ronds pour réduire la taille. Une idée pour résoudre ce problème ?
0 votes
@ScottMermelstein J'ai mis à jour mon message. L'image devient de plus en plus floue à mesure que j'utilise des ronds pour réduire la taille. Une idée pour résoudre ce problème ?
0 votes
@confile avez-vous laissé le lissage activé ? Pouvez-vous partager l'image originale que vous essayez de réduire ? (p.ex. imgur.com)
0 votes
@Ken-AbdiasSoftware Voici l'image : imgur.com/DR94LKg Lissage sur : Je n'ai pas défini de valeurs css on canvas ou imageSmoothingEnabled.
0 votes
Des étapes supplémentaires ne sont nécessaires que si vous devez réduire l'image à une très petite taille à partir d'une grande taille. Vous semblez vouloir agrandir l'image après l'avoir réduite - cela ne fonctionne pas, pas plus que la réduction en plusieurs petites étapes. Voir par exemple ici, lorsque l'image est réduite à une taille plus petite, le résultat est bon : jsfiddle.net/AbdiasSoftware/4skeg
0 votes
@Ken-AbdiasSoftware Pouvez-vous s'il vous plaît corriger mon code dans une réponse ?
1 votes
Liés : stackoverflow.com/questions/2303690/
0 votes
@ViliusL votre lien ne permet pas d'obtenir une meilleure qualité.
3 votes
Les chances de reproduire la fonctionnalité d'un logiciel professionnel de retouche photo coûteux en utilisant HTML5 sont plutôt minces. On peut sans doute s'en approcher, mais reproduire exactement le fonctionnement de Photoshop, j'imagine que c'est impossible !
0 votes
Oui, je pense que vos attentes sont un peu élevées. Il y a beaucoup d'étapes à franchir pour mettre à l'échelle une image tout en maintenant une bonne qualité, et encore plus pour quelque chose comme le niveau de qualité de Photoshop.
1 votes
Pourquoi utiliser le canevas pour redimensionner les images ? Les navigateurs modernes utilisent tous interpolation bicubique - le même processus utilisé par Photoshop (si vous le faites correctement) - et ils le font plus rapidement que le processus de la toile. Il suffit de spécifier la taille de l'image que vous souhaitez (n'utilisez qu'une seule dimension, la hauteur ou la largeur, pour un redimensionnement proportionnel).
0 votes
@Robusto pouvez-vous s'il vous plaît poster une réponse avec votre idée ? Elle semble excellente. Pouvez-vous également nous parler de la prise en charge des navigateurs ?
0 votes
Cette réponse est-elle utile ? stackoverflow.com/questions/2303690/
0 votes
Les gens avaient l'habitude de faire plusieurs redimensionnements dans photoshop aussi, en prétendant qu'ils obtenaient de meilleurs résultats qu'avec un seul passage bicubique. je n'ai jamais vu beaucoup d'amélioration pour une augmentation de 5 à 10 fois des coûts de CPU et de main d'œuvre, et j'étais un photographe professionnel avant de me mettre à la programmation. un pas de N peut éviter les motifs de moirage, mais c'est aussi généralement un résultat plus doux : bon pour les visages, mauvais pour les photos de paysages/produits. vous ne savez pas comment l'image sera affichée et quel traitement le spectateur appliquera de toute façon, donc vos efforts pourraient aboutir à un résultat pire. un redimensionnement régulier devrait être suffisant pour tout sauf les agrandissements imprimés.
0 votes
@dandavis Cela n'aide pas. Regardez les deux premières images que j'ai postées. Celle qui a été redimensionnée avec la toile est de si mauvaise qualité que vous ne pouvez même pas l'utiliser pour l'écran.
0 votes
J'attendrais de lire la réponse à cette question.
0 votes
@confile : ils ont à peu près la même apparence. les deux sont parfaitement acceptables dans la plupart des conditions. je doute que la plupart des gens accordent autant d'attention ou de considération aux images que vous. les deux collègues de bureau à qui j'ai posé la question au hasard préféraient en fait la toile redimensionnée que vous avez critiquée...
0 votes
Pourquoi est-ce que je me retrouve avec un fichier aussi gros alors ? passant de 168Kb à 610MB ?