Змініть це! Урок з відтінків сірого… е… колір… ер… як завгодно


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 для палітри Rubik повинні відповідати наступним:

  • Червоний: # 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
Я думаю, було б краще, якщо ви додасте значення RGB Rubik до публікації, а не посилаючись на посилання.
SztupY

Чи "зображення, яке обробляється, має бути x пікселів у ширину на y пікселів", означає, що зміна розміру є частиною коду, або що зображення попередньо обробляється до потрібного розміру?
користувач2846289

Чи є якісь неможливі стани кубика Рубіка, якщо ви обмежуєте лише одне обличчя?
Нік Т

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"якщо ви вважаєте, що це недійсно, сміливо коментуйте.

Я використовував Ленну як образ (вона з'явилася в Playboy, і хтось, хто це робить, повинен вважати голлівудською знаменитістю, правда?)

Вхід:

Вхідне зображення

Вихід:

$ 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 Я думаю, що ваша відповідь майже неперевершена (або взагалі непереможна). Я просто запропоную вам зробити якусь безперечно фотографію голлівудської знаменитості чи американського президента та додати до цього (не потрібно знімати Ленну, зберігайте обоє). Інакше деякі нудні люди можуть скаржитися і зволікати саме тому.
Віктор Стафуса

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

@SztupY Я дуже добре знаю Ленну ... Я вважаю, що ... Приємна робота і з Брюсом Віллісом ...
WallyWest

1
Ленна мила (р). Вгору
blabla999

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

14

Математика

Ми будемо працювати з квадратним регіоном із американського штампу із зображенням Грети Гарбо. Це буде позначатися як 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, булева змінна, яка визначає, чи слід використовувати лінії Mesh. (За замовчуванням встановлено значення True).

Використання растрових розмірів 15, 30, 45 та 75:

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

4 гарбо

Я не уявляю, як хтось зробить кубик Рубрика з такою кількістю штук! Тим не менше, цікаві вправи.


Граючи з кольорами

Це з попереднього запису. Код трохи інший. 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]]]}}]

гарбос


Гарбос Галоре

Ось 72 (із 720) зображень Грети Гарбо, які використовують 6 кольорів кубика Рубрика. Деякі зображення працюють краще, ніж інші, ви не думаєте?

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

garbos галор


Грета, о Грета ... Це вийшло краще, ніж я очікував. @DavidCarraher, приємна робота тут ...
WallyWest

@WallyWest. Спасибі. Це був дуже цікавий виклик.
DavidC

Я був настільки впевнений, що Mathematica переможе іміджемагік, чи не можна це ще більше пограти в гольф? Чи потрібні всі ці функції?
SztupY

1
@SztupY Половина коду присвячена правильному використанню кольорів. Reverseможна було усунути, залишивши картинку догори дном, але я не бачу інших можливостей. Математика виразна, але використовує великі слова. Хтось досвідчений у зображеннях, ймовірно, може трохи зменшити розмір коду, але я сумніваюся, що вони можуть перемогти ваш код imagemagick.
DavidC

1
Дійсно в коді були деякі невідповідності. Я сподіваюся, що їх зараз немає. iутримуйте оригінальне зображення. grозначає, що Рубрик зелений. gвідноситься до растризованих і квантованих даних зображення для зображень сірого масштабу.
DavidC

6

Smalltalk (Smalltalk / X), 289 139 *

вхід: i; вихід: 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

Постскрипт та ІСТИНА кольори Рубіка! ;-)

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

Рішення використовує той факт, що перша редакція цього питання визначає необхідні кольори за посиланням на сайт, де чітко зазначено, що кольори 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 як вхід - оскільки інтерпретатор постскрипту може декодувати потік даних безпосередньо з нього. Квадратна форма - тому що програма спирається на 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макс. ширина / висота, d:\test.jpgє вхідним файлом і d:\out.pngє вихідним файлом.

Вихід для різних зображень на цьому конкурсі:

WallyWest SztupY 1 SztupY 2 blabla999

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

Гарт!

Вихід:

Гарт 75 Гарт 225

Однак інші розміри (більше 75x75) покращують зображення:

150 300

І якщо ми будемо дотримуватися президентів:

ДуббаЯ 294 DubbaYa 75 DubbaYa 225

Оскільки це вже не (довгий?) Кодовий гольф, я не намагався занадто сильно "мінімізувати" код. Крім того, оскільки в інструкціях конкретно не згадувалося, що зображення повинно бути такої ж ширини, як висота (квадрат), я не переймався обрізанням; Я робити , однак, переконайтеся , що зображення є кратним 3 пікселі ширина / висота. Якщо ви хочете квадратних зображень, використовуйте квадратні введення : Pнарешті; алгоритм далеко не оптимальний.

Ще кілька (оскільки люди більше підтримують гарячих курчат / героїв Інтернету : P)

Карі Байрон 300 Карі Байрон 75 Карі Байрон 225 Гоф 300 Гоф 75 Гоф 225


3

Брейнфук

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

Для цього потрібен інтерпретатор / компілятор BF, який має -1 як EOF і має більше 8 бітових комірок, якщо один з червоних пікселів становить 255. Або ж він зупиниться передчасно, оскільки він не зможе відрізнятись між EOF та значення 0xFF . У jitbf у вас є все, що машина має цілий розмір, і ви можете зробити це, щоб примусити -1 як EOF:

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

Відображений формат файлу зображення - це повний PNG-файл RGB (P6), необроблений як опція у Gimp.

Він використовує лише зелений канал (що є одним із багатьох способів перетворення кольорового зображення у відтінки сірого). Це зменшує значення на 43, не зменшуючи значення нижче нуля, щоб дізнатися, який колір рубіків використовувати, і мати перемикач, який виводить правильний колір RBG, що відповідає.

Зображення Анджеліни Джолі з Хакерів (1995) зменшилось до 75x75 та обробляється програмою:

Анджеліна Джолі 75х75 / Справедливе використання Анджеліна Джолі 75х75 в кольорах кубика Рубікс / Справедливе використання Те саме масштабується 6х

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

Те саме, що не зменшено спочатку / Справедливе використання

А оскільки я психічний, ось і президент:

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


Поза темою, але сьогодні у xkcd також є посилання на хакерів (1995)
Sylwester

1
Це також робить: xkcd.com/1247
Shade

1

Ціль-С

Я бачив цей виклик минулої ночі і мав колись настільки збентежений час -[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


Чи не відсутній білий колір? І найтемніший повинен бути блакитним, але, як я зараз бачу, це стосується і деяких інших зображень.
користувач2846289

@VAdimiR Whoops! Списано їх у неправильному порядку. Щодо білого не відображається, то це через точність FP (1.055 - 0.055 = 0.9999999999999999). Я думаю, що мені доведеться ввести жорсткий код білого кольору, що не важко, оскільки він все одно відображатиметься лише за початковим значенням #FFFFFF.
Оберон

Щодо білого, на мою думку, діапазон 0..1 (легкість) ділиться на 6 частин, і все, що 0.83..1.00 відображається на білий, інакше не буде особливого сенсу робити зображення 6 кольорів куба , але ось як я це прочитав.
користувач2846289

@Oberon Цікавий вибір використання Pertini ... Він майже дожив до 94 років ... І велика робота з використанням Python, і я повинен визнати, не одна з найпростіших мов, які я натрапила, так добре зроблено!
WallyWest
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.