Wartość koloru RGB #00FF00
jest raczej ważna: służy do tworzenia filmów, programów telewizyjnych, komunikatów pogodowych i innych. Jest to słynny kolor „zielony telewizor” lub „zielony ekran”.
Wyzwanie
Twoim zadaniem jest napisanie programu, który pobierze dwa obrazy wejściowe, zarówno w formacie PNG (lub w typie obiektu obrazu w bibliotece obrazów), o tych samych wymiarach. Jeden obraz może być dowolnym starym obrazem. Drugi to obraz, który będzie miał tło koloru #00FF00
. Obraz wyjściowy będzie się składał z drugiego obrazu nałożonego na pierwszy, bez #00FF00
obecności koloru (z wyjątkiem pierwszego obrazu). Dane wejściowe i wyjściowe można wykonywać za pomocą plików, interfejsu GUI itp. Możesz przyjmować tablicę wartości RGB jako danych wejściowych, jak pokazano tutaj . Możesz założyć, że obraz ma tylko piksele o pełnym kryciu.
Gruntownie...
Stwórz program, który pobiera każdy #00FF00
piksel na jednym obrazie i zastępuje go odpowiednim pikselem na obrazie tła.
Przypadki testowe
Hojnie dostarczone przez @dzaima: Background:
Foreground:
Output:
Oczywiście standardowe luki są surowo zabronione . Obejmuje to korzystanie z zasobu online, aby to zrobić za Ciebie.
To jest golf golfowy , więc może wygrać najkrótszy kod, a najlepszy programista ...
źródło
Odpowiedzi:
Kod maszynowy x86-64 (i x86-32),
131513 bajtówdziennik zmian:
Bugfix: pierwsza wersja sprawdzała tylko G = 0xff, nie wymagając, aby R i B wynosiły 0. Zmieniłem na modyfikację tła w miejscu, dzięki czemu mogłem użyć
lodsd
na pierwszym planie, aby mieć piksele fgeax
docmp eax, imm32
kodowania krótkiego (5 bajtów ), zamiastcmp dh,0xff
(3 bajty).Zapisz 2 bajty: zauważyłem, że modyfikacja bg w miejscu pozwoliła na użycie operandu pamięci
cmov
, zapisanie 2-bajtowegomov
obciążenia (i zapisanie rejestru, w razie potrzeby ).Jest to funkcja zgodna z konwencją wywoływania Systemu V x86-64, wywoływaną bezpośrednio z C lub C ++ (w systemach innych niż Windows x86-64) z tym podpisem:
Format obrazu to RGB0 32 bpp, z zielonym składnikiem pod drugim najniższym adresem pamięci w każdym pikselu. Obraz tła
pierwszego planujest modyfikowany na miejscu.pixel_count
to rzędy * kolumny. Nie obchodzi go wiersze / kolumny; po prostu chromekey łączy dowolną liczbę domen pamięci określoną przez użytkownika.RGBA (z A musi być 0xFF) wymagałoby użycia innej stałej, ale bez zmiany wielkości funkcji. DWORD pierwszego planu są porównywane w celu uzyskania dokładnej równości z dowolną 32-bitową stałą zapisaną w 4 bajtach, dzięki czemu można łatwo obsługiwać dowolny rząd pikseli lub kolor klucza.
Ten sam kod maszynowy działa również w trybie 32-bitowym. Aby złożyć jako 32-bitowy, zmień
rdi
naedi
na źródło. Wszystkie inne rejestry, które stają się 64-bitowe, są niejawne (lodsd / stosd i loop), a inne jawne rejestry pozostają 32-bitowe. Pamiętaj jednak, że będziesz potrzebował opakowania, aby zadzwonić z 32-bitowego C, ponieważ żadna ze standardowych konwencji wywoływania x86-32 nie używa tych samych reguł co SysV x86-64.Lista NASM (kod maszynowy + źródło), komentowała początkujących asmów opisami tego, co robią bardziej złożone instrukcje. (Powielanie instrukcji obsługi jest normalnym użytkiem w złym stylu).
Aby usunąć oryginalne źródło NASM z tej listy, usuń 26 wiodących znaków każdej linii za pomocą
<chromakey.lst cut -b 26- > chromakey.asm
. Wygenerowałem to znasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
listami NASM, pozostawiając więcej pustych kolumn między kodem maszynowym a źródłem. Aby zbudować plik obiektowy, który można połączyć za pomocą C lub C ++, użyjnasm -felf64 chromakey.asm
. (Lubyasm -felf64 chromakey.asm
).niesprawdzone , ale jestem całkiem pewien, że podstawowa idea load / load / cmov / store jest solidna, ponieważ jest taka prosta.
Mógłbym zapisać 3 bajty, gdybym mógł zażądać od dzwoniącego przekazania stałej klucza kluczowania (0x00ff00) jako dodatkowego argumentu zamiast stałego kodowania stałej w funkcji. Nie sądzę, aby zwykłe reguły pozwalały na pisanie bardziej ogólnej funkcji, w której osoba dzwoniąca skonfigurowała dla niej stałe. Ale jeśli tak, trzeci argument (obecnie
dummy
) jest przekazywany wedx
ABI SysV x86-64. Po prostu zmieńcmp eax, 0x0000ff00
(5B) nacmp eax, edx
(2B).Z SSE4 lub AVX, można zrobić to szybciej (ale większy rozmiar kodu) z
pcmpeqd
iblendvps
zrobić 32-bitowego formatu elementem zmiennym mieszankę kontrolowany przez porównanie maski. (Zpand
, możesz zignorować wysoki bajt). W przypadku spakowanego RGB24 możesz użyć,pcmpeqb
a następnie 2xpshufb
+,pand
aby uzyskać PRAWDA w bajtach, w których pasują wszystkie 3 elementy tego pikselapblendvb
.(Wiem, że to jest golf golfowy, ale zastanawiałem się nad wypróbowaniem MMX przed przejściem na liczbę całkowitą skalarną).
źródło
nasm -felf32
. (W przypadku wersji 32-bitowej będziesz także potrzebować funkcji otoki, aby wywoływać z C, ponieważ nadal używa tych samych rejestrów, co x86-64 SysV ABI.)Mathematica
5735 bajtówaktualizacja: domyślnie zielone tło jest usuwane za pomocą
RemoveBackground
. Pierwsze przesłanie zawierało niepotrzebny drugi parametr, „{„ Tło ”, zielony}”.Usuwa tło obrazu 2 i łączy wynik z obrazem 1.
Przykład
Poniżej, w formie prefiksu, a nie infixu, wyraźniej pokazano, jak działa kod.
źródło
Python 3 + numpy , 59 bajtów
Wypróbuj online!
Dane wejściowe są podawane w formacie
numpy
tablicy, z trojaczami całkowitymi reprezentującymi piksele (gdzie#00FF00
w kodzie szesnastkowym kod koloru jest równoważny[0, 255, 0]
). Tablica wejściowa jest modyfikowana w miejscu, co jest dozwolone na meta .Przykładowe obrazy
Dane wejściowe (z pytania)
Tło:
Pierwszoplanowy:
Obraz pierwszego planu po uruchomieniu funkcji:
Implementacja referencyjna (służy
opencv
do odczytu plików obrazów)Wyświetla obraz na ekranie i zapisuje go w pliku wyjściowym.
źródło
lambda f,b:[x[list(x[0])==[0,255,0]]for x in zip(f,b)]
. Jeśli lista list liczb całkowitych jest również akceptowalna, możesz to zrobić w 48 zlambda f,b:[x[x[0]==[0,255,0]]for x in zip(f,b)]
G == 255
wartość zostanie zastąpiona, nawet jeśli R i B nie są równe zero, co prowadzi do czerwonych kropek. Dzieje się tak również w przypadku innych zespołów, nawet trudnych, co jest mniej widoczne. Wykonuje więc kontrole logiczne niezależnie od siebie i zamienia pojedyncze kanały, nawet jeśli spełniony jest tylko jeden z warunków. Np. Jeśli piksel to[0 255 37]
czerwony, a zielone pasy zostaną zastąpione.Przetwarzanie,
11699 bajtówNiestety, przetwarzanie nie obsługuje rzeczy w Javie 8, takich jak lambdas.
Przykładowa implementacja: (zapisuje obraz jako
out.png
i rysuje go na ekranie)źródło
settings()
orazsetup()
funkcji i wystarczy uruchomić bezpośrednio kod.#ff00
albo0xff00
taki sam jak#00ff00
w przetwarzaniu?0x0000FF00
bitowego szukasz?Bash + ImageMagick, 45 bajtów
Pobiera dwa obrazy jako argumenty i wyświetla dane wyjściowe na ekranie. Zamiast tego zmień
x:
na,$3
aby zapisać w argumencie trzeciego pliku. Metoda jest prosta: przeczytaj obraz „tła”; przeczytaj obraz „pierwszego planu”; reinterpretuj kolor „limonka” (# 00ff00) jako przezroczystość na drugim obrazie; następnie skomponuj drugi obraz na pierwszym i wyślij.ImageMagick: 28 bajtów?
Mogłem przesłać to jako odpowiedź ImageMagick, ale nie jest jasne, jak radzić sobie z argumentami. Jeśli chcesz założyć, że ImageMagick jest językiem opartym na stosie (co jest trochę nie do końca prawdą, ale prawie ... to dziwne), to
-transparent lime -composite
jest funkcja, która oczekuje dwóch obrazów na stosie i pozostawia jeden scalony obraz na stosie. Może to wystarczy, żeby policzyć?źródło
MATL ,
403731 bajtówPrzykład uruchomienia z tłumaczem offline. Obrazy są wprowadzane przez ich adresy URL (można również podać lokalne nazwy plików).
Wyjaśnienie
źródło
Pyth , 27 bajtów
Wymaga danych wejściowych. Dane wejściowe to dwie ścieżki plików obrazów. Wyjście pliku
o.png
Niestety tego nie można przetestować w tłumaczu online ze względów bezpieczeństwa ('
jest na nim wyłączone). Musisz zainstalować Pyth na swoim komputerze, aby go przetestować.Wyjaśnienie
źródło
Matlab 2016b i Octave,
6259 bajtówDane wejściowe: A = macierz pierwszego planu MxNx3 jednostka 8, B = macierz tła MxNx3 jednostka 8.
Wyjście: A = macierz MxNx3 jednostka 8
Przykładowe użycie:
źródło
C ++, 339 bajtów
Korzysta z CImg i może również pobierać pliki w innych formatach. Wynik zostanie wyświetlony w oknie.
Kompiluj z
g++ chromakey.cpp -g -L/usr/lib/i386-linux-gnu -lX11 -o chromakey -pthread
.źródło
R, 135 bajtów
Funkcja anonimowa, przyjmuje 2 ścieżki plików png jako argumenty i wyświetla obraz png o nazwie
a.png
.Nieco golfa z objaśnieniami:
źródło
SmileBASIC, 90 bajtów, co jest kluczem
I
jest pierwszym planem i rezultatem,J
jest tłem. Obie są liczbami całkowitymi pikseli, w 32-bitowym formacie ARGB.Bez golfa
Wyjaśnienie:
ARYOP to funkcja, która stosuje prostą operację do każdego elementu w tablicy.
Nazywa się to jak
ARYOP mode, output_array, input_array_1, input_array_2, ...
Po pierwsze, aby ustalić, które piksele na obrazie są zielone,
-16711936
(reprezentacja RGBA koloru zielonego) jest odejmowana od każdego piksela na obrazie na pierwszym planie. Daje to tablicę gdzie0
reprezentują zielone piksele, a dowolna inna liczba reprezentuje nie zielone piksele.Aby przekonwertować wszystkie wartości niezerowe
1
, są one podniesione do kwadratu (w celu usunięcia liczb ujemnych), a następnie zaciśnięte pomiędzy0
i1
.Daje to tablicę zawierającą tylko
0
s i1
s.0
s reprezentują zielone piksele na obrazie pierwszego planu i powinny zostać zastąpione pikselami z tła.1
s reprezentują nie zielone piksele, które trzeba będzie zastąpić pikselami z pierwszego planu.Można to łatwo zrobić za pomocą interpolacji liniowej.
źródło
PHP, 187 bajtów
zakłada 24-bitowe pliki PNG; pobiera nazwy plików z argumentów wiersza poleceń, zapisuje na standardowe wyjście.
Uruchom z
-r
.awaria
źródło
JavaScript (ES6), 290 bajtów
Pobiera dane wejściowe jako dwa
Image
obiekty (w składni curry), które można utworzyć za pomocą<image>
elementu HTML . Zwraca obietnicę, która rozwiązuje adres URL danych Base64 wynikowego obrazu, który można zastosować dosrc
pliku an<image>
.Chodziło tu o ustawienie wartości alfa dla każdego
#00FF00
piksela na0
a następnie pomalować pierwszy plan, z wytłoczonym tłem, na tle.Test Snippet
Uwzględnienie pierwszego planu i tła według ich adresów URL danych było zbyt duże, aby można było je tutaj opublikować, dlatego zostało przeniesione do CodePen:
Wypróbuj online!
źródło
OSL , 83 bajty
Zajmuje dwa wejścia. Pierwszy to pierwszy plan, a drugi tło.
źródło