Ich verwende HTML5-Canvas-Elemente, um die Größe von Bildern in meinem Browser zu ändern. Es stellt sich heraus, dass die Qualität sehr gering ist. Ich habe Folgendes gefunden: Deaktivieren Sie die Interpolation beim Skalieren eines <canvas>, aber es hilft nicht, die Qualität zu verbessern.
Unten finden Sie meinen CSS- und JS-Code sowie das mit Photoshop überarbeitete und in der Canvas-API skalierte Bild.
Was muss ich tun, um beim Skalieren eines Bildes im Browser eine optimale Qualität zu erzielen?
Hinweis: Ich möchte ein großes Bild auf ein kleines verkleinern, die Farbe in einer Zeichenfläche ändern und das Ergebnis von der Zeichenfläche an den Server senden.
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);
});
Die Bildgröße wurde mit Photoshop geändert:
Die Bildgröße wurde auf Leinwand geändert:
Bearbeiten:
Ich habe versucht, das Downscaling in mehr als einem Schritt durchzuführen, wie in:
Ändern der Größe eines Bildes in einer HTML5- Zeichenfläche und einer HTML5- Zeichenfläche drawImage: Anwenden von Antialiasing
Dies ist die Funktion, die ich verwendet habe:
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);
}
Hier ist das Ergebnis, wenn ich eine 2-Stufen-Größenänderung verwende:
Hier ist das Ergebnis, wenn ich eine 3-Stufen-Größenänderung verwende:
Hier ist das Ergebnis, wenn ich eine 4-Stufen-Größenänderung verwende:
Hier ist das Ergebnis, wenn ich eine Größenänderung von 20 Schritten verwende:
Hinweis: Es stellt sich heraus, dass sich die Bildqualität von 1 Schritt auf 2 Schritte erheblich verbessert. Je mehr Schritte Sie dem Prozess hinzufügen, desto unschärfer wird das Bild.
Gibt es eine Möglichkeit, das Problem zu lösen, dass das Bild umso unschärfer wird, je mehr Schritte Sie hinzufügen?
Edit 2013-10-04: Ich habe den Algorithmus von GameAlchemist ausprobiert. Hier ist das Ergebnis im Vergleich zu Photoshop.
PhotoShop Bild:
GameAlchemist-Algorithmus: