Geração de gradientes RGB

18

O desafio

Dadas as duas cadeias de caracteres hexadecimais maiúsculas (ambos 6 caracteres, XXXXXX e YYYYYY) representando valores RGB (que vão desde 000000a FFFFFFinclusive), e uma diferente de zero positivo inteiro N, exiba uma transição linear de N + 2 cores geradas a partir de XXXXXX para YYYYYY isso resultaria em um gradiente de cor.

Exemplo

Entrada

FF3762
F08800
9

Resultado

Observe que em nosso exemplo, solicitei 9 etapas intermediárias entre as duas cores; portanto, 11 linhas serão exibidas da cor inicial à cor final

FF3762
FD3F58
FC474E
FA4F44
F9573A
F75F31
F66727
F46F1D
F37713
F17F09
F08800

Ressalvas

Enquanto eu segui um processo linear simples de derivar os valores inteiros para as cores provisórias antes de convertê-los novamente em hexadecimal, seus métodos podem variar. Por favor, considere as várias maneiras de arredondar / diminuir seus números de acordo.

Teste

Para tornar isso interessante, forneci um snippet para permitir o teste do seu código, inclusive um botão para fornecer duas cores aleatórias para testar seu código. A exibição de seus resultados é opcional, mas é incentivada!

c1=()=>('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6);

$("#col").click(function(){
  alert("Your two colors are: "+c1()+" and "+c1()+".");
});
        
$("#colors").blur(function(){
  $("#test").empty();
	var colArr = $("#colors").val().split("\n");
	for(c in colArr){
  	$("#test").append('<div class="tester" style="background-color:#'+colArr[c]+';">'+colArr[c]+'</div>')
  }
  
});
.tester{height: 20px;
width: 60px;padding: 4px;border: 1px solid black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="col">Your two colors</button><br />
<textarea id="colors"></textarea>
<div id="test">

</div>

1) Você pode acessar duas cores aleatórias para o seu teste clicando no botão "Suas duas cores". 2) O número de etapas intermediárias será o mesmo que o número de caracteres no seu nome de usuário PPCG, incluindo espaços, no caso de "WallyWest", seria 9 (conforme meu exemplo acima). 3) Execute seu código com as duas cores e o número e, depois de ter sua lista gerada, você poderá colar sua saída na área de texto e separá-la para obter o gradiente de cores gerado.

Meu exemplo é mostrado aqui:

Gradientes

Devo admitir, isso parece incrível!

Observação: como mencionei, mostrar o teste de sua saída usando o snippet é opcional, mas é recomendável! :)

Resultado

A saída da lista deve estar na forma de conjuntos N + 2 de números hexadecimais de 6 dígitos separados por feeds de linha (\ n), como mostrado no meu exemplo acima. A saída pode ser na forma de linhas separadas, lista separada por espaço / vírgula, uma matriz ou o que for mais adequado para o seu idioma ... (Obrigado @nimi pelo aviso) Lembre-se de que, se você planeja testar seu código com o snippet, no entanto, você separa cada "cor" que depende de você.

Regras

Isso é código-golfe, então a solução mais curta em bytes será coroada a vencedora. Sem brechas , naturalmente. A entrada deve aceitar as duas strings e um número (que, como eu disse, será equivalente ao número de letras no seu nome de usuário no PPCG, portanto, a saída resultante sempre terá no mínimo três linhas.

WallyWest
fonte
Notável, e atualizados ... Graças a cabeça para cima (+1)
Wally West
Por curiosidade, aplicativos de imagem como o Illustrator usam gradientes lineares ou gradientes em algum espaço de cor perceptivo? Eu posso ver casos de uso para ambos (talvez você esteja fazendo a transformação para percepção posterior, por exemplo, uma textura para um jogo).
Robert Fraser

Respostas:

1

MATL , 31 bytes

2+1yhjjh2e!1ZA3e!b:1&Ynk8W5Y2Za

Isso usa interpolação linear com arredondamento para baixo. O formato de entrada é

9
FF3762
F08800

Experimente online!

Saída gráfica, 31 bytes

2+1yhjjh2e!1ZA3e!b:t2YG1&Ynk2ZG

Este é o resultado para entradas

5
FF3762
F08800

insira a descrição da imagem aqui

Experimente no MATL Online ! O intérprete é atualmente experimental. Se você não obtiver nenhuma saída, atualize a página e pressione "Executar" novamente.

Luis Mendo
fonte
4

JavaScript (ES6), 130 bytes

g=
(f,t,n)=>[...Array(++n+1)].map((_,i)=>f.replace(/../g,(e,j)=>((`0x${e}`*(n-i)+`0x${t[j]+t[j+1]}`*i)/n|256).toString(16).slice(1)))
;
p=_=>g(f.value,t.value,+n.value).map(e=>o.insertRow().insertCell().appendChild(document.createTextNode(e)).parentNode.bgColor=e);
<input id=f value=e14f09><input id=t value=9a04f6><input id=n value=4 type=number><input type=button onclick=p() value=Go!><table id=o bgcolor=black cellpadding=4>

Neil
fonte
3

Dyalog APL , 44 bytes

Instruções para N , então B eginning-cor, então E encontrando-cor. Precisa o ⎕IO←0que é padrão em muitos sistemas.

h[↑⌊B∘+¨(⍳2+N)×(-/E B←(h←⎕D,⎕A)∘⍳¨⍞⍞)÷1+N←⎕]

h[... ]indexe em h (que tem um valor quando terminarmos de avaliar o conteúdo do colchete)

N←⎕solicitação para N numérico (4)

1+adicione um a N (5)

(... use isso para dividir o resultado de ...

  ⍞⍞ prompt para duas cadeias de caracteres ["7E0E7E", "FF3762"]

  (... )∘⍳¨encontre os índices dos caracteres de cada string em ...

   ⎕D,⎕A D igits seguidos de A lphabet

   h← atribuído a h

  agora temos "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  E B←atribua os índices a E e B [[7,14,0,14,7,14], [15,15,3,7,6,2]]

  -/subtraia e coloque B de E [[-8, -1, -3,7,1,12]]

  o resultado até agora é [[-1,6, -0,2, -0,6,1,4,0,2,2,4]]]

(... multiplique isso por ...

  2+Ndois mais N (6)

   primeiros inteiros [0,1,2,3,4,5]

 isso nos dá [[0,0,0,0,0,0], [- 1,6, -0,2, -0,6,1,4,0,2,2,4], [- 3,2, -0,4, -1,2,2,8,0,4,4,8 ], ...]

B∘+¨adicione B a cada [[15,15,3,7,6,2], [13,4,14,8,2,4,8,4,6,2,4,4], [11,8,14,6,1,8,9,8,6,4,6,8], ... ]

arredondar para baixo [[15,15,3,7,6,2], [13,14,2,8,6,4], [11,14,1,9,6,6], ...]

transformar lista de listas em tabela

[[15,15, 3, 7, 6, 2]
 [13,14, 2, 8, 6, 4]
 [11,14, 1, 9, 6, 6]
 [10,14, 1,11, 6, 9]
 [ 8,14, 0,12, 6,11]
 [ 7,14, 0,14, 7,14]]

aqui indexamos em h , dando

[["F","F","3","7","6","2]
 ["D","E","2","8","6","4]
 ["B","E","1","9","6","6]
 ["A","E","1","B","6","9]
 ["8","E","0","C","6","B]
 ["7","E","0","E","7","E]]

que é o mesmo que

[["FF3762"]
 ["DE2864"]
 ["BE1966"]
 ["AE1B69"]
 ["8E0C6B"]
 ["7E0E7E"]]

e imprime como

FF3762
DE2864
BE1966
AE1B69
8E0C6B
7E0E7E

gradiente

TryAPL online!

Adão
fonte
Bom trabalho! A transição está ótima!
WallyWest 7/09/16
@WallyWest Thanks. Provavelmente, é uma transição linear diferente da maioria: cada letra é transferida separadamente.
Adám 7/09/16
2

Pitão - 35 bytes

Horrivelmente jogado, desisti.

j++hQsMCm.HMsM:F+dc-FdvzCmiR16cd2Qe

Experimente online aqui .

Exemplo:

exemplo

Maltysen
fonte
Conto 11 linhas de gradiente, embora seu nome PPCG tenha apenas 8 letras ... Então você não deveria ter inserido 7cb472 93fb8a 8e recebido apenas 10 linhas de saída ao testar seu código?
WallyWest 7/09/16
O @WallyWest perdeu completamente essa parte do OP sobre o nome de usuário, eu apenas usei 9 porque você fez, consertando.
Maltysen 7/09/16
@WallyWest atualizado
Maltysen
Hey @ Maltysen, o gradiente parece um pouco estranho ... você tem duas referências de 93fb8a... Seu código produziu duas linhas do mesmo valor?
Wally West
2

PowerShell v2 +, 176 159 150 bytes

param($a,$b,$n)$x=$a-split'(..)'-ne'';$a;++$n..1|%{$j=$_;-join($x=$x|%{"{0:x2}"-f(+"0x$_"-[int]((+"0x$_"-"0x$(($b-split'(..)'-ne'')[$i++%3])")/$j))})}

Pega a entrada como duas strings e um número e, em seguida, converte a string inicial em uma matriz de strings divididas em cada dois caracteres, armazenando-a em $x. Em seguida, produzimos $acomo nossa seção inicial e fazemos o loop de ++$npara 1(para garantir o posicionamento correto da cerca).

Cada iteração define o auxiliar $jcomo o número atual (usado posteriormente para garantir que tenhamos o número certo de etapas entre o local em que estamos atualmente no nosso destino) e calcula a próxima etapa com base em um loop$x .

Cada loop interno é apenas uma atribuição. Estamos configurando $xno local apropriado igual a uma nova string "{0:x2}"usando o -foperador ormat. O x2aqui especifica uma saída hexadecimal de dois dígitos e a entrada é o lado direito do -foperador. O PowerShell possui um operador hexadecimal nativo para decimal 0x, portanto, essa longa expressão aninhada por parênteses está usando esse operador para converter o hex atual em números, subtraindo-o para encontrar a diferença que ainda está por vir (feito dividindo dinamicamente $baqui, como fizemos para $a, e usando o módulo para selecionar o elemento correto), dividindo pelas $jetapas restantes, convertendo para um[int] (O PowerShell faz o arredondamento do banqueiro por padrão) e subtrai essa contagem de etapas do hexadecimal atual para obter qual deve ser o próximo hexadecimal.

O resultado desse cálculo é armazenado novamente em $xtrês elementos hexadecimais. Isso é encapsulado em parênteses para criar uma cópia no pipeline e -joineditado em uma única sequência. Todas essas seqüências resultantes são deixadas no pipeline e a saída via implícita Write-Outputacontece na execução do programa.


Exemplo

Recebi 0ba7c5 e 6c0e50 pelas minhas duas cores, e TimmyD tem 6 caracteres.

PS C:\Tools\Scripts\golfing> .\rgb-gradients-generation.ps1 '0ba7c5' '6c0e50' 6
0ba7c5
1991b4
277ba3
356592
434f82
513971
5f2361
6c0e50

Exemplo de gradiente

AdmBorkBork
fonte
1

Python 2, 189 bytes

w='[int(%s[i:i+2],16)for i in range(0,6,2)]'
def f(a,b,n):
 l=lambda x,y:'%02x'%int((x*(n-i)+y*i)/n);c,d,e=eval(w%'a');f,g,h=eval(w%'b');n+=1
 for i in range(n+1):print l(c,f)+l(d,g)+l(e,h)

captura de tela gradiente

Andrew Epstein
fonte
Lindo par de cores, @AndrewEpstein ... Bom trabalho com o código!
WallyWest
1

Atualização final [Groovy] (199 bytes) - conforme solicitação

Não golfe

def g(a,b,n){
  (0..(1.0/n)).collect{
    c->
    x={s->s.split("(?<=\\G.{2})").collect{Integer.parseInt(it,16)}};
    (0..2).collect {
      (int)(x(a).get(it)*n*c+x(b).get(it)*(1-n*c))
    }.collect {
      String.format("%X", it)
    }.join()
  }
}
g('FFFFFF','000000',1/10​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​)​​​​​​​​​​​​​​

Golfe

g(a,b,n){(0..(1.0/n)).collect{c->x={s->s.split("(?<=\\G.{2})").collect{Integer.parseInt(it,16)}};(0..2).collect {(int)(x(a).get(it)*n*c+x(b).get(it)*(1-n*c))}.collect{String.format("%X",it)}.join()}}

Experimente a final aqui: https://groovyconsole.appspot.com/script/5130696796405760


VERSÕES ANTIGAS ABAIXO, DECLINADAS PELA OP


Groovy (123 bytes)

Golfe

def g(r,g,b,r2,g2,b2,s){(1..(1.0/s)).collect{c->[(int)(r*s*c+r2*(1-s*c)),(int)(g*s*c+g2*(1-s*c)),(int)(b*s*c+b2*(1-s*c))]}}

Não golfe

def g(r,g,b,r2,g2,b2,s){
  (1..(1.0/s)).collect {
    c ->
    [(int)(r*s*c+r2*(1-s*c)),(int)(g*s*c+g2*(1-s*c)),(int)(b*s*c+b2*(1-s*c))]
  }
}

Entradas

r,g,b -> Starting RGB Color
r2,g2,b2 -> Ending RGB Color
s -> Gradient step

Exemplo de saída

(00,00,00,255,255,255,.5)

resulta em

[
  [255, 255, 255]
  [127, 127, 127]
  [0, 0, 0]
]

Tente você mesmo: https://groovyconsole.appspot.com/script/5184465357766656

Com conversões hexadecimais incluídas

Acho que estou trapaceando também ... Aqui está o script com o uso de hex:

Novo código com conversões hexadecimais:

​    def g(r,g,b,r2,g2,b2,s){
      (0..(1.0/s)).collect {
        c ->
        String.format("%X", ((int)(r*s*c+r2*(1-s*c)))) +  String.format("%X", ((int)(g*s*c+g2*(1-s*c)))) + "" +  String.format("%X", ((int)(b*s*c+b2*(1-s*c))))
      }
    }

    g(126,34,166,218,26,33,0.0625)​

188 caracteres quando jogavam golfe:

def g(r,g,b,r2,g2,b2,s){(0..(1.0/s)).collect {c->String.format("%X",((int)(r*s*c+r2*(1-s*c))))+String.format("%X",((int)(g*s*c+g2*(1-s*c))))+String.format("%X",((int)(b*s*c+b2*(1-s*c))))}}

Saída para 000000 a FFFFFF e 16 (comprimento do nome de usuário)

g(00,00,00,255,255,255,0.0625).each{println it}​

Gradiente monocromático com 1/16 passos

Urna de polvo mágico
fonte
Err ... versão original ligeiramente inválida usada "(0 .. (1.0 / s))" "deveria ter sido" (1 .. (1.0 / s)) "".
Magic Octopus Urn
1
Oi @carusocomputing ... A entrada precisa ser de duas cadeias hexadecimais e um inteiro ... Não tenho certeza se o Groovy pode receber entradas dessa maneira, mas você não conseguiu acertar o resumo ... Você poderia atualizar seu código com base na entrada mencionada na seção Desafio?
WallyWest 7/09/16
{s-> s.split("(?<=\\G.{2})").collect{Integer.parseInt(it,16)}}('FFFFFF') Resultados em [255,255,255] Posso adicionar 62 bytes ao meu código usando essa conversão, se você realmente quiser.
Magic Octopus Urn
1
Wally, adicionei uma versão atualizada e subi para 199 a contagem final de bytes, com as conversões incluídas.
Magic Octopus Urn
1

R, 68 bytes

Há uma função interna que interpola duas cores:

a=scan(,'')
colorRampPalette(paste0("#",a[1:2]))(as.numeric(a[3])+2)

Entrada:

d9e7a5
3ef951
15

Saída: um vetor com valores

"#D9E7A5" "#CFE89F" "#C5E99A" "#BBEA95" "#B2EB90" "#A8EC8A" "#9EED85" "#95EE80"
"#8BF07B" "#81F175" "#78F270" "#6EF36B" "#64F466" "#5BF560" "#51F65B" "#47F756"
"#3EF951"

A especificação de cores em R requer um símbolo de hash.

Rampa de cores

Vamos traçar algo, como uma função:

filled.contour(outer(1:20, 1:20, function(x,y) sin(sqrt(x*y)/3)),
    col = colorRampPalette(paste0("#",a[1:2]))(as.numeric(a[3])+2))

sin (sqrt (x * y) / 3)

Andreï Kostyrka
fonte
Ótima resposta, mas o resumo pede para usar o número de etapas que houver no seu nome de usuário do PPCG, que conta com o espaço de 15 ... Você poderia atualizar sua resposta com base em FF3762 F08800 15?
WallyWest 8/09/16
@WallyWest Desculpe, eu tinha perdido aquela parte em que se obtém duas cores e conta o próprio nome de usuário. Agora a resposta deve ser totalmente compatível com a especificação!
Andreï Kostyrka 9/09/16
1

C, 175 169 168 bytes

i;j;x[6];f(a,b,n)char*a,*b;{char*f="%2x%2x%02x";for(n++;i<=n;i++,puts(""))for(j=sscanf(a,f,x,x+1,x+2)-sscanf(b,f,x+3,x+4,x+5);j++<printf(f+6,x[j]+(x[j+3]-x[j])*i/n););}

Ungolfed:

int i, j;
int x[3], y[3];

f(char *a, char *b, int n) {
  sscanf(a, "%2x%2x%2x", &x[0], &x[1], &x[2]);
  sscanf(b, "%2x%2x%2x", &y[0], &y[1], &y[2]);

  for(i = 0, n++; i <= n; i++) {
    for(j = 0; j < 3; j++)
      printf("%02x", x[j] + (y[j] - x[j]) * i / n);
    puts("");
  }
}

Obrigado ao @ h-walters por remover 5 bytes!

G. Sliepen
fonte
Lembrar o que a putssintaxe faz de novo?
WallyWest 9/09/16
É como printf(), mas não formata, apenas imprime a sequência especificada e adiciona uma nova linha.
G. Sliepen 9/09/16
Ah, então não há como jogar golfe ... C é um pouco restritivo assim, não é?
WallyWest 9/09/16
"então não há como jogar golfe" ... Claro que existe! Vá puts("")para a terceira parte do primeiro loop for ( ;depois de se tornar um ,antes) ... +0 bytes. No entanto, isso permite remover os chavetas após o segundo loop ... -2 bytes. Você pode salvar outro byte removendo 3 de j<3e substituindo-o por sua printfinstrução (isso é sorrateiro ... printf retornará apenas 2, mas ainda precisará avaliar pela terceira vez).
H Walters
... mais dois bytes podem ser salvos subtraindo os valores de retorno do sscanf um do outro (resultando em 0) e usando isso em vez do literal 0in j=0. Quando tudo estiver pronto, seu programa deverá ser 5 bytes mais curto e pelo menos 50% mais estranho.
H Walters #
1

sh + ImageMagick, 81 bytes

convert -size 1x$((2+$3)) gradient:#$1-#$2 -depth 8 txt:-|grep -o "[A-F0-9]\{6\}"

uso:

> ./grad.sh FF3762 F08800 9
FF3762
FE3F58
FC474E
FB4F45
F9573B
F86031
F66827
F5701D
F37814
F2800A
F08800

("profundidade 8" não é necessário se o seu IM for compilado com 8bpp como padrão)

Sparr
fonte