J'utilise des éléments de canevas html5 pour redimensionner les images dans mon navigateur. Il s'avère que la qualité est très faible. J'ai trouvé ceci: Désactivez l'interpolation lors de la mise à l'échelle d'un <canvas>, mais cela n'aide pas à augmenter la qualité.
Vous trouverez ci-dessous mon code css et js ainsi que l'image scallée 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?
Remarque: je souhaite réduire une grande image à une petite image, modifier la couleur d'une toile et envoyer le résultat de la toile 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 redimensionnée avec Photoshop:
L'image redimensionnée sur toile:
Éditer:
J'ai essayé de faire une réduction d'échelle en plus d'une étape comme proposé dans:
Redimensionner une image dans un canevas HTML5 et un canevas Html5 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 un dimensionnement en 2 étapes:
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 un dimensionnement en 20 étapes:
Remarque: Il s'avère que d'une étape à deux étapes, il y a une grande amélioration de la qualité de l'image, mais plus vous ajoutez d'étapes au processus, plus l'image devient floue.
Y a-t-il un moyen de résoudre le problème que l'image devient plus floue à mesure que vous ajoutez d'étapes?
Edit 2013-10-04: J'ai essayé l'algorithme de GameAlchemist. Voici le résultat par rapport à Photoshop.
Image de PhotoShop:
Algorithme de GameAlchemist: