Używam elementów kanwy html5 do zmiany rozmiaru obrazów w mojej przeglądarce. Okazuje się, że jakość jest bardzo niska. Znalazłem to: Wyłącz interpolację podczas skalowania <canvas>, ale nie pomaga to w poprawie jakości.
Poniżej znajduje się mój kod css i js, a także obraz wyskalowany w Photoshopie i skalowany w API Canvas.
Co muszę zrobić, aby uzyskać optymalną jakość podczas skalowania obrazu w przeglądarce?
Uwaga: chcę zmniejszyć duży obraz do małego, zmodyfikować kolor na płótnie i wysłać wynik z płótna na serwer.
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);
});
Obraz zmieniony w Photoshopie:
Obraz zmieniony na płótnie:
Edytować:
Próbowałem zmniejszyć skalowanie w więcej niż jednym kroku, jak zaproponowano w:
Zmiana rozmiaru obrazu na kanwie HTML5 i drawImage w formacie HTML5 : jak zastosować antyaliasing
Oto funkcja, której użyłem:
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);
}
Oto wynik, jeśli użyję rozmiaru 2 stopni w dół:
Oto wynik, jeśli użyję rozmiaru 3 stopni w dół:
Oto wynik, jeśli użyję rozmiaru 4 stopniowego:
Oto wynik, jeśli użyję rozmiaru o 20 stopni:
Uwaga: Okazuje się, że od 1 do 2 kroków następuje duża poprawa jakości obrazu, ale im więcej kroków dodasz do procesu, tym bardziej rozmyty staje się obraz.
Czy istnieje sposób na rozwiązanie problemu polegającego na tym, że obraz staje się bardziej rozmyty, im więcej kroków dodajesz?
Edytuj 2013-10-04: Wypróbowałem algorytm GameAlchemist. Oto wynik w porównaniu do Photoshopa.
Zdjęcie PhotoShop:
Algorytm GameAlchemist: