Cubify это! Урок в оттенках серого ... э-э ... цвет ... э-э ... все


27

Будучи большим поклонником кубика Рубика и крутого искусства, я работал над тем, чтобы объединить их вместе, чтобы сделать действительно классные вещи. В основном решение миниатюрных кубиков Рубика для формирования элементарных пикселей в формировании кубического искусства Рубика. Примеры такого искусства можно увидеть по этой ссылке: http://google.com/search?q=rubik%27s+cube+art

Теперь целью этого Code Golf является создание кода, который принимает изображение в качестве входных данных, а затем преобразует его следующим образом:

Изображение изначально уменьшается до веб-безопасных оттенков серого. Причина этого заключается в том, что нам необходимо изолировать палитру градаций серого в сети (т. Е. 000000, 333333, 666666, 999999, CCCCCC и FFFFFF). Алгоритм колориметрического метода преобразования в оттенки серого доступен по адресу: http://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-preserving.29_conversion_to_grayscale , если вы хотите использовать его в качестве источника вдохновения.

Затем можно отобразить оттенки серого до соответствующих цветов. Чтобы быстро его разбить: 000000 будет означать синий цвет Рубика, 333333 будет означать красный цвет Рубика, 666666 будет означать зеленый цвет Рубика, 999999 будет означать оранжевый цвет Рубика, CCCCCC будет означать желтый цвет Рубика, а FFFFFF будет означать белый цвет Рубика.

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

Фактические значения RGB для палитры Рубика должны соответствовать следующему:

  • Красный: # C41E3A
  • Зеленый: # 009E60
  • Синий: # 0051BA
  • Оранжевый: # FF5800
  • Желтый: # FFD500
  • Белый: #FFFFFF

Чтобы дать вам пример, я обрезал голову Авраама Линкольна из следующей картинки: введите описание изображения здесьи отредактировал алгоритм для получения следующего:

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

Сетка предназначена для того, чтобы вы могли видеть, как каждый отдельный миниатюрный кубик Рубика должен быть сконфигурирован для формирования изображения. Истинный размер получившегося изображения составляет 45 на 45 пикселей, что означает (45/3) * (45/3) = 15 * 15 = 225 миниатюрных кубиков Рубика, которые будут использованы для создания этого изображения. Я не ожидаю, что вы представите полученное изображение с сеткой, как у меня.

Итак, вот что требуется:

  1. Изображение, обрабатываемое этим алгоритмом, должно иметь ширину x пикселей и высоту y пикселей, чтобы x и y были кратны 3. Это облегчает рендеринг как часть мозаики кубика Рубика. Если ваше изображение достаточно велико, рекомендуется уменьшить его до размеров от 45 x 45 до 75 x 75 или около этого в размерах до обработки. Имейте в виду, этот компонент изменения размера является необязательным.

  2. Чтобы создать мозаику, изображение необходимо преобразовать в палитру кубиков Рубика с секс-цветами.

  3. Полученное изображение должно быть действительным графическим файлом после обработки. Чтобы доказать, что ваш код работает, запустите его с изображением одного из президентов Соединенных Штатов Америки или известной голливудской знаменитости. Я уже использовал Авраама Линкольна в своем примере, поэтому этого президента больше нельзя использовать. Убедитесь, что вы указали язык, который вы использовали, количество байтов, а также президент / знаменитость, использовавшиеся для тестирования вашего кода, в том числе до и после снимков ...

  4. У каждой записи должен быть уникальный президент / знаменитость в качестве тестового примера. Я не буду принимать дубликаты. Это гарантирует, что повторяющиеся результаты не будут использоваться для проверки различных записей кода. Хорошо, что ваш код работает, это еще одна вещь, чтобы доказать это.

5. Самый короткий код выигрывает.

Я изменяю это на конкурс популярности ... Я бы лучше посмотрел, кто может сделать это, не участвуя в соревнованиях по количеству байтов ... Так что я награжу это вместе с наградой после 28 февраля 2014 года.


4
Я думаю, что было бы лучше, если бы вы добавили значения Rubik RGB к сообщению, а не полагались на ссылку.
SztupY

Означает ли, что «обрабатываемое изображение должно иметь ширину x пикселей и высоту y пикселей», означает ли это, что изменение размера является частью кода или изображение предварительно обрабатывается до требуемого размера?
user2846289

Есть ли невозможные состояния кубика Рубика, если вы ограничиваете только одно лицо?
Ник Т

1
@WallyWest Ты бы ЛЮБИЛ мое приложение MineCam, оно делает это, но вместо того, чтобы делать квадраты, оно использует мои блоки крафта, и это также делает это 15 раз в секунду с камерой iPhone в реальном времени, таким образом, превращая весь мир вокруг тебя в моя ремесленная вселенная. itunes.apple.com/us/app/minecam/id675845303?mt=8 (Если бы только это могло также создать семя для упомянутого мира хахахаха)
Альберт Реншоу

2
@WallyWest: дело не в лени. Проблема должна дать вам всю информацию, необходимую для начала работы, даже если остальная часть интернета не работает. Через год или два эта ссылка может быть удалена, и никто не будет обновлять ссылку. Если вы предоставите достаточно информации о том, как создавать веб-безопасные цвета в градациях серого (что не является необходимым для решения проблемы), вы могли бы просто добавить небольшую таблицу сопоставления, например #000000 => #0051BA, и т. Д.
SztupY

Ответы:


16

Имиджмагик (108)

Версия: ImageMagick 6.8.7-7 Q16 x86_64 2013-11-27

Следующий звонок:

$ convert -resize 75x75 -fx "q=p.intensity;q<1/6?#0051BA:q<2/6?#C41E3A:q<3/6?#009e60:q<4/6?#ff5800:q<5/6?#FFD500:#FFF" input output

где inputи outputдолжны быть изменены для имени файла ввода и вывода.

Я только посчитал символы между -resizeи #FFF", если вы думаете, что это неверно, не стесняйтесь комментировать.

Я использовал Ленну как образ (она появилась в «Плейбое», и любой, кто делает это, должен считаться голливудской знаменитостью, верно?)

Входные данные:

Входное изображение

Выход:

$ convert -resize 75x75 -fx "q=p.intensity;q<1/6?#0051BA:q<2/6?#C41E3A:q<3/6?#009e60:q<4/6?#ff5800:q<5/6?#FFD500:#FFF" Lenna.png LennaRubik.png

Сгенерированное изображение

Выход увеличен:

Увеличенное изображение

Примечания: в соответствии с документами imagemagick вы не можете иметь более одного условного оператора в выражении, но вызов все равно работает нормально, так что, вероятно, это было исправлено, а документы просто не обновлялись.

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

$ identify -verbose LennaRubik.png
  (...)   
  Colors: 6
  Histogram:
       338: (  0, 81,186) #0051BA srgb(0,81,186)
      1652: (  0,158, 96) #009E60 srgb(0,158,96)
      1187: (196, 30, 58) #C41E3A srgb(196,30,58)
      1674: (255, 88,  0) #FF5800 srgb(255,88,0)
       706: (255,213,  0) #FFD500 srgb(255,213,0)
        68: (255,255,255) #FFFFFF white
  (...)

Если вы думаете, что Ленна не считается настоящей знаменитостью, вот Брюс Уиллис:

Брюс Оригинал

Брюс Смолл

Брюс Большой


+1 Я думаю, что ваш ответ почти непобедим (или даже непобедим). Я просто предлагаю вам принять некоторые голливудская знаменитость безусловный плюс или американский президент фото и добавить к этому (не нужно удалить Lenna, держать оба). В противном случае некоторые скучные люди могут жаловаться и опускать руки только из-за этого.
Виктор Стафуса

@Victor: Я думаю, что Mathematica, Matlab или Octave могли бы легко справиться с этим, поскольку условия внутри fxдетали могут быть сжаты еще больше на языке, который имеет лучшую выразительность. И эти языки также имеют встроенную поддержку изображений (поэтому символы не теряются при импорте imagemagick / gd / и т.д.)
SztupY

@SztupY Я очень хорошо знаю Ленну ... Считаю, что ... Хорошая работа и с Брюсом Уиллисом ...
WallyWest

1
Ленна милая (р). Up.
blabla999

+1 за использование правильного инструмента для работы. Насколько я понимаю, правильный способ использовать imagemagick - сначала вызывать изображение, а не параметры, а не выходной файл.
Кузен Кокаин

14

Mathematica

Мы будем работать с квадратным регионом из американской марки с изображением Греты Гарбо. Это будет упоминаться как j.

J

f[i_,rs_,m_:True]:=
Module[{(*rs=rastersize-4*)r={0.77,0.12,0.23},gr={0,0.62,0.38},b={0,0.32,0.73},o={1,0.35,0},y={1,0.84,0},w={1,1,1},
c1={r,gr,b,o,y,w},grayGreta,garboColors},
grayGreta=(*Reverse@*)ImageData[ColorQuantize[Rasterize[i,(*ImageResolution \[Rule]15*)RasterSize->rs+1,ImageSize->rs],6]];
garboColors=Union@Flatten[grayGreta,1];
ArrayPlot[grayGreta/.Thread[garboColors-> RGBColor@@@c1],
Mesh->If[m==True,{rs-1,rs-1},None],MeshStyle->Black]]

Функция f принимает 3 параметра:

  • i что относится к изображению
  • rsразмер растра
  • m, булева переменная, которая указывает, должны ли использоваться линии сетки. (По умолчанию установлено значение True).

Используя растровые размеры 15, 30, 45 и 75:

GraphicsGrid[{{f[j, 15], f[j, 30]}, {f[j, 45], f[j, 75]}}, ImageSize -> 800]

4 garbos

Я не могу представить, чтобы кто-нибудь делал кубик Рубрика с таким количеством кусков! Интересное занятие тем не менее.


Играя с цветами

Это из более ранней записи. Код немного отличается. Graphicsиспользуется вместо ArrayPlot. Кроме того, мы используем полную печать, даже если она не квадратная.

Есть 6! = 720 перестановок цветов кубика Рубрика.

Далее отображается центральное изображение верхнего ряда (установите 6 изображений ниже). Когда значения градаций серого располагаются от самых темных к самым светлым, цвета являются {r, gr, b, o, y, w}. Другие варианты, тем не менее, работают.

i исходное изображение в оттенках серого.

Graphics[Raster[(g=Reverse@ImageData[ColorQuantize[Rasterize[i,RasterSize->75],6]])
/.Thread[Union@Flatten[g,1]-> {{7,1,2},{0,6,4},{0,3,7},{10,4,0},{10,8,0},{10,10,10}}/10]]]

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

Rasterize[garbo,RasterSize->75 растеризует изображение в массив 75 на 75.

ColorQuantize[<>, 6] уменьшает значения градаций серого до набора 6.

ImageDataизвлекает массив данных из изображения; это приходит с ног на голову.

Reverse переворачивает массив данных, отсюда и картинку, правой стороной вверх.

garboColors 6 значений оттенков серого в квантованном изображении.

Graphics[Raster отображает окончательное изображение.

rubrikColors являются значениями RGB 6 цветов кубика Рубрика.

Даны различные цветовые сочетания красного, зеленого, синего, оранжевого, желтого и белого цветов.

r={0.77,0.12,0.23};gr={0,0.62,0.38};b={0,0.32,0.73};o={1,0.35,0};y={1,0.84,0};w={1,1,1};
c1={r,gr,b,o,y,w};
c2={r,b,gr,o,y,w};
c3={b,r,gr,o,y,w};
c4={gr,b,r,o,y,w};
c5={b,r,gr,y,o,w};

И код:

grayGreta=Reverse@ImageData[ColorQuantize[Rasterize[i,RasterSize->75],6]];
garboColors=Union@Flatten[grayGreta,1];
Grid[{{i,
Graphics[Raster[grayGreta/.Thread[garboColors-> c1]]],
Graphics[Raster[grayGreta/.Thread[garboColors-> c2]]]},
{Graphics[Raster[grayGreta/.Thread[garboColors-> c3]]],
Graphics[Raster[grayGreta/.Thread[garboColors-> c4]]],
Graphics[Raster[grayGreta/.Thread[garboColors-> c5]]]}}]

garbos


Garbos Galore

Вот 72 (из 720) изображений Греты Гарбо, которые используют 6 цветов кубика Рубрика. Некоторые изображения работают лучше, чем другие, не правда ли?

GraphicsGrid@Partition[(Graphics[Raster[grayGreta /. Thread[garboColors -> #]]] & 
/@ Take[Permutations[{r, gr, b, o, y, w}, {6}], 72]), 12]

Garbos Galore


Грета, о Грета ... Это оказалось лучше, чем я ожидал. @DavidCarraher, хорошая работа здесь ...
WallyWest

@WallyWest. Спасибо. Это был очень интересный вызов.
DavidC

Я был так уверен, что Mathematica победит имиджмэджик, разве это не удастся сделать еще дальше? Требуются ли все эти функции?
SztupY

1
@SztupY Половина кода посвящена получению правильных цветов. Reverseможно было бы убрать, оставив картинку с ног на голову, но я не вижу других возможностей. Mathematica выразительна, но использует громкие слова. Кто-то, имеющий большой опыт в области изображений, возможно, немного уменьшит размер кода, но я сомневаюсь, что они могут превзойти ваш код в ImageMagick.
DavidC

1
В коде действительно были некоторые несоответствия. Я надеюсь, что они уже ушли. iудерживайте исходное изображение. grобозначает зеленый Рубрика. gотносится к растеризованным и квантованным данным изображения для изображения в градациях серого.
DavidC

6

Smalltalk (Smalltalk / X), 289 139 *

вход: я; вывод: r

r:=i magnifiedTo:75@75.
r colorMapProcessing:[:c||b|b:=c brightness.Color rgbValue:(#(16r0051BA 16rC41E3A 16r009e60 16rff5800 16rFFD500 16rFFFFFF)at:(b*6)ceiling)]

вход:

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

выход:

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

расширен:

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

(для всех молодых людей: это НЕ Мадонна ;-)

[*] Я не учел увеличение до 75x75 (первая строка) - мог бы использовать уже измененный размер в качестве входных данных. Надеюсь, что с тобой все в порядке.


Я обожаю Мэрилин Монро ... Отличный выбор ... Изменение размера было дополнительной функцией ...
WallyWest

4

Постскриптум и ИСТИННЫЕ цвета Рубика! ;-)

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

Решение использует тот факт, что 1-я редакция этого вопроса определяет требуемые цвета по ссылке на сайт, в которой четко указано, что должны использоваться цвета Pantone (R), а цвета RGB являются только приблизительными. Тогда я подумал, зачем мне приближения, когда я могу сделать настоящий цвет? - :)

10 dict begin
/Size 75 def
/Names  [(PMS 012C) (PMS 021C) (PMS 347C)   (PMS 200C)    (PMS 293C)   ] def
/Colors [[0 .16 1 0][0 .65 1 0][1 0 .39 .38][0 .9 .72 .28][1 .56 0 .27]] def
<</PageSize [Size dup]>> setpagedevice
Size dup scale
true setoverprint
(%stdin) (r) file 100 string readline pop 
(r) file <</CloseSource true>>/DCTDecode filter
0 1000000 string 
dup <</CloseTarget true>>/NullEncode filter 
{
    3 index 3 string readstring
    {
        4 -1 roll 1 add 4 1 roll
        {} forall
        0.11 mul exch 0.59 mul add exch 0.3 mul add cvi
        1 index exch write
    } {pop exit} ifelse
} loop
closefile
0 3 -1 roll getinterval
exch closefile
/data exch def
/n data length sqrt cvi def
1 1 Names length {
    /N exch def
    { 
        dup N Names length 1 add div gt 
            {N 1 add Names length 1 add div gt 
                {1} {0} ifelse} 
            {pop 1} 
        ifelse
    } settransfer
    [/Separation Names N 1 sub get /DeviceCMYK {
        Colors N 1 sub get 
        { 1 index mul exch } forall pop
    }] setcolorspace
    <<
        /ImageType        1
        /Width            n
        /Height           n
        /ImageMatrix      [n 0 0 n neg 0 n]
        /BitsPerComponent 8
        /Decode           [0 1]
        /DataSource       data
    >> image
} for
showpage
end

Этот код должен быть сохранен как, например, rubik.psа затем передан в Ghostscript с обычным заклинанием:

gs -q -sDEVICE=psdcmyk -o out.psd rubik.ps

Затем он ждет вас на следующей строке для ввода имени файла JPG, например

kelly.jpg

и, если все пойдет хорошо, сохраняет результаты в out.psdфайл.

Входной сигнал должен быть квадратным RGB JPEG (любого размера), выходной - PSD с каналами плашечного цвета. Вам понадобится Photoshop для просмотра файла. Изменение устройства GS с psdcmykчего-либо еще не даст ничего полезного. JPEG в качестве входных данных - потому что интерпретатор postscript может декодировать поток данных непосредственно из него. Квадратная форма - потому что программа использует sqrtдлину строки, чтобы найти ширину (и высоту) изображения.

Первые строки определяют размер выходного изображения (можно изменить по умолчанию 75) и цветовую палитру (можно изменить цвета и их количество). Все остальное не является жестко закодированным, я думаю.

В чем дело? Поток RGB-триплетов на лету преобразуется в строку значений градаций серого (с простой формулой), обычный словарь 8-битных контоновых изображений построен и используется для рисования 5 одинаковых изображений друг над другом в 5 Separationцветовых пространствах. Хитрость заключается в применении передаточных функций перед каждым вызовом imageоператора. Например, для желтой краски эта функция возвращает 0 для входных значений только в диапазоне 0,167 ... 0,333 и 1 в противном случае.

Входные данные:

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

Снимок экрана с выходом 75x75, открытым в Photoshop, увеличен на 800%:

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

И палитра каналов Photoshop:

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


1
+1 за использование Грейс Келли ... вы меня полностью уважаете ...
WallyWest

3

C #

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        unchecked
        {
            var t = new[] { 0xFFC41E3A, 0xFF009E60, 0xFF0051BA, 0xFFFF5800, 0xFFFFD500, 0xFFFFFFFF }.Select(v => Color.FromArgb((int)v)).ToArray();
            var o = new Bitmap(Bitmap.FromFile(args[1]));
            var m = double.Parse(args[0]);
            var r = Math.Min(m / o.Width, m / o.Height);
            var w = (int)(o.Width * r);
            var h = (int)(o.Height * r);

            o = new Bitmap(o, w - (w % 3), h - (h % 3));
            for (int y = 0; y < o.Height; y++)
                for (int x = 0; x < o.Width; x++)
                    o.SetPixel(x, y, N(o.GetPixel(x, y), t));
            o.Save(args[2], ImageFormat.Png);
        }
    }

    static Color N(Color c, Color[] t)
    {
        return t.OrderBy(v => Math.Abs(W(v) - W(c))).First();
    }

    static double W(Color c)
    {
        return .11 * c.B + .59 * c.G + .30 * c.R;
    }
}

Вам нужно запустить его с 3 параметрами:

foo.exe 75 d:\test.jpg d:\out.png

Где 75макс. width / height, d:\test.jpgявляется входным файлом и d:\out.pngявляется выходным файлом.

Вывод для различных изображений в этом конкурсе:

Уолли Уэст Штупы 1 Штупы 2 blabla999

Моя собственная знаменитость:

Гарт!

Выход:

Гарт 75 Гарт 225

Тем не менее, другие (больше, чем 75x75) размеры дают лучшие изображения:

150 300

И, если мы будем придерживаться президентов:

ДуббаЯ 294 ДуббаЯ 75 ДуббаЯ 225

Так как это уже не кодогольф, я не стал слишком сильно «минимизировать» код. Кроме того, поскольку в инструкциях конкретно не упоминалось, что изображение должно быть той же ширины, что и высота (квадрат), я не стал беспокоиться об обрезке; Я делать , однако, убедитесь , что изображение является кратным 3 пикселя ширина / высота. Если вы хотите квадратные изображения, используйте квадратные входы :ПНаконец; алгоритм далеко не оптимален.

Еще несколько (так как люди больше поддерживают горячих цыпочек / интернет-героев :П)

Кари Байрон 300 Кари Байрон 75 Кари Байрон 225 Хофф 300 Хофф 75 Хофф 225


3

Brainfuck

++++[->+[,.----------]<]>>>>---->->++++++++++>>------------>+++>+++>--
--->++++++[->+++++<]---->+[-<+++++++<+++<+++++<+++<+++<++++++<++++++<+
<++>>>>>>>>>]<[<]<<,+[,<++++++>[>++++++[->+++++++<]>+[<<[->]>[<]>-]<<<
->]+<[-[-[-[-[[-].>>>>>>>>.<.<<<<<<-<]>[->>>>>[.<]<<]<]>[-.>>>[>]<<<.<
.[<]<<]<]>[--.+>>>[>]<<.[<].<<]<]>[--.+>>>[>]<.[<].<<]<]>[--...+],,+]

Это требует интерпретатора / компилятора BF, который имеет -1 как EOF и имеет более чем 8-битные ячейки, ЕСЛИ один из красных пикселей равен 255. В противном случае он остановится преждевременно, поскольку он не сможет различаться между EOF и значением 0xFF , С jitbf у вас есть все, что машина имеет целочисленный размер, и вы можете сделать это, чтобы принудительно установить -1 как EOF:

jitbf --eof -1 rubiks.bf < angelina.pnm > angelina-rubix.pnm

Представленный формат файла изображения - это полный файл RGB PNM (P6), необработанный как опция в Gimp.

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

Изображение Анджелины Джоли из Hackers (1995) уменьшено до 75x75 и обработано с помощью приложения:

Анджелина Джоли 75x75 / добросовестное использование Анджелина Джоли 75x75 в рубиксовом цвете куб / Fair Use То же масштабируется 6x

То же самое, только я использовал оригинальный размер :

То же самое, только не уменьшенное в первую очередь / добросовестное использование

И так как я экстрасенс, вот и президент:

Арнольд Шварценеггер из Википедии


Не по теме, но сегодня xkcd также имеет ссылки на Hackers (1995)
Sylwester

1
Этот также делает: xkcd.com/1247
Shade

1

Objective-C

Я видел этот вызов прошлой ночью, и у меня было немного запутанное время -[NSArray indexOfObject:inSortedRange:options:usingComparator:], отсюда и задержка.

- (UIImage  *)rubiksImage:(UIImage *)inputImg
{
    //Thank you http://stackoverflow.com/a/11687434/1153630 for the greyscale code
    CGRect imageRect = CGRectMake(0, 0, inputImg.size.width, inputImg.size.height);

    int width = imageRect.size.width;
    int height = imageRect.size.height;

    uint32_t *pixels = (uint32_t*)malloc(width * height * sizeof(uint32_t));

    memset(pixels, 0, width * height * sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(context, imageRect, [inputImg CGImage]);

    const int RED = 1;
    const int GREEN = 2;
    const int BLUE = 3;

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            uint8_t* rgbaPixel = (uint8_t*)&pixels[y * width + x];
            uint32_t grayPixel = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];

            NSArray *r = [self rubixColorFromGrey:grayPixel];

            rgbaPixel[RED] = [r[2] integerValue];
            rgbaPixel[GREEN] = [r[1] integerValue];
            rgbaPixel[BLUE] = [r[0] integerValue];
        }
    }

    CGImageRef newCGImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);

    UIImage* newUIImage = [UIImage imageWithCGImage:newCGImage];

    CGImageRelease(newCGImage);

    return newUIImage;
}

