Manipulation Von Pixeln Mit Leinwand

0
10

Moderne Browser unterstützt die Wiedergabe von Videos über den <video> – element. Die meisten Browser haben außerdem Zugriff auf webcams, die über die MediaDevices.getUserMedia () – API. Aber sogar mit diese beiden Dinge kombiniert, können wir nicht wirklich Zugriff auf und Bearbeiten diese Pixel direkt.

Glücklicherweise Browser ein Canvas-API, die es uns ermöglicht, Grafiken zeichnen mit JavaScript. Wir können sogar Bilder zeichnen, um das <canvas> – vom video selbst, das gibt uns die Fähigkeit, zu manipulieren und spielen mit diesen Pixeln.

Alles, was Sie hier lernen, darüber, wie zu manipulieren Pixel wird Ihnen eine Grundlage für die Arbeit mit Bildern und videos jeglicher Art oder jeder Quelle, nicht nur Leinwand.

Hinzufügen eines Bildes auf Leinwand

Bevor wir anfangen zu spielen mit video, let ‘ s Blick auf das hinzufügen ein Bild auf die Leinwand.

<img id=”SourceImage” src=”image.jpg”>
<div class=”video-container”>
<canvas id=”Leinwand” class=”video”></canvas>
</div>

Wir erstellt ein Bild-element repräsentiert das Bild, das gezeichnet werden auf der Leinwand. Alternativ könnten wir das Image-Objekt in JavaScript.

var canvas;
var context;

function init() {
var image = document.getElementById(‘SourceImage’);
canvas = document.getElementById(‘Canvas’);
context = canvas.getContext(‘2d’);

drawImage(image);
// Oder
// var Bild = new Image();
// Bild.onload = function () {
// Methode drawImage(image);
// }
// Bild.src = ‘image.jpg’;
}

Funktion drawImage(Bild) {
// Legen Sie die Leinwand mit der gleichen Breite und Höhe des Bildes
canvas.Breite = Bild.Breite;
canvas.height = Bild.Höhe;

Kontext.drawImage(Bild, 0, 0);
}

Fenster.addEventListener (“load”, init);

Der code oben, zieht das ganze Bild auf die Leinwand.

Finden Sie den Stift Paint-Bild auf Leinwand von Welling Guzman (@wellingguzman) auf CodePen.

Jetzt können wir anfangen zu spielen mit diesen Pixeln!

Die Aktualisierung der Bilddaten

Die Bilddaten auf der Leinwand erlaubt uns, uns zu manipulieren und ändern Sie die Pixel.

Die data-Eigenschaft ist ein ImageData-Objekt mit drei Eigenschaften — Breite, – Höhe und-Daten/ alle repräsentieren jene Dinge, die basierend auf dem original-Bild. Alle diese Eigenschaften sind schreibgeschützt. Die, die wir uns kuemmern muessen, ist-Daten, n eindimensionales array dargestellt durch ein Uint8ClampedArray-Objekt mit den Daten der einzelnen pixel in ein RGBA-format.

Obwohl der data-Eigenschaft readonly ist, es bedeutet nicht, wir können nicht ändern Sie dessen Wert. Es bedeutet, dass wir nicht zuordnen können ein array auf diese Eigenschaft.

// Die canvas-Bilddaten
var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);

Bild.Daten = new Uint8ClampedArray(); // FALSCH
Bild.Daten[1] = 0; // KORREKT

Was für Werte hat die Uint8ClampedArray Objekt repräsentieren, können Sie Fragen. Hier ist die Beschreibung von MDN:

Die Uint8ClampedArray typisiertes array repräsentiert ein array von 8-bit unsigned Integer gespannt auf 0-255; wenn Sie einen Wert angegeben, der außerhalb des Bereichs von [0,255], 0 oder 255 gesetzt statt; wenn Sie angeben, dass eine nicht-ganze Zahl, die nächste ganze Zahl gesetzt wird. Die Inhalte werden initialisiert auf 0. Einmal etabliert, können Sie auf Elemente im array mit den Objekt-Methoden oder mit standard-array-index-syntax (das heißt, mit Klammer-notation)

