Rainbowlify An Image
Pyth, 86 bytes, full program
=N.tE7=Z*6*.n0cEl.n'zMmhtS[0255ss*VG.>+Lc-1.tH1 3[.tH1Kc.tH0@3 2_K)d)3.wmmgk~-NZd'z
Pyth doesn't have built-in color space conversions - this is the real deal.
Takes input in the following format on stdin:
input_filename.png
offset
cycles
The output image is written to o.png
.
This works by rotating the color cube around its diagonal, and then clamping any values outside of the range.
If a
is the angle to rotate by, and r, g, b
is the input color, we calculate the new color r', g', b'
by:
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])
Java (Full program), 491 488 bytes (Thanks @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);
}
}
Explanation
Usage: Pretty straightforward. Compile with
java -c Q.java
. Run withjava Q <cycles> <offset> <imagepath>
. Will override the existing image, so be careful.I was gonna make a method only solution at first but I didn't quite know how to handle imports on those, so I figured I'd go full java, this is probably not going to win anyways :^)
Results:
Image 1: 1 cycle, 0 offset
Image 1: 1 cycle, 180 offset
Image 2: 2 cycles, 60 offset
Image 3: 1 cycle, 120 offset
Image 4: 1 cycle, 0 offset
Image 4: 4 cycles, 0 offset
Image 4: 200 cycles, 0 offset
Bonus: The Starry Night, 1 cycle, 0 offset
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))
This takes a path to a .jpg
as input. It will not work with png, although you can change r,g,b=i.split();
to r,g,b=i.split()[:3];
to load a png image.
Here are some images:
Original:
Offset: 0, Cycles: 4
Original:
Offset 0, 1 cycle:
Original:
Offset 0, 2.5 cycles: