Regenbogen ein Bild

23

Diese Herausforderung besteht darin, die Farbtöne in einem Bild schrittweise zu verschieben, um hübsche Bilder wie das folgende zu erstellen:

große sternenklare Nacht ( original )

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die zwei nicht negative Ganzzahlen und ein Bild in einem beliebigen gängigen Bilddateiformat Ihrer Wahl enthält (Sie können einen Pfad zum Bild oder zu den Rohbilddaten angeben).

Wir nennen die erste Ganzzahl die Zyklen und die zweite Ganzzahl den Offset .

Wir definieren den Gleitkomma- Schritt auch als 360-malige Zyklen geteilt durch die Bildfläche oderstep = 360 * cycles / (image width * image height) .

Führen Sie für jedes Pixel P im Bild, das sich zeilenweise von links nach rechts und von oben nach unten bewegt (dh in der Lesereihenfolge, wenn die Pixel Buchstaben waren), die folgenden Schritte aus:

  1. Erhöhen Sie den Farbton von P um Versatzgrade (ggf. von 360 auf 0).

  2. Dann erhöht Offset von Schritt .

Speichern, Anzeigen oder Ausgeben des resultierenden Bildes in einem beliebigen gängigen Bilddateiformat.

Durch diesen Vorgang wird der Farbton aller Pixel im Bild inkrementell erhöht, und es werden vollständige Schleifen um den Farbtonregenbogen erstellt , wobei zunächst der Farbton um den Versatz versetzt wird .

Wenn die Anzahl der Zyklen 1 und der Versatz 0 beträgt, wie im obigen Sternennachtbild, haben die oberen und unteren Pixelreihen praktisch keine Farbtonverschiebung, dazwischen liegt jedoch ein vollständiger Farbzyklus.

Einzelheiten

  • Bei Zyklen kann es sich um eine beliebige nicht negative Ganzzahl handeln. Sie können jedoch davon ausgehen, dass der Offset zwischen 0 und einschließlich 359 liegt.

  • Wenn die Anzahl der Zyklen 0 ist, wird der Farbton jedes Pixels im Bild genau um einen Versatz verschoben, da der Schritt ebenfalls 0 sein muss. (In diesem Fall ändert sich das Bild überhaupt nicht, wenn der Versatz 0 ist.)

  • Sie können davon ausgehen, dass Zyklen und Offset bei Bedarf als Gleitkommazahlen eingegeben werden (dh 1.0anstelle von 1). (Mir ist klar, dass es sich überhaupt nicht um ganze Zahlen handeln muss. Das macht die Herausforderung nur einfacher.)

  • "Farbton" bezieht sich auf die in HSL / HSV-Farbmodellen übliche RGB-Farbraumversion .

Beispiele

Original:

Fluss

Zyklen = 1, Offset = 0:

Flussleistung 1

Zyklen = 1, Offset = 180:

Flussleistung 2

Original:

Kugeln

Zyklen = 2, Versatz = 60:

Kugeln ausgegeben

Original:

Sonnenuntergang
(Danke ArtOfCode .)

Zyklen = 1, Offset = 120:

Sonnenuntergang Ausgabe

Original:

Türknauf
(Danke Türknauf .)

Zyklen = 1, Offset = 0:

Türklinkenausgang 1

Zyklen = 4, Offset = 0:

Türklinkenausgang 2

Zyklen = 200, Offset = 0:

Türklinkenausgang 3

Zyklen = 30000, Versatz = 0:

Türklinkenausgang 4

(Diese Bilder sind möglicherweise nicht pixelgenau, da sie imgur komprimiert wurden.)

Wertung

Der kürzeste Code in Bytes gewinnt. Tiebreaker ist höher gestimmte Antwort.

Antworten, die ihre eigenen cool aussehenden Testbilder posten, werden mehr Brownie-Punkte von mir bekommen.

