Der RGB-Farbwert #00FF00
ist ziemlich wichtig: Er wird zum Erstellen von Filmen, Fernsehsendungen, Wettermeldungen und vielem mehr verwendet. Es ist die berühmte "TV-Grün" - oder "Green-Screen" -Farbe.
Die Herausforderung
Ihre Aufgabe ist es, ein Programm zu schreiben, das zwei Eingabebilder im PNG-Format (oder im Bildobjekttyp Ihrer Bildbibliothek) mit denselben Abmessungen aufnimmt. Ein Bild kann ein beliebiges altes Bild sein. Das andere ist das Bild, das einen farbigen Hintergrund hat #00FF00
. Das Ausgabebild besteht aus dem zweiten Bild, das dem ersten überlagert ist, und es ist keine #00FF00
Farbe vorhanden (außer im ersten Bild). Die Ein- und Ausgabe kann mit Dateien, einer grafischen Benutzeroberfläche usw. erfolgen. Sie können eine Reihe von RGB-Werten als Eingabe verwenden, wie hier gezeigt . Sie können davon ausgehen, dass ein Bild nur Pixel mit voller Deckkraft enthält.
Grundsätzlich gilt...
Erstellen Sie ein Programm, das jedes #00FF00
Pixel in einem Bild aufnimmt, und ersetzen Sie es durch das entsprechende Pixel im Hintergrundbild.
Testfälle
Großzügig zur Verfügung gestellt von @dzaima: Hintergrund:
Vordergrund:
Ausgabe:
Standardlücken sind natürlich strengstens untersagt . Dies beinhaltet die Verwendung einer Online-Ressource, um dies für Sie zu tun.
Das ist Code-Golf , also kann der kürzeste Code gewinnen und der beste Programmierer gedeihen ...
quelle
Antworten:
x86-64 (und x86-32) Maschinencode,
131513 BytesÄnderungsprotokoll:
Bugfix: Die erste Version überprüfte nur G = 0xff, ohne dass R und B 0 sein mussten. Ich änderte den Hintergrund, so dass ich
lodsd
im Vordergrund fg Pixeleax
für die Kurzformkodierungcmp eax, imm32
(5 Bytes) verwenden konnte ) anstelle voncmp dh,0xff
(3 Byte).Save 2 bytes (2 Byte speichern): Es wurde bemerkt, dass das Ändern des BG an Ort und Stelle die Verwendung eines Speicheroperanden zum
cmov
Speichern eines 2-Byte-mov
Ladevorgangs (und zum Speichern eines Registers, falls dies wichtig ist) ermöglicht.Dies ist eine Funktion, die der Aufrufkonvention von x86-64 System V folgt und direkt von C oder C ++ (auf x86-64-Systemen ohne Windows) mit dieser Signatur aufgerufen werden kann:
Das Bildformat ist RGB0 32bpp, wobei sich die grüne Komponente an der zweitniedrigsten Speicheradresse in jedem Pixel befindet. Das
Vordergrund-Hintergrundbild wird direkt geändert.pixel_count
ist Zeilen * Spalten. Es kümmert sich nicht um Zeilen / Spalten; Mit chromekey können Sie beliebig viele Speicherbereiche mischen.RGBA (wobei A 0xFF sein muss) würde die Verwendung einer anderen Konstante erfordern, jedoch keine Änderung der Funktionsgröße. Vordergrund-DWORDs werden auf exakte Gleichheit mit einer beliebigen 32-Bit-Konstante verglichen, die in 4 Bytes gespeichert ist, sodass jede Pixel- oder Chroma-Key-Farbe problemlos unterstützt werden kann.
Der gleiche Maschinencode funktioniert auch im 32-Bit-Modus. Zur Montage als 32-Bit, ändern
rdi
zuedi
in der Quelle. Alle anderen Register, die 64-Bit werden, sind implizit (lodsd / stosd und loop), und die anderen expliziten Register bleiben 32-Bit. Beachten Sie jedoch, dass Sie einen Wrapper benötigen, um von 32-Bit-C aus aufzurufen, da keine der standardmäßigen x86-32-Aufrufkonventionen dieselben Regeln wie x86-64 SysV verwendet.NASM-Auflistung (Maschinencode + Quelle), kommentiert für Anfänger mit Beschreibungen dessen, was die komplexeren Anweisungen tun. (Das Duplizieren der Bedienungsanleitung ist bei normaler Verwendung nicht korrekt.)
Um die ursprüngliche NASM-Quelle aus dieser Auflistung zu entfernen, entfernen Sie die führenden 26 Zeichen jeder Zeile mit
<chromakey.lst cut -b 26- > chromakey.asm
. Ich habe dies mitnasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
NASM-Auflistungen generiert. Lassen Sie mehr leere Spalten zwischen dem Computercode und der Quelle, als ich möchte. Verwenden Sie zum Erstellen einer Objektdatei, die Sie mit C oder C ++ verknüpfen könnennasm -felf64 chromakey.asm
. (Oderyasm -felf64 chromakey.asm
).ungetestet , aber ich bin ziemlich zuversichtlich, dass die Grundidee von load / load / cmov / store solide ist, weil es so einfach ist.
Ich könnte 3 Bytes einsparen, wenn der Aufrufer die Chroma-Key-Konstante (0x00ff00) als zusätzliches Argument übergeben müsste, anstatt die Konstante fest in die Funktion zu codieren. Ich glaube nicht, dass die üblichen Regeln das Schreiben einer allgemeineren Funktion erlauben, für die der Aufrufer Konstanten eingerichtet hat. Ist dies jedoch der Fall , wird das 3. Argument (derzeit
dummy
)edx
im x86-64-SysV-ABI übergeben. Ändern Sie einfachcmp eax, 0x0000ff00
(5B) zucmp eax, edx
(2B).Mit SSE4 oder AVX können Sie dies möglicherweise schneller (aber mit größerer Codegröße)
pcmpeqd
undblendvps
mit einer variablen 32-Bit-Elementgröße ausführen, die von der Vergleichsmaske gesteuert wird. (Mitpand
können Sie das High-Byte ignorieren). Für gepacktes RGB24 können Siepcmpeqb
und dann 2xpshufb
+ verwendenpand
, um WAHR in Bytes zu erhalten, bei denen dann alle 3 Komponenten dieses Pixels übereinstimmenpblendvb
.(Ich weiß, dass dies Codegolf ist, aber ich habe darüber nachgedacht, MMX zu testen, bevor ich mich für eine skalare Ganzzahl entschieden habe.)
quelle
nasm -felf32
. (Für 32-Bit benötigen Sie auch eine Wrapper-Funktion, um von C aus aufzurufen, da immer noch dieselben Register verwendet werden wie beim x86-64-SysV-ABI.)Mathematica
5735 BytesUpdate: Standardmäßig wird ein grüner Hintergrund mit entfernt
RemoveBackground
. Die erste Einreichung enthielt den unnötigen zweiten Parameter "{" Background ", Green}".Entfernt den Hintergrund von Bild 2 und setzt das Ergebnis mit Bild 1 zusammen.
Beispiel
Im Folgenden wird in Präfix- und nicht in Infixform die Funktionsweise des Codes deutlicher dargestellt.
quelle
Python 3 + Anzahl , 59 Bytes
Probieren Sie es online!
Die Eingabe erfolgt im Format eines
numpy
Arrays, wobei ganzzahlige Triplets Pixel darstellen (wobei#00FF00
hexadezimaler Farbcode entspricht[0, 255, 0]
). Das Eingabearray wird an Ort und Stelle geändert, was pro Meta zulässig ist .Beispielbilder
Eingabe (aus der Frage)
Hintergrund:
Vordergrund:
Vordergrundbild nach dem Ausführen der Funktion:
Referenzimplementierung (
opencv
zum Lesen von Bilddateien)Zeigt das Bild auf dem Bildschirm an und schreibt es in eine Ausgabedatei.
quelle
lambda f,b:[x[list(x[0])==[0,255,0]]for x in zip(f,b)]
. Wenn eine Liste von Listen mit ganzen Zahlen auch tatsächlich akzeptabel ist, können Sie dies in 48 mitlambda f,b:[x[x[0]==[0,255,0]]for x in zip(f,b)]
G == 255
, wird der Wert ersetzt, auch wenn R und B nicht Null sind, was zu den roten Punkten führt. Dies passiert auch bei den anderen Bands, auch wenn diese weniger sichtbar sind. Es führt also die Logikprüfungen unabhängig voneinander durch und tauscht einzelne Kanäle aus, auch wenn nur eine der Bedingungen erfüllt ist. ZB wenn ein Pixel ist, werden[0 255 37]
die roten und grünen Bänder ersetzt.Verarbeitung,
11699 BytesLeider unterstützt die Verarbeitung kein Java 8-Zeug, wie z. B. Lambdas.
Beispielimplementierung: (speichert das Bild als
out.png
und zeichnet es auch auf dem Bildschirm)quelle
settings()
undsetup()
Funktionen und nur den Code direkt ausführen.#ff00
oder0xff00
das gleiche wie#00ff00
in der Verarbeitung?0x0000FF00
ist das Bitmuster das Sie suchen?Bash + ImageMagick, 45 Bytes
Nimmt zwei Bilder als Argumente und zeigt die Ausgabe auf dem Bildschirm an. Wechseln Sie
x:
zu$3
, um stattdessen in ein drittes Dateiargument zu schreiben. Die Methode ist einfach: Lesen Sie das Hintergrundbild. Lies das Bild "Vordergrund". interpretiere die Farbe "Lime" (# 00ff00) als Transparenz im zweiten Bild; Kombinieren Sie dann das zweite Bild mit dem ersten und geben Sie es aus.ImageMagick: 28 Bytes?
Ich hätte dies als ImageMagick-Antwort einreichen können , aber es ist nicht klar, wie mit den Argumenten umgegangen werden soll. Wenn Sie davon ausgehen möchten, dass ImageMagick eine stapelbasierte Sprache ist (was irgendwie nicht wirklich stimmt, aber fast ... seltsam ist), dann
-transparent lime -composite
ist dies eine Funktion, die zwei Bilder auf dem Stapel erwartet und ein zusammengeführtes Bild auf dem Stapel zurücklässt. vielleicht ist das gut genug um zu zählenquelle
MATL ,
403731 BytesBeispiellauf mit dem Offline-Interpreter. Die Bilder werden über ihre URLs eingegeben (lokale Dateinamen können ebenfalls angegeben werden).
Erläuterung
quelle
Pyth , 27 Bytes
Es wird eine Eingabe in Anführungszeichen benötigt. Die Eingabe sind die beiden Pfade der Bilddateien. Datei
o.png
ausgeben Leider kann das aus Sicherheitsgründen nicht auf dem Online-Interpreter getestet werden ('
ist darauf deaktiviert). Sie müssen Pyth auf Ihrem Computer installieren, um es zu testen.Erläuterung
quelle
Matlab 2016b und Octave,
6259 BytesEingabe: A = MxNx3 Einheit8 Vordergrundmatrix, B = MxNx3 Einheit8 Hintergrundmatrix.
Ausgabe: A = MxNx3 unit8 Matrix
Beispielgebrauch:
quelle
C ++, 339 Bytes
Dies verwendet CImg und kann auch Dateien in anderen Formaten aufnehmen. Das Ergebnis wird in einem Fenster angezeigt.
Kompilieren mit
g++ chromakey.cpp -g -L/usr/lib/i386-linux-gnu -lX11 -o chromakey -pthread
.quelle
R, 135 Bytes
Anonyme Funktion, nimmt 2 PNG-Dateipfade als Argumente und gibt ein PNG-Bild mit dem Namen aus
a.png
.Leicht ungolfed, mit erklärungen:
quelle
SmileBASIC, 90 Bytes was ist der Schlüssel
I
ist der Vordergrund und die Ausgabe,J
ist der Hintergrund. Beide sind Ganzzahl-Arrays von Pixeln im 32-Bit-ARGB-Format.Ungolfed
Erläuterung:
ARYOP ist eine Funktion, die eine einfache Operation auf jedes Element in einem Array anwendet.
Es heißt wie
ARYOP mode, output_array, input_array_1, input_array_2, ...
Um zu bestimmen, welche Pixel im Bild grün sind, wird zunächst
-16711936
(die RGBA-Darstellung der grünen Farbe) von jedem Pixel im Vordergrundbild abgezogen. Dies ergibt ein Array, in dem0
grüne Pixel und jede andere Zahl nicht grüne Pixel darstellen.Um alle Werte ungleich Null in umzuwandeln
1
, werden sie quadriert (um negative Zahlen zu entfernen) und dann zwischen0
und geklemmt1
.Dies ergibt ein Array mit nur
0
s und1
s.0
s stellen grüne Pixel im Vordergrundbild dar und sollten durch Pixel aus dem Hintergrund ersetzt werden.1
s stellen nicht-grüne Pixel dar und diese müssen durch Pixel aus dem Vordergrund ersetzt werden.Dies kann leicht durch lineare Interpolation erfolgen.
quelle
PHP, 187 Bytes
geht von 24-Bit-PNG-Dateien aus; Nimmt Dateinamen von Befehlszeilenargumenten und schreibt sie nach stdout.
Laufen Sie mit
-r
.Nervenzusammenbruch
quelle
JavaScript (ES6), 290 Byte
Nimmt Eingaben als zwei
Image
Objekte (in gängiger Syntax) entgegen, die mit einem HTML-<image>
Element erstellt werden können. Gibt ein Versprechen , dass Entschlüssen zum Base64 Daten URL des resultierenden Bildes, die auf die angewendet werden kann ,src
der ein<image>
.Die Idee hier war, den Alpha-Wert für jedes
#00FF00
Pixel auf einzustellen0
und dann den Vordergrund mit ausgeblendetem Hintergrund über den Hintergrund zu malen.Testschnipsel
Das Einbeziehen des Vordergrunds und des Hintergrunds in die Daten-URLs war zu groß, um hier veröffentlicht zu werden, und wurde daher nach CodePen verschoben:
Probieren Sie es online!
quelle
OSL , 83 Bytes
Nimmt zwei Eingänge. Der erste ist der Vordergrund und der zweite der Hintergrund.
quelle