Rainbowlify una imagen

23

Este desafío se trata de cambiar gradualmente los tonos en una imagen para hacer imágenes bonitas como esta:

gran noche estrellada ( original )

Reto

Escriba un programa o función que tome dos enteros no negativos y una imagen en cualquier formato de archivo de imagen común que elija (puede tomar un camino hacia la imagen o los datos de la imagen sin procesar).

Llamaremos al primer entero los ciclos y al segundo entero el desplazamiento .

También definiremos el paso de coma flotante como ciclos de 360 veces divididos por el área de la imagen, o step = 360 * cycles / (image width * image height).

Para cada píxel P en la imagen, moviendo una fila a la vez, de izquierda a derecha, de arriba a abajo (es decir, en orden de lectura si los píxeles fueran letras), haga lo siguiente:

  1. Aumente el tono de P en grados de desplazamiento (girando de 360 ​​a 0 si es necesario).

  2. Luego aumente la compensación por pasos .

Guarde, muestre o imprima la imagen resultante en cualquier formato de archivo de imagen común.

Este procedimiento aumenta gradualmente el tono de todos los píxeles en la imagen, haciendo ciclos de bucles completos alrededor del arco iris de tono , comenzando por compensar inicialmente el tono por desplazamiento .

Cuando los ciclos son 1 y el desplazamiento es 0, como en la imagen Starry Night anterior, las filas de píxeles superior e inferior prácticamente no tienen cambio de tono, pero en el medio hay un ciclo de color completo.

Detalles

  • Los ciclos pueden ser cualquier número entero no negativo, pero puede suponer que el desplazamiento es de 0 a 359 inclusive.

  • Cuando los ciclos son 0, cada píxel de la imagen tendrá su tonalidad desplazada exactamente por desplazamiento, ya que el paso también debe ser 0. (En este caso, si el desplazamiento es 0, la imagen no cambia en absoluto).

  • Si lo desea, puede suponer que los ciclos y el desplazamiento se introducen como flotantes (es decir, en 1.0lugar de 1). (Me doy cuenta de que no necesitan ser enteros en absoluto, solo hace que el desafío sea más simple).

  • "Tono" se refiere a la versión de espacio de color RGB, común en los modelos de color HSL / HSV .

Ejemplos

Original:

río

Ciclos = 1, desplazamiento = 0:

salida del río 1

Ciclos = 1, desplazamiento = 180:

salida del río 2

Original:

esferas

Ciclos = 2, desplazamiento = 60:

salida de esferas

Original:

puesta de sol
(Gracias ArtOfCode .)

Ciclos = 1, desplazamiento = 120:

salida del atardecer

Original:

Perilla de la puerta
(Gracias pomo de la puerta )

Ciclos = 1, desplazamiento = 0:

pomo de la puerta de salida 1

Ciclos = 4, desplazamiento = 0:

pomo de la puerta de salida 2

Ciclos = 200, desplazamiento = 0:

pomo de la puerta de salida 3

Ciclos = 30000, desplazamiento = 0:

pomo de la puerta de salida 4

(Estas imágenes pueden no ser perfectas en píxeles debido a que imgur las comprime).

Tanteo

El código más corto en bytes gana. Tiebreaker es la respuesta más votada.

Las respuestas que publiquen sus propias imágenes de prueba de aspecto genial obtendrán más puntos brownie de mí.

Pasatiempos de Calvin
fuente
66
Parece que Doorknob está fumando marihuana.
Denker
Supongo que una matriz de enteros como valor de retorno se incluiría en "o salida sin formato"?
Marv
2
@Marv No. Quiero decir que los bytes sin procesar de la imagen (en el formato común elegido, digamos ppm ) se pueden canalizar directamente a stdout.
Aficiones de Calvin
2
¿Las salidas tienen que ser idénticas a sus ejemplos? Estoy obteniendo imágenes ligeramente diferentes.
DJMcMayhem
1
@DrGreenEggsandHamDJ Si no puede distinguir visualmente la diferencia, entonces probablemente esté bien. No se requiere la perfección de píxeles (de todos modos, imgur puede haber comprimido mis imágenes con pérdida).
Aficiones de Calvin

Respuestas:

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 no tiene conversiones de espacio de color incorporadas: este es el verdadero negocio.

Toma entrada en el siguiente formato en stdin:

input_filename.png
offset
cycles

La imagen de salida se escribe en o.png.


Esto funciona girando el cubo de color alrededor de su diagonal y luego sujetando cualquier valor fuera del rango.

Si aes el ángulo para rotar y r, g, bes el color de entrada, calculamos el nuevo color 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])
orlp
fuente
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))

Esto toma un camino hacia a .jpgcomo entrada. No funcionará con png, aunque puede cambiar r,g,b=i.split();a r,g,b=i.split()[:3];para cargar una imagen png.

Aquí hay algunas imágenes:

Original:

ingrese la descripción de la imagen aquí

Offset: 0, Ciclos: 4

ingrese la descripción de la imagen aquí

Original:

ingrese la descripción de la imagen aquí

Offset 0, 1 ciclo:

ingrese la descripción de la imagen aquí

Original:

ingrese la descripción de la imagen aquí

Offset 0, 2.5 ciclos:

ingrese la descripción de la imagen aquí

DJMcMayhem
fuente
6

Java (programa completo), 491 488 bytes (Gracias @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);}}

Sin golf

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);
    }
}

Explicación

  • Uso: bastante sencillo. Compilar con java -c Q.java. Corre con java Q <cycles> <offset> <imagepath>. Anulará la imagen existente, así que tenga cuidado.

  • Al principio iba a hacer una solución de método único, pero no sabía cómo manejar las importaciones de esos, así que pensé que iría a completo , de todos modos esto probablemente no va a ganar: ^)

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 4

Image 4: 1 cycle, 0 offset

5 5

Image 4: 4 cycles, 0 offset

6 6

Image 4: 200 cycles, 0 offset

7 7

Bonus: The Starry Night, 1 cycle, 0 offset

ingrese la descripción de la imagen aquí

Marv
fuente
1
Para referencia futura, puede importar para respuestas de solo método de la misma manera que lo haría normalmente. Simplemente colóquelos fuera del cuerpo del método y cuente los bytes. También puede calificar completamente las clases en lugar de importarlas si solo las necesitará una vez, para ahorrar algunos bytes en algunos casos.
Geobits
Además, ¿hay alguna razón para importar en java.io.Filelugar de java.io.*?
Geobits
Gracias, es bueno saberlo. Y segundo, no, no hay razón. Buen punto.
Marv
¿Por qué import ** static**, no solo import?
Solomon Ucko
1
Para poder llamar ImageIO::ready ImageIO::writesin tener que anteponer ImageIO.: Esto agrega 9 bytes ( static .*) pero ahorra 16 ( ImageIO.dos veces).
Marv