Rainbowlify uma imagem


23

Esse desafio é mudar gradualmente os tons de uma imagem para criar imagens bonitas como esta:

grande noite estrelada ( original )

Desafio

Escreva um programa ou função que inclua dois números inteiros não negativos e uma imagem em qualquer formato de arquivo de imagem comum de sua escolha (você pode seguir um caminho para a imagem ou para os dados brutos da imagem).

Vamos chamar o primeiro número inteiro de ciclos e o segundo número inteiro de deslocamento .

Também definiremos a etapa de ponto flutuante como ciclos de 360 vezes divididos pela área da imagem ou step = 360 * cycles / (image width * image height).

Para cada pixel P na imagem, movendo uma linha de cada vez, da esquerda para a direita, de cima para baixo (ou seja, na ordem de leitura, se os pixels forem letras), faça o seguinte:

  1. Aumente a tonalidade de P em graus de deslocamento (retornando de 360 ​​para 0, se necessário).

  2. Em seguida, aumentar compensado por etapa .

Salve, exiba ou imprima a imagem resultante em qualquer formato de arquivo de imagem comum.

Este procedimento aumenta incrementalmente a tonalidade de todos os pixels da imagem, fazendo ciclos em loop completo ao redor do arco-íris de tonalidades , começando inicialmente por compensar a tonalidade por offset .

Quando os ciclos são 1 e o deslocamento é 0, como na imagem da Noite estrelada acima, as linhas superior e inferior dos pixels praticamente não têm mudança de tonalidade, mas há um ciclo de cores completo.

Detalhes

  • Os ciclos podem ser qualquer número inteiro não negativo, mas você pode assumir que o deslocamento é de 0 a 359, inclusive.

  • Quando o ciclo é 0, todos os pixels da imagem terão sua tonalidade alterada exatamente como o deslocamento, pois a etapa também deve ser 0. (Nesse caso, se o deslocamento for 0, a imagem não será alterada.)

  • Você pode assumir que ciclos e deslocamento são inseridos como flutuadores, se desejado (por exemplo, em 1.0vez de 1). (Percebo que eles não precisam ser números inteiros, apenas simplifica o desafio.)

  • "Matiz" refere-se à versão do espaço de cores RGB, comum nos modelos de cores HSL / HSV .

Exemplos

Original:

rio

Ciclos = 1, deslocamento = 0:

saída do rio 1

Ciclos = 1, deslocamento = 180:

saída do rio 2

Original:

esferas

Ciclos = 2, deslocamento = 60:

saída de esferas

Original:

pôr do sol
(Obrigado ArtOfCode .)

Ciclos = 1, deslocamento = 120:

saída do sol

Original:

maçaneta
(Obrigado, maçaneta da porta .)

Ciclos = 1, deslocamento = 0:

maçaneta de saída 1

Ciclos = 4, deslocamento = 0:

maçaneta de saída 2

Ciclos = 200, deslocamento = 0:

maçaneta de saída 3

Ciclos = 30000, deslocamento = 0:

saída da maçaneta da porta 4

(Essas imagens podem não ser perfeitas em pixels devido à compressão do imgur.)

Pontuação

O código mais curto em bytes vence. O desempatador é a resposta votada mais alta.

As respostas que postarem suas próprias imagens de teste interessantes receberão mais pontos de brownie de mim.


6
Parece que a maçaneta da porta está fumando maconha.
Denker

Presumo que uma matriz de números inteiros como valor de retorno seria incluído em "ou saída bruta"?
Marv

2
@Marv No. Quero dizer, os bytes brutos da imagem (no formato comum escolhido, digamos ppm ) podem ser canalizados diretamente para o stdout.
Hobbies de Calvin

2
As saídas precisam ser idênticas aos seus exemplos? Estou recebendo imagens ligeiramente diferentes.
DJMcMayhem

1
@DrGreenEggsandHamDJ Se você não pode dizer visualmente a diferença, provavelmente está bem. A perfeição de pixels não é necessária (o imgur pode ter compactado minhas imagens com perdas de qualquer maneira).
Hobbies de Calvin

Respostas:


8

Pyth, 86 bytes, programa completo

=N.tE7=Z*6*.n0cEl.n'zMmhtS[0255ss*VG.>+Lc-1.tH1 3[.tH1Kc.tH0@3 2_K)d)3.wmmgk~-NZd'z

Pyth não possui conversões de espaço de cores integradas - este é o negócio real.

Recebe a entrada no seguinte formato no stdin:

input_filename.png
offset
cycles

A imagem de saída é gravada em o.png.


Isso funciona girando o cubo de cores em torno de sua diagonal e fixando quaisquer valores fora do intervalo.

Se aé o ângulo a ser girado e r, g, ba cor de entrada, calculamos a nova cor r', g', b'por:

o = cos(a), i = sin(a) / sqrt(3)
n = (1 - o) / 3
m = [n + o, n - i, n + i]
clamp(c) = max(0, min(255, c))
r' = clamp(r*m[0] + g*m[1] + b*m[2])
g' = clamp(r*m[2] + g*m[0] + b*m[1])
b' = clamp(r*m[1] + g*m[2] + b*m[0])

6

Python, 379 bytes

from PIL.Image import*
from colorsys import*
def f(H,c,I):
 i=open(I);x,y=i.size;S=1.*c/(x*y);r,g,b=i.split();R=[];G=[];B=[]
 for x,y,z in zip(r.getdata(),g.getdata(),b.getdata()):
  e=255.;h,s,v=rgb_to_hsv(x/e,y/e,z/e);t=hsv_to_rgb(h+H,s,v);H=H+S%1.;x,y,z=[int(x*e)for x in t];R.append(x);G.append(y);B.append(z)
 p=Image.putdata;p(r,R);p(g,G);p(b,B);return merge('RGB',(r,g,b))

Isso leva um caminho para a .jpgcomo entrada. Não vai funcionar com png, embora você pode mudar r,g,b=i.split();para r,g,b=i.split()[:3];carregar uma imagem png.

Aqui estão algumas imagens:

Original:

insira a descrição da imagem aqui

Deslocamento: 0, Ciclos: 4

insira a descrição da imagem aqui

Original:

insira a descrição da imagem aqui

Deslocamento 0, 1 ciclo:

insira a descrição da imagem aqui

Original:

insira a descrição da imagem aqui

Deslocamento 0, 2,5 ciclos:

insira a descrição da imagem aqui


6

Java (programa completo), 491 488 bytes (Obrigado @Geobits)

import java.awt.*;import java.io.*;import static javax.imageio.ImageIO.*;class Q{public static void main(String[]v)throws Exception{File f=new File(v[2]);java.awt.image.BufferedImage b=read(f);for(int i=0,j,h=b.getHeight(),w=b.getWidth();i<h;i++)for(j=0;j<w;){Color c=new Color(b.getRGB(j,i));float[]a=new float[3];c.RGBtoHSB(c.getRed(),c.getGreen(),c.getBlue(),a);b.setRGB(j++,i,c.HSBtoRGB((a[0]+Float.valueOf(v[1])/360+(i*w+j)*Float.valueOf(v[0])/w/h)%1,a[1],a[2]));}write(b,"png",f);}}

Ungolfed

import java.awt.*;
import java.io.*;

import static javax.imageio.ImageIO.*;

class A79200 {
    public static void main(String[] v) throws Exception {
        File file = new File(v[2]);
        java.awt.image.BufferedImage image = read(file);
        for (int i = 0, j, height = image.getHeight(), width = image.getWidth(); i < height; i++)
            for (j = 0; j < width; ) {
                Color color = new Color(image.getRGB(j, i));
                float[] arr = new float[3];
                color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), arr);
                image.setRGB(j++, i, color.HSBtoRGB((arr[0] + Float.valueOf(v[1]) / 360 + (i * width + j) * Float.valueOf(v[0]) / width / height) % 1, arr[1], arr[2]));
            }
        write(image, "png", file);
    }
}

Explicação

  • Uso: Bem direto. Compile com java -c Q.java. Corra com java Q <cycles> <offset> <imagepath>. Substituirá a imagem existente, portanto, tenha cuidado.

  • Eu ia fazer uma solução apenas de método no começo, mas não sabia muito bem como lidar com as importações, então imaginei que iria usar completo , provavelmente isso não vai ganhar de qualquer maneira: ^)

Resultados:

Image 1: 1 cycle, 0 offset

1

Image 1: 1 cycle, 180 offset

2

Image 2: 2 cycles, 60 offset

3

Image 3: 1 cycle, 120 offset

4

Image 4: 1 cycle, 0 offset

5

Image 4: 4 cycles, 0 offset

6

Image 4: 200 cycles, 0 offset

7

Bonus: The Starry Night, 1 cycle, 0 offset

insira a descrição da imagem aqui


1
Para referência futura, você pode importar para respostas somente de método da mesma maneira que faria normalmente. Apenas coloque-os fora do corpo do método e conte os bytes. Você também pode qualificar totalmente as classes em vez de importá-las se precisar apenas uma vez, para salvar alguns bytes em alguns casos.
Geobits

Além disso, existe um motivo para você importar em java.io.Filevez de java.io.*?
Geobits

Obrigado, bom saber. E segundo, não, não há razão. Bom ponto.
Marv

Por que import ** static**, não apenas import?
Solomon Ucko

1
Para que eu possa ligar ImageIO::reade ImageIO::writesem precisar ImageIO.acrescentar: Isso adiciona 9 bytes ( static .*), mas salva 16 ( ImageIO.duas vezes).
Marv
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.