Rainbowlify An Image

23

Ce défi consiste à changer progressivement les teintes d'une image pour créer de jolies images comme celle-ci:

grande nuit étoilée ( original )

Défi

Écrivez un programme ou une fonction qui accepte deux nombres entiers non négatifs et une image dans n'importe quel format de fichier d'image courant de votre choix (vous pouvez prendre un chemin vers l'image ou les données d'image brutes).

Nous appellerons le premier entier les cycles et le deuxième entier le décalage .

Nous allons également définir à virgule flottante étape comme 360 fois les cycles divisé par la zone de l'image, ou step = 360 * cycles / (image width * image height).

Pour chaque pixel P de l'image, en déplaçant une ligne à la fois, de gauche à droite, de haut en bas (c'est-à-dire dans l'ordre de lecture si les pixels étaient des lettres), procédez comme suit:

  1. Augmentez la teinte de P par degrés de décalage (boucle de 360 ​​à 0 si nécessaire).

  2. Augmentez ensuite le décalage par étape .

Enregistrez, affichez ou affichez en brut l'image résultante dans n'importe quel format de fichier d'image courant.

Cette procédure augmente progressivement la teinte de tous les pixels de l'image, faisant des cycles de boucles complètes autour de l' arc -en- ciel de teinte , en commençant par compenser initialement la teinte par décalage .

Lorsque les cycles est 1 et le décalage est 0, comme dans l'image de la nuit étoilée ci-dessus, les rangées de pixels supérieure et inférieure n'ont pratiquement pas de décalage de teinte, mais entre les deux, il y a un cycle de couleur complet.

Détails

  • Les cycles peuvent être n'importe quel entier non négatif, mais vous pouvez supposer que le décalage est compris entre 0 et 359 inclus.

  • Lorsque cycles est 0, chaque pixel de l'image aura sa teinte décalée par exactement décalage depuis étape doit être 0 aussi. (Dans ce cas, si le décalage est égal à 0, l'image ne change pas du tout.)

  • Vous pouvez supposer que les cycles et le décalage sont saisis sous forme de flottants si vous le souhaitez (c'est- 1.0à- dire au lieu de 1). (Je me rends compte qu'ils ne doivent pas du tout être des entiers, cela rend le défi plus simple.)

  • "Teinte" fait référence à la version de l'espace colorimétrique RVB, courante dans les modèles de couleurs HSL / HSV .

Exemples

Original:

rivière

Cycles = 1, décalage = 0:

sortie de la rivière 1

Cycles = 1, décalage = 180:

sortie de la rivière 2

Original:

sphères

Cycles = 2, décalage = 60:

sortie de sphères

Original:

le coucher du soleil
(Merci ArtOfCode .)

Cycles = 1, décalage = 120:

sortie au coucher du soleil

Original:

poignée de porte
(Merci Poignée de porte .)

Cycles = 1, décalage = 0:

sortie poignée de porte 1

Cycles = 4, décalage = 0:

sortie de la poignée de porte 2

Cycles = 200, décalage = 0:

poignée de porte sortie 3

Cycles = 30000, décalage = 0:

sortie de la poignée de porte 4

(Ces images peuvent ne pas être parfaites en pixels en raison de l'imgur de les compresser.)

Notation

Le code le plus court en octets gagne. Tiebreaker est la réponse la plus votée.

Les réponses qui affichent leurs propres images de test au look cool recevront plus de points brownie de ma part.

Loisirs de Calvin
la source
6
On dirait que la poignée de porte fume du pot.
Denker
Je suppose qu'un tableau d'entiers comme valeur de retour serait inclus dans "ou sortie brute"?
Marv
2
@Marv Non. Je veux dire que les octets bruts de l'image (dans le format commun que vous avez choisi, disons ppm ) peuvent être dirigés directement vers la sortie standard.
Calvin's Hobbies
2
Les résultats doivent-ils être identiques à vos exemples? Je reçois des images légèrement différentes.
DJMcMayhem
1
@DrGreenEggsandHamDJ Si vous ne pouvez pas faire de différence visuelle, c'est très bien. La perfection des pixels n'est pas requise (imgur peut avoir compressé avec perte mes images de toute façon).
Les loisirs de Calvin

Réponses:

8

Pyth, 86 octets, programme complet

=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'a pas de conversions d'espace colorimétrique intégrées - c'est la vraie affaire.

Prend l'entrée au format suivant sur stdin:

input_filename.png
offset
cycles

L'image de sortie est écrite o.png.


Cela fonctionne en faisant pivoter le cube de couleur autour de sa diagonale, puis en fixant toutes les valeurs en dehors de la plage.

Si aest l'angle de rotation et r, g, bla couleur d'entrée, nous calculons la nouvelle couleur r', g', b'par:

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
la source
6

Python, 379 octets

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

Cela prend un chemin vers une .jpgentrée. Il ne fonctionnera pas avec .png, mais vous pouvez changer r,g,b=i.split();pour r,g,b=i.split()[:3];charger une image .png.

Voici quelques images:

Original:

entrez la description de l'image ici

Décalage: 0, Cycles: 4

entrez la description de l'image ici

Original:

entrez la description de l'image ici

Décalage 0, 1 cycle:

entrez la description de l'image ici

Original:

entrez la description de l'image ici

Décalage 0, 2,5 cycles:

entrez la description de l'image ici

DJMcMayhem
la source
6

Java (programme complet), 491 488 octets (Merci @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);}}

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

Explication

  • Utilisation: assez simple. Compilez avec java -c Q.java. Courez avec java Q <cycles> <offset> <imagepath>. Remplacera l'image existante, alors soyez prudent.

  • J'allais faire une solution uniquement méthode au début, mais je ne savais pas trop comment gérer les importations sur ceux-ci, alors je me suis dit que j'irais en complet , cela ne gagnera probablement pas de toute façon: ^)

Résultats:

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

entrez la description de l'image ici

Marv
la source
1
Pour référence future, vous pouvez effectuer des importations pour les réponses de méthode uniquement exactement comme vous le feriez normalement. Mettez-les simplement en dehors du corps de la méthode et comptez les octets. Vous pouvez également qualifier pleinement les classes au lieu de les importer si vous n'en aurez besoin qu'une seule fois, pour économiser quelques octets dans certains cas.
Geobits
De plus, y a-t-il une raison pour laquelle vous importez à la java.io.Fileplace java.io.*?
Geobits
Merci, bon à savoir. Et deuxièmement, non, il n'y a aucune raison. Bon point.
Marv
Pourquoi import ** static**, pas seulement import?
Solomon Ucko
1
Pour que je puisse appeler ImageIO::readet ImageIO::writesans avoir à ImageIO.ajouter: cela ajoute 9 octets ( static .*) mais enregistre 16 ( ImageIO.deux fois).
Marv