Nach meinem vorherigen Tutorial () wo ihr gelernt habt wie ihr eine Tile Map mit Canvas zeichnen könnt, gehe ich heute ein bisschen auf kleinere Dinge ein - das arbeiten mit einzelnen Pixeln die ihr in einem Canvas verfügbar habt.
Was lernt ihr hier heute im Detail?:
- Wie kann man einzelne Pixel in einem Canvas ansprechen?
- Was lässt sich dann damit tun?
- Beispielprojekt zur darstellung des ganzen
Fangen wir an.
Ihr solltet bisher wissen wie ihr ein Canvas erzeugt, und was ein Canvas grob ist. Zunächst einmal ist ein Canvas eine Zeichenfläche die wir in unserem HTML Dokument einfügen können. Mit Javascript können wir dann anschließend auf dieser Fläche zeichnen.
Es gibt Personen die dieses Canvas unteranderem dafür nutzen um damit Spielereien zu machen wie z.b den Effekt eines Greenscreens. Das geschieht dadurch das man jeden Pixel des Canvas durchläuft, und alles was hierbei grün ist ersetzt. Man kann zum ersetzen dann zum Beispiel ein Bild nehmen!
Grundsätzlich lässt sich ein Canvas für alles mögliche nutzen - von selbst erstellten Videoplayern, bishin zu einem Spiel (als alternative zu Flash).
Doch halt - wie sprechen wir denn einzelne Pixel in einem Canvas an für so ein Greenscreen? Zuerst benötigen wir hierfür das Canvas Objekt.. das holen wir uns ganz einfach mit:
bild1 ist hierbei die Id die man im Html Code dem Canvas gegeben hat.Quote:
var g = document.getElementById('bild1');
Verdeutlichung des ganzen:
So, nun besitzen wir schon einmal das Objekt, nun müssen wir uns aber von diesem Objekt noch den Context holen. Wir benötigen hierfür den 2D Context.Quote:
<canvas id="bild1" width="1000" height="1000"></canvas>
Das passiert mit folgendem Code:
So, nun besitzen wir den Context für unser Html Canvas, und können diesen Context nutzen um auf dem Canvas zu zeichnen. Bei meinem vorherigen Tutorial haben wir diesen Context benutzt um eine Tile Map zu zeichnen.Quote:
var display = g.getContext('2d');
Hierbei haben wir nicht jeden Pixel einzelnd gezeichnet, sondern auf bereits vorhandene Funktionen zugegriffen die es uns erleichtert haben ein bereits vorhandenes Bild zu slicen + auf unser Canvas zu zeichnen.
In diesem Tutorial möchte ich euch jedoch zeigen wie ihr auf einzelne Pixel zugreifen könnt, und somit dann auch Grafikfunktionen von Bildbearbeitungsprogrammen portieren könnt.
Also damit meine ich Dinge wie:
- Farben umkehren
- Helligkeit & Dunkelheit
- Alpha Wert des Bildes
- Farben ersetzen
Und so weiter.. !
So, fangen wir mal an - wie greifen wir auf die Pixel zu?
Zunächst einmal müssen wir uns die Daten der Pixel des aktuellen Canvas holen, das machen wir mit
Wobei img1 ein von uns geladenes Bild ist, das wir bereits auf unser Canvas gezeichnet haben. Ich behandle das nur zeichnen des Bildes nur kurz, weil dies nicht Hauptteil des Tutorials ist und es eigendlich selbstverständlich sein sollte:Quote:
var p1 = display.getImageData(0,0,img1.width, img1.height);
img1 ist unser Dateiname & Bildobjekt das wir zeichnen wollen.Quote:
var img1 = new Image();
img1.src="1.jpg";
display.drawImage(img1,0,0);
0,0 bei drawImage() sagt soviel wie "Zeichne das Bild links oben am Anfang des Canvas". Man kann wenn das Canvas größer als das zu zeichnende Bild ist auch die Position wo das Bild gezeichnet werden soll ändern, aber das ist Geschmackssache.
Kommen wir zu den Pixeln zurück.
Wir haben uns nun die Daten der Pixel mit getImageData() geholt.
Nun haben wir sogesehen alle Pixel die im Canvas sind in unserer Variable p1 gespeichert.
Wir können nun jeden einzelnen Pixel mit For-Schleifen durchgehen, und somit auch Manipulieren oder auslesen (um die Farben im Bild zu erkennen).
Fangen wir an..
Für jedes Pixel gibt es 4 Werte die wir zur Verfügung haben:
- Rot
- Grün
- Blau
- Alpha
Sprich, jeder Pixel ist ein RGBA Farbspektrum , wobei die Werte Integer-Zahlen sind (keine Floats).
Wäre ein Pixel komplett Rot, könnte es also folgendermaßen ausschauen:
(255,0,0,255)
Der Index des ersten Pixels ist 0, der Index des zweiten Pixels dann 4, der Index des dritten Pixels ist 12, und das geht dann so weiter. Jedes Pixel beginnt also auf einem Vielfachen von 4.
Und nun gehen wir mal also unsere Pixel mit 2 For-Schleifen durch und lesen die Farben aus!
So.. wir lassen die For Schleife durchlaufen, und bei jedem Durchgang haben wir dann den jeweiligen Rot,Grün,Blau,Alpha Farbanteil des jeweiligen Pixels.Quote:
for (var x=0;x<p1.width;x++){
for (var y=0;y<p1.height;y++) {
// Indexwert ermitteln
var idx = (x+y*p1.width)*4;
// Ermittlung der RGBA-Werte
var r = p1.data[idx+0];
var g = p1.data[idx+1];
var b = p1.data[idx+2];
var a = p1.data[idx+3];
}
}
Was heißt das nun für uns? Ganz einfach - wir haben direkten Zugriff auf jeden Pixel, und können nun unsere Funktionen darauf anwenden.
Überlegen wir uns mal eine einfache.. wie wäre es mit einem Komplementär-Farben Filter für unser Bild?
Zuerst einmal Theorie dahinter - wie entsteht ein Komplementär-Farben Filter?
Bei diesem Filter wird eine Farbe genommen, und durch die Gegenteilige Farbe ersetzt. Wie berechnet man nun aber die Gegenteilige Farbe (z.b von Weiß wäre die Komplementärfarbe Schwarz)?
Das ist ganz einfach - wir ziehen einfach von 255 jeweils unsere 3 Werte (R,G,B) ab. Beispiel:
Ergo ergibt sich daraus das aus der Farbe Rot nun ein helles Blau wird (als Komplementärfarbe).Quote:
Rot (R:255,G:0,B:0)
R: 255-255 = 0
G: 255-0 = 255
B: 255-0 = 255
Hell Blau(R:0,G:255,B:255)
Realisieren wir das Vorgehen nun in unserer Canvas Funktion!
So.. nun was passiert hier?Quote:
for (var x=0;x<p1.width;x++){
for (var y=0;y<p1.height;y++) {
// Indexwert ermitteln
var idx = (x+y*p1.width)*4;
// Abziehen der Werte von 255 für die Komplimentärfarbe
var r = 255 - p1.data[idx+0];
var g = 255 - p1.data[idx+1];
var b = 255 - p1.data[idx+2];
var a = p1.data[idx+3]; //Alpha lassen wir weg! Das ist die Transparenz
p1.data[idx+0] = r;
p1.data[idx+1] = g;
p1.data[idx+2] = b;
p1.data[idx+3] = a;
}
}
Wir laufen jedes Pixel des Canvas durch, und berechnen für jedes Pixel die Komplimentärfarbe und setzen das Ergebniss in unsere Variable (p1).
Dieser Vorgang ansich ändert nun noch nichts an unserem Canvas das wir sehen - wir manipulieren hier lediglich eine "Kopie" unserer Bilddaten.
Damit wir nun das Ergebniss sehen müssen wir unsere Kopie der Bilddaten nun nochmals auf das Canvas zeichnen. Das funktioniert wieder ganz leicht.
Dies führen wir nach unserer For Schleife aus.Quote:
display.putImageData(p1,0,0);
Habt ihr alles richtig gemacht ist das von euch geladene Bild (img1) nun in Komplimentärfarben dargestellt.
Mit dem selben Vorgehen könnt ihr nun euer Bild mit allen möglichen Spielereien Manipulieren. Ihr könnt eine Art "Nachtsicht" Effekt einbauen, oder z.b Die Farbtemperatur eines Bildes ändern.. oder die allgemeine Farben + Alphawerte des Bildes.
Hier mal ein kleines Beispiel wie man so ein Script aufbauen könnte:
Nun liegt es an euch - ihr habt die Grundlage wie ihr Pixel manipulieren könnt mit Javascript. Anwendungszwecke müsst ihr nun selbst finden (Dunkle Bilder aufhellen, 2 Bilder überlagern lassen etc, Nightvision usw).
Jenachdem was ihr erreichen wollt, müsst ihr euch eigene Vorgehensweisen überlegen.. Bei Nightvision könntet ihr alles in verschiedene Grüntöne färben (Rot+Blau Integerzahl verringern, und bei Grün ein spezifischer Wert hinzuaddieren).. und joar. Ihr findet schon raus wie ihr die einzelnen Effekte realisieren könnt !
Anregung was ihr so tun könntet ->
2 Bilder überlagern (man benötigt 2 canvas..das was unten rausguckt ist das 2. canvas)
Grüße,
Crosside