Rainbowlify Изображение

23

Эта задача заключается в постепенном изменении оттенков на изображении, чтобы сделать красивые картинки, подобные этой:

большая звездная ночь ( оригинал )

Вызов

Напишите программу или функцию, которая принимает два неотрицательных целых числа и изображение в любом общем формате файла изображения по вашему выбору (вы можете указать путь к изображению или необработанным данным изображения).

Мы назовем первое целое число циклами, а второе целое - смещением .

Мы также определим шаг с плавающей точкой как 360-кратные циклы, деленные на площадь изображения, или step = 360 * cycles / (image width * image height).

Для каждого пикселя P в изображении, перемещая по одной строке за раз, слева направо, сверху вниз (т.е. в порядке чтения, если пиксели были буквами), выполните следующие действия:

  1. Увеличение цветового тона от Р по офсетным градусам (цикл вокруг от 360 до 0 , если это необходимо).

  2. Затем увеличьте смещение за шагом .

Сохраните, отобразите или выведите исходное изображение в любом общем формате файла изображения.

Эта процедура постепенно увеличивает оттенок всех пикселей в изображении, делая циклы полных циклов вокруг радуги оттенка , начиная с первоначального смещения оттенка смещением .

Когда число циклов равно 1, а смещение равно 0, как на приведенном выше изображении «Звездная ночь», верхний и нижний ряды пикселей практически не имеют сдвига оттенка, но между ними существует полный цветовой цикл.

Детали

  • Циклы могут быть любым неотрицательным целым числом, но вы можете предположить, что смещение составляет от 0 до 359 включительно.

  • Когда число циклов равно 0, оттенок каждого пикселя в изображении будет смещен на точное смещение, поскольку шаг также должен быть равен 0. (В этом случае, если смещение равно 0, изображение не изменяется вообще.)

  • При желании вы можете предположить, что циклы и смещение вводятся как числа с плавающей запятой (т.е. 1.0вместо 1). (Я понимаю, что они вовсе не должны быть целыми числами, это просто упрощает задачу.)

  • «Оттенок» относится к версии цветового пространства RGB, распространенной в цветовых моделях HSL / HSV .

Примеры

Оригинал:

река

Cycles = 1, offset = 0:

речной выход 1

Циклы = 1, смещение = 180:

речной выход 2

Оригинал:

сферы

Cycles = 2, offset = 60:

вывод сфер

Оригинал:

заход солнца
(Спасибо ArtOfCode .)

Циклы = 1, смещение = 120:

выходной закат

Оригинал:

дверная ручка
(Спасибо дверная ручка .)

Cycles = 1, offset = 0:

выход дверной ручки 1

Cycles = 4, offset = 0:

выход дверной ручки 2

Cycles = 200, смещение = 0:

выход дверной ручки 3

Cycles = 30000, смещение = 0:

выход ручки 4

(Эти изображения могут быть не идеальными из-за сжатия изображений imgur.)

счет

Самый короткий код в байтах побеждает. Ответ Tiebreaker выше.

Ответы, которые публикуют свои собственные классные тестовые изображения, получат от меня больше баллов

Кальвин Хобби
источник
6
Похоже, дверная ручка курит какую-то кастрюлю.
Денкер
Я предполагаю, что массив целых чисел, поскольку возвращаемое значение будет включено в "или выходной сырой"?
Марв
2
@ Marv Нет. Я имею в виду, что необработанные байты изображения (в выбранном вами общем формате, скажем, ppm ) могут быть переданы напрямую в стандартный вывод.
Увлечения Кэлвина
2
Должны ли результаты быть идентичны вашим примерам? Я получаю немного разные изображения.
DJMcMayhem
1
@DrGreenEggsandHamDJ Если вы не можете визуально отличить, то это, вероятно, хорошо. Пиксельное совершенство не требуется (в любом случае imgur может сжимать мои изображения).
Увлечения Кэлвина

Ответы:

8

Pyth, 86 байт, полная программа

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

Pyth не имеет встроенных преобразований цветового пространства - это реальная сделка.

Принимает ввод в следующем формате на стандартный ввод:

input_filename.png
offset
cycles

Выходное изображение записывается в o.png.


Это работает, вращая цветной куб вокруг его диагонали, а затем зажимая любые значения за пределами диапазона.

Если aугол поворота и r, g, bвходной цвет, мы вычисляем новый цвет r', g', b'по:

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
источник
6

Python, 379 байт

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

Это принимает путь к .jpgвходу. Он не будет работать с PNG, хотя вы можете изменить , r,g,b=i.split();чтобы r,g,b=i.split()[:3];загрузить изображение PNG.

Вот несколько изображений:

Оригинал:

введите описание изображения здесь

Смещение: 0, циклов: 4

введите описание изображения здесь

Оригинал:

введите описание изображения здесь

Смещение 0, 1 цикл:

введите описание изображения здесь

Оригинал:

введите описание изображения здесь

Смещение 0, 2,5 цикла:

введите описание изображения здесь

DJMcMayhem
источник
6

Java (полная программа), 491 488 байт (спасибо @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);
    }
}

объяснение

  • Использование: Довольно просто. Компилировать с java -c Q.java. Беги с java Q <cycles> <offset> <imagepath>. Переопределит существующее изображение, поэтому будьте осторожны.

  • Сначала я собирался найти решение, основанное только на методах, но я не совсем знал, как обрабатывать импорт этих файлов, поэтому я решил, что пойду на полную , это, вероятно, в любом случае не победит: ^)

Полученные результаты:

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

введите описание изображения здесь

Марв
источник
1
Для дальнейшего использования вы можете выполнить импорт ответов только для методов так же, как обычно. Просто поместите их вне тела метода и сосчитайте байты. Вы также можете полностью квалифицировать классы вместо того, чтобы импортировать их, если они понадобятся вам только один раз, чтобы в некоторых случаях сэкономить несколько байтов.
Geobits
Кроме того, есть ли причина, по которой вы импортируете java.io.Fileвместо java.io.*?
Geobits
Спасибо, приятно знать. И во-вторых, нет, нет причин. Хорошая точка зрения.
Марв
Почему import ** static**, а не только import?
Соломон Уцко
1
Так что я могу звонить ImageIO::readи ImageIO::writeбез необходимости добавлять ImageIO.: Это добавляет 9 байт ( static .*), но сохраняет 16 ( ImageIO.дважды).
Марв