Kurz gesagt, ist dieses array speichert Werte von 0 bis 255 in jeder position, so dass dies die perfekte Lösung für die RGBA-format, da jedes Teil wird vertreten von 0 bis 255 Werte.

RGBA-Farben

Farben können dargestellt werden durch die RGBA-format, das eine Kombination von Rot, Grün und Blau. Die Eine stellt den alpha-Wert, der die Deckkraft der Farbe.

Jede position im array repräsentiert eine Farbe (pixel) Kanal Wert.

  • 1. position ist der Wert für Rot
  • 2. position ist der Grüne Wert
  • Die 3. position ist der Blau-Wert
  • Die position 4 ist der Alpha-Wert
  • 5. position des nächsten pixel den Rot-Wert
  • 6. position des nächsten pixel-Grün-Wert
  • Der 7. Platz ist das nächste pixel Blau-Wert
  • 8. position des nächsten pixel-Alpha-Wert
  • Und so weiter…

Wenn Sie ein 2×2-Bild, dann haben wir eine 16 position array (2×2-Pixel x 4-Wert).

Das 2×2-Bild gezoomt Nähe

Das array wird dargestellt, wie unten gezeigt:

// ROT GRÜN BLAU WEIß
[ 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 255, 255, 255, 255]
Ändern Sie die pixel-Daten

Einer der schnellsten Dinge, die wir tun können, ist gesetzt, alle Pixel zu weiß, indem Sie alle RGBA-Werte auf 255.

// Eine Taste zum auslösen der “Effekt”
var button = document.getElementById(‘Button’);

– Taste.addEventListener(‘click’, onClick);

Funktion changeToWhite(Daten) {
for (var i = 0; i < data.length; i++) {
Daten[i] = 255;
}
}

function onClick() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);

changeToWhite(imageData.Daten);

// Update der Leinwand mit den neuen Daten
Kontext.putImageData(imageData, 0, 0);
}

Die Daten werden als Referenz übergeben, was bedeutet, dass jede änderung, die wir machen, wird es ändern Sie den Wert des Arguments übergeben.

Invertieren Farben

Ein schöner Effekt, der nicht erforderlich ist viel Berechnung ist die Invertierung der Farben eines Bildes.

Invertieren einer Farbe der Wert kann getan werden, mithilfe von XOR-operator (^) oder diese Formel 255 – Wert (Wert muss zwischen 0 und 255).

Funktion invertColors(Daten) {
for (var i = 0; i < data.length; i+= 4) {
Daten[i] = data[i] ^ 255; // Invertiert Rot
Daten[i+1] = data[i+1] ^ 255; // Invertieren Grün
Daten[i+2] = Daten[i+2] ^ 255; // Invertieren Blau
}
}

function onClick() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);

invertColors(imageData.Daten);

// Update der Leinwand mit den neuen Daten
Kontext.putImageData(imageData, 0, 0);
}

Wir Inkrementieren die Schleife von 4 statt 1 wie zuvor, so können wir von pixel zu pixel, die jeder füllen 4 Elemente im array.

Der alpha-Wert hat keinen Einfluss auf die Farben invertieren, so dass wir es überspringen.

Helligkeit und Kontrast

Die Anpassung der Helligkeit eines Bildes kann getan werden, mithilfe der Formel: newValue = currentValue + 255 * (Helligkeit / 100).

  • die Helligkeit muss zwischen -100 und 100
  • currentValue ist der aktuelle Lichtwert von entweder Rot, Grün oder Blau.
  • newValue ist das Ergebnis der aktuellen Farbe light plus Helligkeit

Anpassen des Kontrasts eines Bildes können Sie mit dieser Formel:

Faktor = (259 * (Kontrast + 255)) / (255 * (259 – Kontrast -))
Farbe = GetPixelColor(x, y)
newRed = Kürzen(Faktor * (Rot(Farbe) – 128) + 128)
newGreen = Kürzen(Faktor * (Green(color) – 128) + 128)
newBlue = Kürzen(Faktor * (Blue(color) – 128) + 128)

Der Haupt-Berechnung ist immer der Kontrast-Faktor, der angewendet wird, um jede Farbe Wert. Truncate ist eine Funktion, stellen Sie sicher, dass der Wert sich zwischen 0 und 255.

Wir schreiben diese Funktionen in JavaScript:

Funktion applyBrightness(Daten, Helligkeit) {
for (var i = 0; i < data.length; i+= 4) {
Daten[i] += 255 * (Helligkeit / 100);
Daten[i+1] += 255 * (Helligkeit / 100);
Daten[i+2] += 255 * (Helligkeit / 100);
}
}

Funktion truncateColor(Wert) {
if (Wert < 0) {
Wert = 0;
} else if (Wert > 255) {
Wert = 255;
}

return Wert;
}

Funktion applyContrast(Daten -, Kontrast) {
var Faktor = (259.0 * (Kontrast + 255.0)) / (255.0 * (259.0 – Kontrast));

for (var i = 0; i < data.length; i+= 4) {
Daten[i] = truncateColor(Faktor * (Daten[i] – 128.0) + 128.0);
Daten[i+1] = truncateColor(Faktor * (Daten[i+1] – 128.0) + 128.0);
Daten[i+2] = truncateColor(Faktor * (Daten[i+2] – 128.0) + 128.0);
}
}

In diesem Fall brauchen Sie nicht die truncateColor Funktion als Uint8ClampedArray, schneidet diese Werte, aber für die Zwecke der übersetzung des Algorithmus haben wir Hinzugefügt, dass in.

Eine Sache im Auge zu behalten ist, dass, wenn Sie Helligkeit oder Kontrast, es gibt keine Möglichkeit wieder auf den vorherigen Zustand wie die Bild-Daten wird überschrieben. Die original-Bild-Daten gespeichert werden müssen, getrennt für Referenz, wenn wir wollen, dass das zurücksetzen auf den ursprünglichen Zustand. Halten Sie die image-variable zugänglich zu anderen Funktionen, die hilfreich sein, so können Sie dieses abbild verwenden, statt neu zu zeichnen, die Leinwand mit dem original image.

var image = document.getElementById(‘SourceImage’);

Funktion redrawImage() {
Kontext.drawImage(Bild, 0, 0);
}

Mit videos

Es funktioniert mit den videos, die wir zu unserem ersten Bild, script und HTML-code und einige kleine änderungen vorgenommen.

HTML

Ändern Sie das Bild-element mit einem video-element ersetzen Sie diese Zeile:

<img id=”SourceImage” src=”image.jpg”>

…mit diesem:

<video id=”SourceVideo” src=”video.mp4″></video>
JavaScript

Ersetzen Sie diese Zeile:

var image = document.getElementById(‘SourceImage’);

…mit diesem:

var video = document.getElementById(‘SourceVideo’);

Zu Beginn der Arbeit mit dem video, wir haben zu warten, bis das video abgespielt werden kann.

video.addEventListener(‘canplay’, function () {
// Legen Sie die Leinwand mit der gleichen Breite und Höhe des Videos
canvas.Breite = video.videoWidth;
canvas.Höhe = video.videoHeight;

// Spielen Sie das video
video.play();

// beginnen Sie mit dem zeichnen der frames
Strecke(video);
});

Die canplay-event wird ausgelöst, wenn genügend Daten zur Verfügung stehen, dass die Medien abgespielt werden können, zumindest für ein paar frames.

Wir können nicht sehen das video auf der Leinwand angezeigt, weil wir nur die Anzeige der ersten frame. Wir müssen ausführen, Strecke alle n Millisekunden, um mit der video-frames-rate.

Im inneren Strecke nennen wir Strecke wieder alle 10ms.

Funktion Strecke(video) {
Kontext.drawImage(video, 0, 0);

setTimeout(function () {
Strecke(video);
}, 10);
}

Nachdem wir ausführen Strecke, wir erstellen eine Schleife ausführen Strecke alle 10 MS, genug Zeit, um das video in sync im canvas-Bereich.

Hinzufügen den Effekt auf das video

Wir können die gleiche Funktion, die wir zuvor erstellt haben, zum invertieren Farben:

Funktion invertColors(Daten) {
for (var i = 0; i < data.length; i+= 4) {
Daten[i] = data[i] ^ 255; // Invertiert Rot
Daten[i+1] = data[i+1] ^ 255; // Invertieren Grün
Daten[i+2] = Daten[i+2] ^ 255; // Invertieren Blau
}
}

