O valor da cor RGB #00FF00
é bastante importante: é usado para fazer filmes, programas de TV, anúncios sobre o clima e muito mais. É a famosa cor "verde da TV" ou "tela verde".
O desafio
Sua tarefa é gravar um programa que receba duas imagens de entrada, no formato PNG (ou no tipo de objeto de imagem da sua biblioteca de imagens) e com as mesmas dimensões. Uma imagem pode ser qualquer imagem antiga. A outra é a imagem que terá um fundo da cor #00FF00
. A imagem de saída consistirá na segunda imagem sobreposta à primeira, sem #00FF00
cor presente (exceto na primeira imagem). A entrada e a saída podem ser feitas com arquivos, uma GUI, etc. Você pode receber uma matriz de valores RGB como entrada, como visto aqui . Você pode supor que uma imagem tenha apenas pixels de total opacidade.
Basicamente...
Crie um programa que pegue cada #00FF00
pixel em uma imagem e substitua-o pelo pixel correspondente na imagem de fundo.
Casos de teste
Fornecido generosamente por @dzaima: Histórico:
Primeiro plano:
Saída:
Obviamente, as brechas padrão são estritamente proibidas . Isso inclui o uso de um recurso online para fazer isso por você.
Este é o código-golfe , para que o código mais curto ganhe e o melhor programador prospere ...
fonte
Respostas:
código de máquina x86-64 (e x86-32),
131513 byteschangelog:
Correção de bug: a primeira versão estava apenas checando G = 0xff, não exigindo que R e B fossem 0. Alterei para modificar o plano de fundo no local para que eu pudesse usar
lodsd
em primeiro plano para ter pixels fg na codificação deeax
formato curtocmp eax, imm32
(5 bytes ), em vez decmp dh,0xff
(3 bytes).Economize 2 bytes: observe que modificar o bg no local permite o uso de um operando de memória
cmov
, economizando umamov
carga de 2 bytes (e salvando um registro, caso isso importe).Esta é uma função que segue a convenção de chamada do System V x86-64, que pode ser chamada diretamente de C ou C ++ (em sistemas x86-64 não Windows) com esta assinatura:
O formato da imagem é RGB0 32bpp, com o componente verde no segundo endereço de memória mais baixo em cada pixel. A imagem de fundo do
primeiroplano é modificada no local.pixel_count
é linhas * colunas. Não se preocupa com linhas / colunas; apenas o chromekey combina no entanto muitas dwords de memória que você especificar.RGBA (com A necessário para 0xFF) exigiria o uso de uma constante diferente, mas nenhuma alteração no tamanho da função. Os DWORDs em primeiro plano são comparados quanto à igualdade exata em relação a uma constante arbitrária de 32 bits armazenada em 4 bytes, para que qualquer cor de ordem de pixel ou chave de croma possa ser facilmente suportada.
O mesmo código de máquina também funciona no modo de 32 bits. Para montar como 32 bits, altere
rdi
paraedi
na fonte. Todos os outros registradores que se tornam 64 bits são implícitos (lodsd / stosd e loop), e os outros registros explícitos permanecem em 32 bits. Mas observe que você precisará de um wrapper para chamar de C de 32 bits, porque nenhuma das convenções de chamada x86-32 padrão usa os mesmos registros do x86-64 SysV.Listagem NASM (código de máquina + fonte), comentada para iniciantes em asm com descrições do que as instruções mais complexas fazem. (Duplicar o manual de referência das instruções é um estilo ruim no uso normal.)
Para obter a fonte NASM original dessa lista, retire os 26 caracteres iniciais de cada linha
<chromakey.lst cut -b 26- > chromakey.asm
. Eunasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
criei isso com listagens NASM, deixando mais colunas em branco do que eu quero entre o código da máquina e a fonte. Para criar um arquivo de objeto que você pode vincular com C ou C ++, usenasm -felf64 chromakey.asm
. (Ouyasm -felf64 chromakey.asm
)não testado , mas estou bastante confiante de que a idéia básica de load / load / cmov / store é sólida, porque é muito simples.
Eu poderia salvar 3 bytes se exigisse que o chamador passasse a constante de chave de croma (0x00ff00) como um argumento extra, em vez de codificar a constante na função. Eu não acho que as regras usuais permitam escrever uma função mais genérica que tenha o chamador configurado constantes para ele. Mas, se o fez, o terceiro argumento (atualmente
dummy
) é passado naedx
ABI x86-64 SysV. Apenas mudecmp eax, 0x0000ff00
(5B) paracmp eax, edx
(2B).Com o SSE4 ou AVX, você pode fazer isso mais rapidamente (mas com um tamanho de código maior)
pcmpeqd
eblendvps
fazer uma mistura variável de tamanho de elemento de 32 bits controlada pela máscara de comparação. (Compand
, você pode ignorar o byte alto). Para RGB24 compactado, você pode usarpcmpeqb
e, em seguida, 2xpshufb
+pand
para obter VERDADEIRO em bytes, onde todos os 3 componentes desse pixel correspondempblendvb
.(Eu sei que isso é código-golfe, mas considerei tentar o MMX antes de usar o número inteiro escalar.)
fonte
nasm -felf32
. (Para 32-bit, você também vai precisar de uma função wrapper para chamar de C, porque ele ainda está usando os mesmos registros como o x86-64 SysV ABI.)Mathematica
5735 bytesupdate: por padrão, um fundo verde é removido usando
RemoveBackground
. A primeira submissão incluiu o segundo parâmetro desnecessário, `{" Background ", Green}".Remove o fundo da imagem 2 e compõe o resultado com a imagem 1.
Exemplo
A seguir, no prefixo, e não no formato infix, mostra mais claramente como o código funciona.
fonte
Python 3 + numpy , 59 bytes
Experimente online!
A entrada é fornecida no formato de uma
numpy
matriz, com trigêmeos inteiros representando pixels (onde#00FF00
no código de cor hexadecimal é equivalente a[0, 255, 0]
). A matriz de entrada é modificada no local, o que é permitido por meta .Imagens de exemplo
Entrada (da pergunta)
Fundo:
Primeiro plano:
Imagem em primeiro plano após executar a função:
Implementação de referência (usada
opencv
para ler arquivos de imagem)Exibe a imagem na tela e a grava em um arquivo de saída.
fonte
lambda f,b:[x[list(x[0])==[0,255,0]]for x in zip(f,b)]
. Se a lista de listas de números inteiros também é realmente aceitável, você pode fazê-lo em 48 comlambda f,b:[x[x[0]==[0,255,0]]for x in zip(f,b)]
G == 255
, o valor é substituído mesmo que R e B não sejam zero, o que leva aos pontos vermelhos. Isso também acontece para as outras bandas, mesmo difíceis, que são menos visíveis. Portanto, ele executa as verificações lógicas independentemente uma da outra e troca os canais únicos, mesmo que apenas uma das condições seja atendida. Por exemplo, se um pixel é[0 255 37]
o vermelho e as faixas verdes serão substituídas.Processando,
11699 bytesInfelizmente, o processamento não suporta coisas java 8, como lambdas.
Exemplo de implementação: (salva a imagem como
out.png
também a desenha na tela)fonte
settings()
esetup()
funções e simplesmente executar o código diretamente.#ff00
ou é0xff00
o mesmo que#00ff00
em Processamento?0x0000FF00
como o padrão de bits que está procurando?Bash + ImageMagick, 45 bytes
Tira duas imagens como argumentos e exibe a saída na tela. Mude
x:
para$3
para gravar em um terceiro argumento de arquivo. O método é simples: leia a imagem "background"; leia o "primeiro plano" imagek; reinterprete a cor "limão" (# 00ff00) como transparência na segunda imagem; depois componha a segunda imagem na primeira e saia.ImageMagick: 28 bytes?
Eu poderia ter enviado isso como uma resposta do ImageMagick, mas não está claro como lidar com os argumentos. Se você deseja afirmar que o ImageMagick é uma linguagem baseada em pilha (que meio que não é realmente verdadeira, mas quase ... é estranha),
-transparent lime -composite
é uma função que espera duas imagens na pilha e deixa uma imagem mesclada na pilha. Talvez seja bom o suficiente para contar?fonte
MATL ,
403731 bytesExemplo executado com o intérprete offline. As imagens são inseridas por seus URLs (nomes de arquivos locais também podem ser fornecidos).
Explicação
fonte
Pitão , 27 bytes
É preciso entrada citada. A entrada são os dois caminhos dos arquivos de imagem. Saída de um arquivo
o.png
Infelizmente, isso não pode ser testado no intérprete on-line por motivos de segurança ('
está desativado). Você precisará obter o Pyth no seu computador para testá-lo.Explicação
fonte
Matlab 2016b e oitava,
6259 bytesEntrada: A = matriz em primeiro plano MxNx3 unit8, B = matriz em segundo plano MxNx3 unit8.
Saída: A = matriz MxNx3 unit8
Uso da amostra:
fonte
C ++, 339 bytes
Isso usa o CImg e pode levar arquivos em outros formatos também. O resultado é exibido em uma janela.
Compile com
g++ chromakey.cpp -g -L/usr/lib/i386-linux-gnu -lX11 -o chromakey -pthread
.fonte
R, 135 bytes
Função anônima, usa 2 caminhos de arquivo png como argumentos e gera uma imagem png chamada
a.png
.Ligeiramente não-destruído, com explicações:
fonte
SmileBASIC, 90 bytes, qual é a chave
I
é o primeiro plano e a saída,J
é o segundo plano. Ambos são matrizes inteiras de pixels, no formato ARGB de 32 bits.Ungolfed
Explicação:
ARYOP é uma função que aplica uma operação simples a todos os elementos de uma matriz.
É chamado como
ARYOP mode, output_array, input_array_1, input_array_2, ...
Primeiro, para determinar quais pixels na imagem são verdes,
-16711936
(a representação RGBA da cor verde) é subtraída de cada pixel na imagem em primeiro plano. Isso fornece uma matriz em que0
representa pixels verdes e qualquer outro número representa pixels não verdes.Para converter todos os valores diferentes de zero em
1
, eles são ao quadrado (para remover números negativos) e, em seguida, fixados entre0
e1
.Isso resulta em uma matriz com apenas
0
s e1
s.0
s representam pixels verdes na imagem em primeiro plano e devem ser substituídos por pixels em segundo plano.1
s representam pixels não verdes, e esses precisarão ser substituídos por pixels do primeiro plano.Isso pode ser feito facilmente usando interpolação linear.
fonte
PHP, 187 bytes
assume arquivos PNG de 24 bits; pega nomes de arquivos nos argumentos das linhas de comando e grava no stdout.
Corra com
-r
.demolir
fonte
JavaScript (ES6), 290 bytes
Recebe entrada como dois
Image
objetos (na sintaxe de currying), que podem ser criados com um<image>
elemento HTML . Retorna uma promessa que resolve para o URL de dados Base64 da imagem resultante, que pode ser aplicada aosrc
de um<image>
.A idéia aqui era definir o valor alfa de cada
#00FF00
pixel0
e pintar o primeiro plano, com o plano de fundo excluído, na parte superior do plano de fundo.Snippet de teste
A inclusão do primeiro plano e do plano de fundo pelos URLs de dados era muito grande para serem postados aqui; portanto, foi movida para o CodePen:
Experimente online!
fonte
OSL , 83 bytes
Toma duas entradas. O primeiro é o primeiro plano e o segundo, o segundo plano.
fonte