Rainbowlify một hình ảnh


23

Thử thách này là về việc chuyển dần màu sắc trong một hình ảnh để tạo ra những bức ảnh đẹp như thế này:

đêm đầy sao ( bản gốc )

Thử thách

Viết chương trình hoặc hàm có hai số nguyên không âm và hình ảnh ở bất kỳ định dạng tệp hình ảnh phổ biến nào bạn chọn (bạn có thể đi theo đường dẫn đến hình ảnh hoặc dữ liệu hình ảnh thô).

Chúng ta sẽ gọi số nguyên đầu tiên là chu kỳ và số nguyên thứ hai là phần .

Chúng tôi cũng sẽ xác định bước dấu phẩy động là chu kỳ 360 lần chia cho diện tích hình ảnh, hoặc step = 360 * cycles / (image width * image height).

Đối với mỗi pixel P trong hình ảnh, di chuyển một hàng tại một thời điểm, từ trái sang phải, từ trên xuống dưới (nghĩa là theo thứ tự đọc nếu các pixel là chữ cái), hãy làm như sau:

  1. Tăng màu sắc của P bằng độ (lặp lại từ 360 đến 0 nếu cần thiết).

  2. Sau đó tăng theo từng bước .

Lưu, hiển thị hoặc xuất hình ảnh thô ở bất kỳ định dạng tệp hình ảnh phổ biến nào.

Thủ tục này từng bước làm tăng màu sắc của tất cả các điểm ảnh trong hình ảnh, làm cho chu kỳ vòng đầy đủ xung quanh cầu vồng màu sắc , bắt đầu bằng việc ban đầu bù sắc bởi bù đắp .

Khi chu kỳ là 1 và độ lệch là 0, như trong hình ảnh Starry Night ở trên, các hàng pixel trên cùng và dưới cùng thực tế không có sự thay đổi màu sắc nhưng ở giữa có một chu kỳ màu đầy đủ.

Chi tiết

  • Chu kỳ có thể là bất kỳ số nguyên không âm nào nhưng bạn có thể giả sử rằng giá trị là từ 0 đến 359.

  • Khi chu kỳ bằng 0, mọi pixel trong ảnh sẽ bị thay đổi màu sắc bằng cách chính xác do bước cũng phải bằng 0. (Trong trường hợp này nếu độ lệch bằng 0 thì hình ảnh hoàn toàn không thay đổi.)

  • Bạn có thể giả sử chu kỳ là đầu vào dưới dạng float nếu muốn (nghĩa là 1.0thay vì 1). (Tôi nhận ra rằng họ không cần phải là số nguyên, nó chỉ làm cho thử thách trở nên đơn giản hơn.)

  • "Hue" dùng để chỉ phiên bản không gian màu RGB, phổ biến trong các mô hình màu HSL / HSV .

Ví dụ

Nguyên:

con sông

Chu kỳ = 1, bù = 0:

sản lượng sông 1

Chu kỳ = 1, bù = 180:

sản lượng sông 2

Nguyên:

hình cầu

Chu kỳ = 2, bù = 60:

sản lượng hình cầu

Nguyên:

Hoàng hôn
(Cảm ơn ArtOfCode .)

Chu kỳ = 1, bù = 120:

hoàng hôn đầu ra

Nguyên:

tay nắm cửa
(Cảm ơn Doorknob .)

Chu kỳ = 1, bù = 0:

tay nắm cửa ra 1

Chu kỳ = 4, bù = 0:

tay nắm cửa ra 2

Chu kỳ = 200, bù = 0:

tay nắm cửa ra 3

Chu kỳ = 30000, bù = 0:

tay nắm cửa ra 4

(Những hình ảnh này có thể không phải là pixel hoàn hảo do imgur nén chúng.)

Chấm điểm

Mã ngắn nhất tính bằng byte thắng. Tiebreaker là câu trả lời bình chọn cao hơn.

Câu trả lời rằng đăng hình ảnh thử nghiệm mát mẻ của riêng họ sẽ nhận được nhiều điểm brownie từ tôi.


6
Có vẻ như Doorknob đang hút một số nồi.
Denker