Calvins Hobbys
quelle
6
Das sieht so aus, als würde Doorknob einen Topf rauchen.
Denker
Ich nehme an, ein Array von Ganzzahlen als Rückgabewert würde in "oder Ausgabe roh" enthalten sein?
Marv
2
@Marv Nein. Ich meine, die unformatierten Bytes des Bildes (in Ihrem gewählten allgemeinen Format, z. B. ppm ) können direkt an stdout weitergeleitet werden.
Calvins Hobbys
2
Müssen die Ausgaben mit Ihren Beispielen identisch sein? Ich bekomme etwas andere Bilder.
DJMcMayhem
1
@DrGreenEggsandHamDJ Wenn Sie visuell keinen Unterschied feststellen können, ist dies wahrscheinlich in Ordnung. Pixel-Perfektion ist nicht erforderlich (Bild kann meine Bilder trotzdem verlustbehaftet komprimiert haben).
Calvins Hobbys

Antworten:

8

Pyth, 86 Bytes, volles Programm

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

Pyth hat keine eingebauten Farbraumkonvertierungen - das ist der wahre Deal.

Nimmt Eingaben im folgenden Format auf stdin vor:

input_filename.png
offset
cycles

Das Ausgabebild wird geschrieben o.png.


Dies funktioniert, indem der Farbwürfel um seine Diagonale gedreht und dann alle Werte außerhalb des Bereichs geklemmt werden.

Ist ader Winkel, um den gedreht werden soll, und r, g, bist die Eingabefarbe, berechnen wir die neue Farbe r', g', b'durch:

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

Dies nimmt einen Weg zu a .jpg als Eingabe. Es wird nicht mit png arbeiten, obwohl Sie ändern können , r,g,b=i.split();umr,g,b=i.split()[:3]; ein PNG - Bild zu laden.

Hier sind einige Bilder:

Original:

Bildbeschreibung hier eingeben

Offset: 0, Zyklen: 4

Bildbeschreibung hier eingeben

Original:

Bildbeschreibung hier eingeben

Offset 0, 1 Zyklus:

Bildbeschreibung hier eingeben

Original:

Bildbeschreibung hier eingeben

Offset 0, 2,5 Zyklen:

Bildbeschreibung hier eingeben

DJMcMayhem
quelle
6

Java (Volles Programm), 491 488 Bytes (Danke @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);
    }
}

Erläuterung

  • Verbrauch: Ziemlich unkompliziert. Kompilieren mit java -c Q.java. Laufen Sie mit java Q <cycles> <offset> <imagepath>. Überschreibt das vorhandene Image, seien Sie also vorsichtig.

  • Anfangs wollte ich nur eine Methode als Lösung entwickeln, aber ich wusste nicht genau, wie ich mit Importen umgehen sollte, also dachte ich mir, ich würde voll auf , das wird wahrscheinlich sowieso nicht gewinnen: ^)

Ergebnisse:

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

Bildbeschreibung hier eingeben

Marv
quelle
1
Zum späteren Nachschlagen können Sie nur methodenbezogene Antworten genauso importieren, wie Sie es normalerweise tun würden. Setzen Sie sie einfach außerhalb des Methodenkörpers und zählen Sie die Bytes. Sie können Klassen auch vollständig qualifizieren, anstatt sie zu importieren, wenn Sie sie nur einmal benötigen, um in einigen Fällen einige Bytes zu sparen.
Geobits
Gibt es auch einen Grund, warum Sie importieren java.io.Fileanstatt java.io.*?
Geobits
Danke, gut zu wissen. Und zweitens, nein, es gibt keinen Grund. Guter Punkt.
Marv
Warum import ** staticnicht nur ** import?
Solomon Ucko
1
Damit ich anrufen kann ImageIO::readund ImageIO::writeohne Voranstellen ImageIO.: Das addiert 9 Bytes ( static .*), spart aber 16 ( ImageIO.zweimal).
Marv