- (NSArray *)rubixColorFromGrey:(uint32_t)p
{
    NSArray *colors = @[@0, @51, @102, @153, @204, @255];

    NSUInteger index = [colors indexOfObject:@(p)
                               inSortedRange:NSMakeRange(0, colors.count)
                                     options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual
                             usingComparator:^(id a, id b) {
                                return [a compare:b];
                             }];
    switch (index) {
        case 0:
            return rgb(0, 81, 186);
            break;
        case 1:
            return rgb(196, 30, 58);
            break;
        case 2:
            return rgb(0, 156, 96);
            break;
        case 3:
            return rgb(255, 82, 0);
            break;
        case 4:
            return rgb(255, 213, 0);
            break;
        case 5:
            return rgb(255, 255, 255);
            break;

        default:
            break;
    }

    return colors; //go wild
}

NSArray *rgb(int r, int g, int b)
{
    return @[@(r), @(g), @(b)];
}

Я запустил его на своем iPad так:

UIImageView *img = [[UIImageView alloc] initWithImage:[self rubiksImage:[UIImage imageNamed:@"danny.png"]]];
[img setCenter:self.view.center];
[self.view addSubview:img];

До Дэнни ДеВито Перед после Дэнни ДеВито После

До Грейс Келли до после Грейс Келли после