Tôi đoán một mảng các số nguyên là giá trị trả về sẽ được bao gồm trong "hoặc đầu ra thô"?
Marv

2
@Marv Không. Tôi có nghĩa là các byte thô của hình ảnh (ở định dạng phổ biến bạn đã chọn, giả sử ppm ) có thể được dẫn trực tiếp đến thiết bị xuất chuẩn.
Sở thích của Calvin

2
Các đầu ra có phải giống hệt với ví dụ của bạn không? Tôi đang nhận được một số hình ảnh hơi khác nhau.
DJMcMayhem

1
@DrGreenEggsandoutDJ Nếu bạn không thể thấy sự khác biệt một cách trực quan thì có lẽ nó ổn. Không cần phải hoàn thiện pixel (imgur có thể đã nén hình ảnh của tôi một cách mất mát).
Sở thích của Calvin

Câu trả lời:


8

Pyth, 86 byte, chương trình đầy đủ

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

Pyth không có chuyển đổi không gian màu tích hợp - đây là thỏa thuận thực sự.

Đưa đầu vào theo định dạng sau trên stdin:

input_filename.png
offset
cycles

Hình ảnh đầu ra được ghi vào o.png.


Điều này hoạt động bằng cách xoay khối màu xung quanh đường chéo của nó, và sau đó kẹp bất kỳ giá trị nào ngoài phạm vi.

Nếu alà góc để xoay theo và r, g, blà màu đầu vào, chúng ta tính toán màu mới r', g', b'bằng cách:

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 byte

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

Điều này có một đường dẫn đến một .jpgđầu vào. Nó sẽ không làm việc với png, mặc dù bạn có thể thay đổi r,g,b=i.split();để r,g,b=i.split()[:3];tải một hình ảnh png.

Dưới đây là một số hình ảnh:

Nguyên:

nhập mô tả hình ảnh ở đây

Bù đắp: 0, Chu kỳ: 4

nhập mô tả hình ảnh ở đây

Nguyên:

nhập mô tả hình ảnh ở đây

Bù đắp 0, 1 chu kỳ:

nhập mô tả hình ảnh ở đây

Nguyên:

nhập mô tả hình ảnh ở đây

Bù đắp 0, 2,5 chu kỳ:

nhập mô tả hình ảnh ở đây


6

Java (Chương trình đầy đủ), 491 488 byte (Cảm ơn @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);}}

Bị đánh cắp

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

Giải trình

  • Cách sử dụng: Khá đơn giản. Biên dịch với java -c Q.java. Chạy với java Q <cycles> <offset> <imagepath>. Sẽ ghi đè hình ảnh hiện có, vì vậy hãy cẩn thận.

  • Lúc đầu tôi sẽ tạo ra một giải pháp duy nhất cho phương pháp nhưng tôi hoàn toàn không biết cách xử lý hàng nhập khẩu trên đó, vì vậy tôi nghĩ rằng tôi sẽ sử dụng đầy đủ , điều này có lẽ sẽ không thắng được: ^)

Các kết quả:

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

nhập mô tả hình ảnh ở đây


1
Để tham khảo trong tương lai, bạn có thể thực hiện nhập cho các câu trả lời chỉ có phương thức giống như bạn thường làm. Chỉ cần đặt chúng bên ngoài thân phương thức và đếm các byte. Bạn cũng có thể đủ điều kiện các lớp thay vì nhập chúng nếu bạn chỉ cần một lần, để lưu một vài byte trong một số trường hợp.
Địa chất

Ngoài ra, có một lý do bạn nhập khẩu java.io.Filethay vì java.io.*?
Địa chất

Cảm ơn, tốt để biết. Và thứ hai, không, không có lý do. Điểm tốt.
Marv

Tại sao import ** static**, không chỉimport ?
Solomon Ucko

1
Vì vậy, tôi có thể gọi ImageIO::readImageIO::writekhông cần phải trả trước ImageIO.: Điều này thêm 9 byte ( static .*) nhưng tiết kiệm 16 ( ImageIO.hai lần).
Marv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.