La valeur de couleur RVB #00FF00
est assez importante: elle est utilisée pour faire des films, des émissions de télévision, des annonces météo, etc. C'est la fameuse couleur "vert TV" ou "écran vert".
Le défi
Votre tâche consiste à écrire un programme qui prend deux images d'entrée, à la fois au format PNG (ou dans le type d'objet image de votre bibliothèque d'images) et de mêmes dimensions. Une image peut être n'importe quelle image ancienne. L'autre est l'image qui aura un fond de couleur #00FF00
. L'image de sortie sera constituée de la deuxième image superposée sur la première, sans #00FF00
couleur présente (sauf dans la première image). L'entrée et la sortie peuvent être effectuées avec des fichiers, une interface graphique, etc. Vous êtes autorisé à prendre un tableau de valeurs RVB en entrée, comme on le voit ici . Vous pouvez supposer qu'une image n'a que des pixels de pleine opacité.
Fondamentalement...
Créez un programme qui prend chaque #00FF00
pixel d'une image et remplacez-le par le pixel correspondant dans l'image d'arrière-plan.
Cas de test
Généreusement fourni par @dzaima: Contexte:
Premier plan:
Sortie:
Bien sûr, les failles standard sont strictement interdites . Cela comprend l'utilisation d'une ressource en ligne pour le faire pour vous.
C'est du code-golf , alors que le code le plus court gagne et que le meilleur programmeur prospère ...
la source
Réponses:
code machine x86-64 (et x86-32),
131513 octetsjournal des modifications:
Bugfix: la première version vérifiait seulement G = 0xff, ne nécessitant pas que R et B soient 0. J'ai changé pour modifier l'arrière-plan en place afin que je puisse utiliser
lodsd
au premier plan pour avoir des pixels fgeax
pour l'cmp eax, imm32
encodage court (5 octets) ), au lieu decmp dh,0xff
(3 octets).Enregistrer 2 octets: a remarqué que la modification du bg en place permettait d'utiliser un opérande de mémoire pour
cmov
, l'enregistrement d'unemov
charge de 2 octets (et l'enregistrement d'un registre, au cas où cela importait).Il s'agit d'une fonction suivant la convention d'appel System V x86-64, appelable directement à partir de C ou C ++ (sur les systèmes x86-64 non Windows) avec cette signature:
Le format d'image est RGB0 32bpp, avec le composant vert à la 2ème adresse mémoire la plus basse dans chaque pixel. L' image d'arrière-
plan de premierplan est modifiée sur place.pixel_count
est lignes * colonnes. Il ne se soucie pas des lignes / colonnes; il suffit que chromekey mélange les nombreux mots de mémoire que vous spécifiez.RGBA (avec A requis pour être 0xFF) nécessiterait l'utilisation d'une constante différente, mais aucun changement dans la taille de la fonction. Les DWORD de premier plan sont comparés pour une égalité exacte avec une constante arbitraire de 32 bits stockée sur 4 octets, de sorte que toute couleur d'ordre des pixels ou de chrominance peut être facilement prise en charge.
Le même code machine fonctionne également en mode 32 bits. Pour assembler en 32 bits, passez
rdi
àedi
dans la source. Tous les autres registres qui deviennent 64 bits sont implicites (lodsd / stosd et boucle), et les autres regs explicites restent 32 bits. Mais notez que vous aurez besoin d'un wrapper pour appeler à partir de C 32 bits, car aucune des conventions d'appel x86-32 standard n'utilise les mêmes paramètres que x86-64 SysV.Liste NASM (code machine + source), commentée pour les débutants asm avec des descriptions de ce que font les instructions les plus complexes. (La duplication du manuel de référence des instructions est un mauvais style en utilisation normale.)
Pour obtenir la source NASM d'origine de cette liste, supprimez les 26 premiers caractères de chaque ligne avec
<chromakey.lst cut -b 26- > chromakey.asm
. J'ai généré cela avec desnasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
listes NASM laissant plus de colonnes vides que je ne le souhaite entre le code machine et la source. Pour créer un fichier objet que vous pouvez lier avec C ou C ++, utiliseznasm -felf64 chromakey.asm
. (Ouyasm -felf64 chromakey.asm
).non testé , mais je suis assez confiant que l'idée de base de load / load / cmov / store est bonne, car c'est si simple.
Je pourrais économiser 3 octets si je pouvais exiger que l'appelant passe la constante de chrominance (0x00ff00) comme argument supplémentaire, au lieu de coder en dur la constante dans la fonction. Je ne pense pas que les règles habituelles permettent d'écrire une fonction plus générique pour laquelle l'appelant a configuré des constantes. Mais si c'est le cas, le 3ème argument (actuellement
dummy
) est passéedx
dans l'ABI SysV x86-64. Changez simplementcmp eax, 0x0000ff00
(5B) encmp eax, edx
(2B).Avec SSE4 ou AVX, vous pouvez le faire plus rapidement (mais avec une taille de code plus grande) avec
pcmpeqd
etblendvps
pour effectuer un mélange variable de taille d'élément 32 bits contrôlé par le masque de comparaison. (Avecpand
, vous pouvez ignorer l'octet de poids fort). Pour RGB24 compressé, vous pouvez utiliserpcmpeqb
puis 2xpshufb
+pand
pour obtenir VRAI en octets où les 3 composants de ce pixel correspondent, alorspblendvb
.(Je sais que c'est du code-golf, mais j'ai envisagé d'essayer MMX avant de choisir un entier scalaire.)
la source
nasm -felf32
. (Pour 32 bits, vous aurez également besoin d'une fonction wrapper pour appeler à partir de C, car elle utilise toujours les mêmes registres que l'ABI SysV x86-64.)Mathematica
5735 octetsmise à jour: par défaut, un fond vert est supprimé à l'aide de
RemoveBackground
. La première communication comprenait le deuxième paramètre inutile, `{" Background ", Green}".Supprime l'arrière-plan de l'image 2 et compose le résultat avec l'image 1.
Exemple
Ce qui suit, sous forme de préfixe plutôt que d'infixe, montre plus clairement comment fonctionne le code.
la source
Python 3 + numpy , 59 octets
Essayez-le en ligne!
L'entrée est donnée sous la forme d'un
numpy
tableau, avec des triplets entiers représentant des pixels (où#00FF00
en code couleur hex équivaut à[0, 255, 0]
). Le tableau d'entrée est modifié sur place, ce qui est autorisé par méta .Exemples d'images
Entrée (de la question)
Contexte:
Premier plan:
Image de premier plan après l'exécution de la fonction:
Implémentation de référence (permet
opencv
de lire les fichiers image)Affiche l'image à l'écran et l'écrit dans un fichier de sortie.
la source
lambda f,b:[x[list(x[0])==[0,255,0]]for x in zip(f,b)]
. Si la liste des listes d'entiers est également acceptable, vous pouvez le faire en 48 aveclambda f,b:[x[x[0]==[0,255,0]]for x in zip(f,b)]
G == 255
, la valeur est remplacée même si R et B ne sont pas nuls, ce qui conduit aux points rouges. Cela se produit également pour les autres groupes, même les plus difficiles qui sont moins visibles. Il effectue donc les vérifications logiques indépendamment les unes des autres et échange des canaux uniques même si une seule des conditions est remplie. Par exemple, si un pixel est[0 255 37]
les bandes rouges et vertes seront remplacées.Traitement,
11699 octetsMalheureusement, le traitement ne prend pas en charge les éléments Java 8, comme les lambdas.
Exemple d'implémentation: (enregistre l'image sous
out.png
et la dessine également à l'écran)la source
settings()
etsetup()
fonctions et il suffit d' exécuter le code directement.#ff00
-ce que c'est0xff00
la même chose que#00ff00
dans Traitement?0x0000FF00
est le motif binaire que vous recherchez?Bash + ImageMagick, 45 octets
Prend deux images comme arguments et affiche la sortie à l'écran. Remplacez
x:
par$3
pour écrire dans un troisième argument de fichier à la place. La méthode est simple: lire l'image "d'arrière-plan"; lire l'image "au premier plan"; réinterpréter la couleur "chaux" (# 00ff00) comme transparence dans la deuxième image; puis composez la seconde image sur la première et sortez.ImageMagick: 28 octets?
J'aurais pu soumettre cela comme une réponse ImageMagick mais il n'est pas clair comment gérer les arguments. Si vous voulez affirmer qu'ImageMagick est un langage basé sur la pile (ce qui n'est pas vraiment vrai, mais presque ... c'est bizarre),
-transparent lime -composite
c'est une fonction qui attend deux images sur la pile et laisse une image fusionnée sur la pile .. Peut-être que c'est assez bon pour compter?la source
MATL ,
403731 octetsExemple exécuté avec l'interpréteur hors ligne. Les images sont saisies par leur URL (des noms de fichiers locaux peuvent également être fournis).
Explication
la source
Pyth , 27 octets
Il faut une entrée entre guillemets. L'entrée sont les deux chemins des fichiers image. Sortie d'un fichier
o.png
Malheureusement qui ne peut pas être testé sur l'interpréteur en ligne pour des raisons de sécurité ('
est désactivé dessus). Vous devrez télécharger Pyth sur votre ordinateur pour le tester.Explication
la source
Matlab 2016b et Octave,
6259 octetsEntrée: A = matrice de premier plan MxNx3 unit8, B = matrice de fond MxNx3 unit8.
Sortie: A = matrice MxNx3 unit8
Exemple d'utilisation:
la source
C ++, 339 octets
Cela utilise CImg et peut également prendre des fichiers dans d'autres formats. Le résultat est affiché dans une fenêtre.
Compilez avec
g++ chromakey.cpp -g -L/usr/lib/i386-linux-gnu -lX11 -o chromakey -pthread
.la source
R, 135 octets
Fonction anonyme, prend 2 chemins de fichier png comme arguments et génère une image png appelée
a.png
.Légèrement non golfé, avec explications:
la source
SmileBASIC, 90 octets quelle est la clé
I
est le premier plan et la sortie,J
est l'arrière-plan. Les deux sont des tableaux entiers de pixels, au format ARGB 32 bits.Non golfé
Explication:
ARYOP est une fonction qui applique une opération simple à chaque élément d'un tableau.
Il s'appelle comme
ARYOP mode, output_array, input_array_1, input_array_2, ...
Premièrement, pour déterminer quels pixels de l'image sont verts,
-16711936
(la représentation RGBA de la couleur verte) est soustraite de chaque pixel de l'image de premier plan. Cela donne un tableau où0
représente les pixels verts, et tout autre nombre représente les pixels non verts.Pour convertir toutes les valeurs non nulles en
1
, elles sont au carré (pour supprimer les nombres négatifs), puis fixées entre0
et1
.Il en résulte un tableau avec uniquement
0
s et1
s.0
s représentent des pixels verts dans l'image de premier plan et doivent être remplacés par des pixels de l'arrière-plan.1
s représentent des pixels non verts, et ceux-ci devront être remplacés par des pixels du premier plan.Cela peut facilement être fait en utilisant une interpolation linéaire.
la source
PHP, 187 octets
suppose des fichiers PNG 24 bits; prend les noms de fichiers des arguments des lignes de commande, écrit dans stdout.
Courez avec
-r
.panne
la source
JavaScript (ES6), 290 octets
Prend l'entrée comme deux
Image
objets (dans la syntaxe de curry), qui peuvent être créés avec un<image>
élément HTML . Renvoie une promesse qui se résout à l'URL de données Base64 de l'image résultante, qui peut être appliquée à cellesrc
d'un<image>
.L'idée ici était de définir la valeur alpha pour chaque
#00FF00
pixel0
, puis de peindre le premier plan, avec son arrière-plan masqué, au-dessus de l'arrière-plan.Extrait de test
Inclure le premier plan et l'arrière-plan par leurs URL de données était trop volumineux pour être publié ici, il a donc été déplacé vers CodePen:
Essayez-le en ligne!
la source
OSL , 83 octets
Prend deux entrées. Le premier est le premier plan et le second l'arrière-plan.
la source