Und fügen Sie es in das streckwerk Funktion:

Funktion Strecke(video) {
Kontext.drawImage(video, 0, 0);

var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);
invertColors(imageData.Daten);
Kontext.putImageData(imageData, 0, 0);

setTimeout(function () {
Strecke(video);
}, 10);
}

Wir können eine Schaltfläche hinzufügen, und setzen Sie die Effekte:

Funktion Strecke(video) {
Kontext.drawImage(video, 0, 0);

wenn (applyEffect) {
var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);
invertColors(imageData.Daten);
Kontext.putImageData(imageData, 0, 0);
}

setTimeout(function () {
Strecke(video);
}, 10);
}

Mit Kamera

Wir halten den gleichen code verwenden wir für das video mit der nur anders ist, dass wir gehen, ändern Sie den video-stream von einer Datei auf die Kamera-stream mit MediaDevices.getUserMedia

MediaDevices.getUserMedia ist die neue API abwertend den vorherigen API MediaDevices.getUserMedia(). Es gibt immer noch browser die Unterstützung für die alte version und einige browser unterstützen nicht die neue version und wir haben zu greifen, um polyfill um sicherzustellen, dass die browser-Unterstützung von Ihnen

Erste, entfernen Sie das src-Attribut im video-element:

<video id=”SourceVideo”><code></pre>

<pre rel=”JavaScript”><code class=”language-javascript”>// die Quelle von dem video auf die Kamera-stream
Funktion initCamera(stream) {
video.src = Fenster.URL.createObjectURL(stream);
}

if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.dann(initCamera)
.catch(Konsole.Fehler)
);
}

Live-Demo

Effekte

Alles haben wir abgedeckt, so weit ist das Fundament, das wir brauchen, um zu erstellen Sie verschiedene Effekte auf ein video oder ein Bild. Es gibt viele verschiedene Effekte, die wir nutzen können durch die Umwandlung jede Farbe unabhängig.

Graustufen

Konvertieren einer Farbe zu einem Graustufen kann man auf verschiedene Weise mit verschiedenen Formeln/Techniken, um zu vermeiden, sich allzu tief in das Thema werde ich Ihnen zeigen, fünf der Formeln basierend auf dem GIMP Entsättigen-Werkzeug-und Luma:

Grau = 0.21 R + 0.72 G + 0.07 B // Leuchtkraft
Grau = (R + G + B) ÷ 3 // Mittlere Helligkeit
Grau = 0.299 R + 0.587 G + 0.114 B // standard rec601
Grau = 0.2126 R + 0.7152 G + 0.0722 B // ITU-R BT.709 standard
Grau = 0.2627 R + 0.6780 G + 0.0593 B // ITU-R BT.2100-standard

Was wir wollen finden, dass die Verwendung dieser Formeln ist die Helligkeit Intensität jedes pixels Farbe. Der Wert reicht von 0 (schwarz) bis 255 (weiß). Diese Werte erstellen eines Graustufen (schwarz und weiß) Wirkung.

Dies bedeutet, dass die hellste Farbe am nächsten 255 und die dunkelste Farbe, die 0 am nächsten.

Live-Demo

Duotones

Der Unterschied zwischen den duotone-Effekt und schwarz-weiß-Effekt sind die zwei Farben, die verwendet werden. Auf Graustufen-Sie haben einen Farbverlauf von schwarz zu weiß, während auf “Duplex” können Sie einen Farbverlauf von irgendeiner Farbe zu jeder anderen Farbe, blau, pink als Beispiel.

Mit der Intensität der Graustufen, die wir ersetzen können Sie diese aus dem Verlauf der Werte.

Wir brauchen ein Gefälle von ColorA, ColorB.