1

питон

Формат: python rubik.py <input> <max_cubes> <output>.

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

import Image, sys

def rubik(x, max_cubes = 25):

    img = x
    max_cubes *= 3

    if x.size[0] > max_cubes or x.size[1] > max_cubes:

        print "Resizing image...",

        if x.size[0] > x.size[1]:
            img = x.resize((max_cubes, int(max_cubes * float(x.size[1]) / x.size[0])), Image.ANTIALIAS)
        else:
            img = x.resize((int((max_cubes * float(x.size[0]) / x.size[1])), max_cubes), Image.ANTIALIAS)

    if x.size[0] % 3 or x.size[1] % 3:
        print "Sizes aren't multiples of 3"
        return

    print "Image resized to %i x %i pixels" % img.size

    out = Image.new('RGB', img.size)

    print "Converting image...",

    for x in xrange(out.size[0]):
        for y in xrange(out.size[1]):
            r, g, b = img.getpixel((x, y))
            if r == g == b == 255:
                out.putpixel((x,y), (255, 255, 255))
            else:
                l = 0.2126 * r + 0.7152 * g + 0.0722 * b
                l /= 255
                out.putpixel((x,y), (
                        (0x00, 0x51, 0xBA),
                        (0xC4, 0x1E, 0x3A),
                        (0x00, 0x9E, 0x60),
                        (0xFF, 0x58, 0x00),
                        (0xFF, 0xD5, 0x00)
                    )[int(5 * (l <= 0.0031308 and 12.92 * l  or 1.055 * l ** (1/2.4) - 0.055))])

    print "Image converted successfully."

    print "Stats:"
    h, v = img.size[0] / 3, img.size[1] / 3
    print "   ", h, "horiz. Rubik cubes"
    print "   ", v, "vert. Rubik cubes"
    print "   ", h * v, "total Rubik cubes"

    return out.resize((out.size[0], out.size[1]))

