Skalieren eines Bildes auf Leinwand


76

Ich habe ein Formular, mit dem ein Benutzer ein Bild hochladen kann.

Sobald das Bild geladen ist, führen wir eine Skalierung durch, um die Dateigröße zu verringern, bevor wir es an den Server zurückgeben.

Dazu legen wir es auf die Leinwand und manipulieren es dort.

Dieser Code rendert das skalierte Bild auf der Leinwand mit einer Leinwandgröße von 320 x 240 Pixel:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

... wobei canvas.width und canvas.height die Bildhöhe und -breite xa Skalierungsfaktor ist, der auf der Größe des Originalbilds basiert.

Aber wenn ich den Code benutze:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height

... Ich bekomme nur einen Teil des Bildes auf die Leinwand, in diesem Fall die obere linke Ecke. Ich brauche das gesamte Bild "skaliert", um auf die Leinwand zu passen, obwohl die tatsächliche Bildgröße größer als die Leinwandgröße von 320 x 240 ist.

Für den obigen Code betragen die Breite und Höhe 1142 x 856, da dies die endgültige Bildgröße ist. Ich muss diese Größe beibehalten, um Beck an den Server zu übergeben, wenn das Formular gesendet wird, möchte aber nur, dass eine kleinere Ansicht davon im Canvas für den Benutzer angezeigt wird.

Was vermisse ich hier? Kann mich bitte jemand in die richtige Richtung weisen?

Vielen Dank im Voraus.

Antworten:


132

Geben Sie die Größe des Quellbilds (img) als erstes Rechteck an:

ctx.drawImage(img, 0, 0, img.width,    img.height,     // source rectangle
                   0, 0, canvas.width, canvas.height); // destination rectangle

Das zweite Rechteck ist die Zielgröße (auf welches Quellrechteck wird skaliert).

Update 2016/6 : Informationen zu Seitenverhältnis und Positionierung (ala CSS "Cover" -Methode) finden Sie unter:
Hintergrundgröße der Simulation: Cover in Canvas


1
Das ist perfekt, +1. Kurzer Punkt - Sie vermissen die schließende Klammer der drawImage()Funktion. Ein bisschen mit meiner OCD herumspielen;)
Frits

1
Perfekt für meine Bedürfnisse. Es ersparte mir, mit der Größe / Skalierung meiner Bilddatei herumspielen zu müssen, wenn sich die Formularränder änderten. Vielen Dank;)
Zeek2

140

Sie haben beim zweiten Aufruf den Fehler gemacht, die Größe der Quelle auf die Größe des Ziels festzulegen.
Ich wette jedenfalls, dass Sie das gleiche Seitenverhältnis für das skalierte Bild wünschen, also müssen Sie es berechnen:

var hRatio = canvas.width / img.width    ;
var vRatio = canvas.height / img.height  ;
var ratio  = Math.min ( hRatio, vRatio );
ctx.drawImage(img, 0,0, img.width, img.height, 0,0,img.width*ratio, img.height*ratio);

Ich nehme auch an, dass Sie das Bild zentrieren möchten, also wäre der Code:

function drawImageScaled(img, ctx) {
   var canvas = ctx.canvas ;
   var hRatio = canvas.width  / img.width    ;
   var vRatio =  canvas.height / img.height  ;
   var ratio  = Math.min ( hRatio, vRatio );
   var centerShift_x = ( canvas.width - img.width*ratio ) / 2;
   var centerShift_y = ( canvas.height - img.height*ratio ) / 2;  
   ctx.clearRect(0,0,canvas.width, canvas.height);
   ctx.drawImage(img, 0,0, img.width, img.height,
                      centerShift_x,centerShift_y,img.width*ratio, img.height*ratio);  
}

Sie können es in einem jsbin hier sehen: http://jsbin.com/funewofu/1/edit?js,output


9
Vielen Dank! Ich habe Math.min () in Math.max () geändert, um das Bild so zu skalieren und zuzuschneiden, dass es auf die Leinwand passt. Das war sehr hilfreich!
Daantje

1
Aber dies erzeugt ein Unschärfebild, wenn ich ein großes Bild aus einer kleinen Größe generiere. es wird unscharf .. irgendeine Lösung? bitte
saadk

Sehr geschätzt @gamealchemist. Das Lesen hat mir geholfen zu verstehen, wie ich zu einem verkleinerten Bild komme, und ich hätte ewig gebraucht, um dies selbst herauszufinden. Vielen Dank!
Chris Schmitz

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.