Funktion createGradient(colorA, colorB) {
// Werte der gradient von colorA, colorB
var Verlauf = [];
// der maximale Farbwert 255
var maxValue = 255;
// Konvertieren des hex-Farbwerte in RGB-Objekt
var von = getRGBColor(colorA);
var zu = getRGBColor(colorB);

// Erzeugt 256 Farben von Farbe A zu Farbe B
for (var i = 0; i <= maxwert; i++) {
// IntensityB gehen von 0 bis 255
// IntensityA gehen von 255 auf 0
// IntensityA verringern die Intensität, während instensityB erhöhen
// Was dies bedeutet ist, dass ColorA startet solide und langsam verwandeln sich in ColorB
// Wenn man es in anderer Weise die Transparenz der Farbe zu erhöhen und die Transparenz der Farbe B verringern
var intensityB = i;
var intensityA = maxValue – intensityB;

// Den nachstehenden Formel vereint die beiden Farben je nach Ihrer Intensität
// (IntensityA * ColorA + IntensityB * ColorB) / maxValue
gradient[i] = {
r: (intensityA*aus.r + intensityB*.r) / maxValue,
g: (intensityA*aus.g + intensityB*.g) / maxValue,
b: (intensityA*aus.b + intensityB*.b) / maxValue
};
}

zurück Farbverlauf;
}

// Hilfsfunktion zum umwandeln 6digit hex-Werte für RGB-Farben-Objekt
Funktion getRGBColor(hex)
{
var colorValue;

wenn (hex[0] === ‘#’) {
hex = hex.substr(1);
}

colorValue = parseInt(hex, 16);

return {
r: colorValue >> 16,
g: (colorValue >> 8) & 255,
b: colorValue & 255
}
}

Kurz gesagt, wir erstellen ein array mit den Farbwerten von Farbe Eine Verringerung der Intensität während er zu Farbe B und die Erhöhung Ihrer Intensität.

Aus #0096ff #ff00f0
Gezoomte Darstellung der Farbe übergang

var Gradienten = [
{r: 32, g: 144, b: 254},
{r: 41, g: 125, b: 253},
{r: 65, g: 112, b: 251},
{r: 91, g: 96, b: 250},
{r: 118 g: 81, b: 248},
{r: 145, g: 65, b: 246},
{r: 172, g: 49, b: 245},
{r: 197, g: 34, b: 244},
{r: 220, g: 21, b: 242},
{r: 241 g: 22, b: 242},
];

Oben gibt es ein Beispiel eines Gradienten von 10 Farben-Werte von #0096ff #ff00f0.

Graustufen-Darstellung der Farb-übergang

Jetzt haben wir die Graustufendarstellung des Bildes, können wir es verwenden, um eine Karte zu, um die Duplex-gradient-Werte.

Die zweifarbigen Farbverlauf mit 256 Farben, während die Graustufen hat auch 256 Farben reichen von schwarz (0) bis weiß (255). Das bedeutet, dass ein Graustufen-Farbe-Wert-Karte zu einer Gradienten-element index.

var gradientColors = createGradient(‘#0096ff’, ‘#ff00f0’);
var imageData = context.getImageData(0, 0, canvas.width, canvas.Höhe);
applyGradient(imageData.Daten);

for (var i = 0; i < data.length; i += 4) {
// Holen Sie sich die pro Kanal Farbe Wert
var redValue = Daten[i];
var greenValue = Daten[i+1];
var blueValue = Daten[i+2];

// Zuordnung der Farbwerte zu den Steigungs-index
// Ersetzen der Graustufen-Farbe-Wert mit einer Farbe für den Farbverlauf zweifarbig
Daten[i] = gradientColors[redValue].r;
Daten[i+1] = gradientColors[greenValue].g;
Daten[i+2] = gradientColors[blueValue].b;
Daten[i+3] = 255;
}

Live-Demo

Fazit

Dieses Thema können Sie gehen mehr in die Tiefe zu erklären oder mehr Effekte. Die Hausaufgaben für Sie zu finden, verschiedene algorithmen, die Sie anwenden können, um diese Skelett-Beispiele.

Zu wissen, wie die Pixel sind so strukturiert, dass auf eine Leinwand erlauben Ihnen das erstellen einer unbegrenzten Anzahl von Effekten, wie sepia, Farbe mischen, ein green-screen-Effekt, Bild flackert/glitching, etc.

Sie können sogar Effekte on-the-fly, ohne ein Bild oder ein video:

Das Jetpack WordPress-plugin läuft auf dieser Website, indem Sie nicht nur die verwandten Beiträge unten, aber die Sicherheit und backups, Markdown-support, site-Suche, Kommentar-Formularen, social-network-verbindungen und vieles mehr!