if __name__ == "__main__":
    rubik(Image.open(sys.argv[1]).convert("RGB"), int(sys.argv[2])).save(sys.argv[3])

Входные данные:

Сандро Пертини
(источник: ilmamilio.it )

Вывод с max_cubes = 25:

Сандро Пертини, Рубикд 1

Вывод с max_cubes = 75:

Сандро Пертини, Рубикд 2

Вывод с max_cubes = 225:

Сандро Пертини, Рубик 3


Не белый цвет отсутствует? И самое темное должно быть синим, но, как я вижу сейчас, это проблема и с некоторыми другими изображениями.
user2846289

@VAdimiR Упс! Отобразил их в неправильном порядке. Что касается белого, не появляющегося, это из-за точности FP (1.055 - 0.055 = 0.9999999999999999). Я думаю, мне придется жестко кодировать белый, что не сложно, так как в любом случае он будет отображаться только с исходным значением #FFFFFF.
Оберон

Что касается белого, мое мнение состояло в том, что диапазон 0..1 (легкость) разделен на 6 частей, а все, что 0.83..1.00 сопоставлено с белым, иначе не будет особого смысла в создании изображения из 6 цветов куба. но вот как я это прочитал.
user2846289

@Oberon Интересный выбор с использованием Пертини ... Он почти дожил до 94 лет ... И отличная работа с использованием Python, и я должен признать, что это не один из самых простых языков, с которыми я сталкивался, так хорошо сделано!
WallyWest
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.