Cubify This! Lekcja w skali szarości… er… kolor… er… cokolwiek

27

Będąc wielkim fanem kostki Rubika i fajnej sztuki, pracowałem nad połączeniem tych dwóch, aby zrobić naprawdę fajne rzeczy. Zasadniczo rozwiązywanie miniaturowych kostek Rubika w celu utworzenia podstawowych pikseli w tworzeniu kostki Rubika. Przykłady takich dzieł można zobaczyć pod tym linkiem: http://google.com/search?q=rubik%27s+cube+art

Teraz celem tego Code Golf jest utworzenie kodu, który akceptuje obraz jako dane wejściowe, a następnie konwertuje go w następujący sposób:

Obraz jest początkowo redukowany do bezpiecznych dla sieci kolorów w skali szarości. Powodem tego jest to, że musimy wyizolować bezpieczną dla palety internetowej skalę szarości (tj. 000000, 333333, 666666, 999999, CCCCCC i FFFFFF). Algorytm metody kolorymetrycznej konwersji na skalę szarości jest dostępny na stronie : http://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-preserving.29_conversion_to_grayscale , jeśli chcesz użyć tego jako inspiracji.

Następnie renderowano skalę szarości na odpowiednie kolory. Aby szybko to rozbić: 000000 będzie odnosić się do niebieskiego Rubika, 333333 będzie odnosić się do czerwonego Rubika, 666666 będzie odnosić się do zielonego Rubika, 999999 będzie odnosić się do pomarańczowego Rubika, CCCCCC będzie odnosić się do żółtego Rubika, a FFFFFF będzie odnosić się do białego Rubika.

Wolę, aby Twój wynikowy kod mógł renderować z palety zdjęcia prosto do kolorów Rubika. Dwustopniowa metoda przejścia z bezpiecznej dla sieci skali szarości, a następnie do odpowiedniej palety Rubika, ma na celu przedstawienie logiki procesu, ale jeśli jest to łatwiejsze, zrób to.

Rzeczywiste wartości RGB dla palety Rubika muszą odpowiadać następującym:

  • Czerwony: # C41E3A
  • Zielony: # 009E60
  • Niebieski: # 0051BA
  • Pomarańczowy: # FF5800
  • Żółty: # FFD500
  • Biały: #FFFFFF

Aby dać wam przykład, przyciąłem głowę Abrahama Lincolna z poniższego obrazu: wprowadź opis zdjęcia tutaji przetworzyłem algorytm, aby uzyskać następujące:

wprowadź opis zdjęcia tutaj

Siatka jest tam, abyś mógł zobaczyć, w jaki sposób każda indywidualna miniaturowa kostka Rubika musiałaby zostać skonfigurowana do utworzenia obrazu. Rzeczywisty rozmiar uzyskanego obrazu wynosi 45 na 45 pikseli, co oznacza (45/3) * (45/3) = 15 * 15 = 225 miniaturowe kostki Rubika zostaną użyte do stworzenia tego obrazu. Nie oczekuję, że przedstawisz wynikowy obraz z siatką, tak jak ja.

Oto, co jest wymagane:

  1. Obraz przetwarzany przez ten algorytm musi mieć szerokość x pikseli na wysokość y pikseli, tak aby xiy były wielokrotnościami 3. Ma to na celu ułatwienie renderowania jako części mozaiki kostki Rubika. Jeśli obraz jest dość duży, zaleca się zmniejszenie go do około 45 x 45 do 75 x 75 lub mniej więcej przed przetworzeniem. Pamiętaj, że ten element zmiany rozmiaru jest OPCJONALNY.

  2. Aby utworzyć mozaikę, obraz należy przekonwertować na paletę sześcianów Rubika o seksownym kolorze.

  3. Powstały obraz musi być poprawnym plikiem graficznym po przetworzeniu. Aby udowodnić, że Twój kod działa, uruchom go na obrazie jednego z prezydentów Stanów Zjednoczonych Ameryki lub znanej gwiazdy Hollywood. Użyłem już Abrahama Lincolna w moim przykładzie, więc nie można już używać tego prezydenta. Upewnij się, że podajesz używany język, liczbę bajtów, a także prezydenta / celebryty użytej do przetestowania kodu, w tym przed i po ujęciach ...

  4. Każdy wpis musi mieć unikalnego prezydenta / celebrytę jako swój testowy przypadek. Nie przyjmę duplikatów. Zapewni to, że duplikaty wyników nie będą używane do testowania różnych wpisów kodu. Bardzo dobrze jest powiedzieć, że twój kod działa, to kolejna rzecz, aby to udowodnić.

5. Najkrótszy kod wygrywa.

Zmieniam to na konkurs popularności ... Wolałbym zobaczyć, kto może to zrobić bez konkurowania pod względem liczby bajtów ... Więc nagrodzę to nagrodą po 28 lutego 2014 roku.

WallyWest
źródło
4
Myślę, że byłoby lepiej, gdybyś dodał wartości Rubik RGB do postu zamiast polegać na linku.
Sztuczki
Czy „obraz do przetworzenia musi mieć szerokość x pikseli i wysokość y pikseli” oznacza, że ​​zmiana rozmiaru jest częścią kodu lub że obraz jest wstępnie przetworzony do wymaganego rozmiaru?
user2846289
Czy są jakieś niemożliwe stany Kostki Rubika, jeśli ograniczysz tylko jedną twarz?
Nick T
1
@WallyWest UWIELBISZ moją aplikację MineCam, robi to, ale zamiast robić kwadraty, używa bloków kopalnianych, a także robi to 15 razy na sekundę z kamerą iPhone w czasie rzeczywistym, przekształcając cały świat wokół ciebie w wszechświat rzemiosła kopalni. itunes.apple.com/us/app/minecam/id675845303?mt=8 (Gdyby tylko mógł wygenerować ziarno dla wspomnianego świata hahahaha)
Albert Renshaw
2
@WallyWest: nie chodzi o lenistwo. Problem powinien dostarczyć wszystkich informacji potrzebnych do rozpoczęcia pracy, nawet jeśli reszta Internetu nie działa. Za rok lub dwa ten link może zostać usunięty i nikt go nie zaktualizuje. Jeśli podasz wystarczającą ilość informacji na temat tworzenia bezpiecznych dla sieci kolorów w skali szarości (co nie jest konieczne do rozwiązania problemu), możesz po prostu łatwo dodać małą tabelę mapowania #000000 => #0051BAitp.
SztupY

Odpowiedzi:

16

Imagemagick (108)

Wersja: ImageMagick 6.8.7-7 Q16 x86_64 2013-11-27

Następujące połączenie:

$ 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

gdzie inputi outputmuszą zostać zmodyfikowane dla wejściowej i wyjściowej nazwy pliku.

Naliczyłem tylko znaki między -resizei #FFF", jeśli uważasz, że jest to nieważne, możesz komentować.

Użyłem Lenny jako obrazu (pojawiła się w Playboyu i każdy, kto to robi, powinien liczyć się jako gwiazda Hollywood, prawda?)

Wkład:

Wprowadź obraz

Wydajność:

$ 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

Wygenerowany obraz

Wyjście powiększone:

Powiększony obraz

Uwagi: zgodnie z dokumentami imagemagick nie można mieć więcej niż jednego operatora warunkowego w zestawieniu, ale połączenie nadal wydaje się działać dobrze, więc prawdopodobnie zostało to naprawione, a dokumenty po prostu nie zostały zaktualizowane.

Uruchamianie identyfikacji na obrazie wynikowym (aby pokazać, że kolory są rzeczywiście w porządku):

$ 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
  (...)

Jeśli uważasz, że Lenna nie liczy się jako celebrytka, oto Bruce Willis:

Bruce Original

Bruce Small

Bruce Large

Sztuczki
źródło
+1 Myślę, że twoja odpowiedź jest prawie nie do pobicia (lub nawet nie do pobicia). Po prostu zasugeruję, abyś zrobił zdjęcie pewnej celebrytce z Hollywood lub amerykańskiemu prezydentowi i dodał do tego (nie musisz usuwać Lenny, zachowaj oba). W przeciwnym razie niektórzy nudni ludzie mogą narzekać i głosować tylko z tego powodu.
Victor Stafusa
@Victor: Myślę, że Mathematica, Matlab lub Octave mogą to łatwo pokonać, ponieważ warunki wewnątrz fxczęści można jeszcze bardziej skompresować w języku o lepszej ekspresji. I te języki mają również natywną obsługę obrazów (więc nie trzeba tracić znaków przy importowaniu imagemagick / gd / itp.)
SztupY
@SztupY Wiem o Lennie bardzo dobrze ... Policzę to ...
Dobra
1
Lenna jest słodka (r). W górę.
blabla999
+1 za użycie odpowiedniego narzędzia do pracy. O ile mi wiadomo, właściwym sposobem użycia imagemagick jest wywołanie obrazu najpierw, a nie opcji, niż pliku wyjściowego.
CousinCocaine
14

Matematyka

Będziemy pracować z kwadratowym regionem z amerykańskiego znaczka z Gretą Garbo. Będzie to określane jako j.

jot

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

Funkcja f przyjmuje 3 parametry:

  • i który odnosi się do obrazu
  • rs, rozmiar rastra
  • m, zmienna boolowska określająca, czy należy użyć linii siatki. (Domyślne ustawienie to True).

Używając rozmiarów rastrowych 15, 30, 45 i 75:

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

4 garbos

Nie wyobrażam sobie, żeby ktoś tworzył kostkę Rubrika z tyloma kawałkami! Niemniej interesujące ćwiczenie.


Baw się kolorami

To z wcześniejszego wpisu. Kod jest nieco inny. Graphicsjest używany zamiast ArrayPlot. Ponadto używamy pełnego stempla, nawet jeśli nie jest kwadratowy.

Istnieje 6! = 720 permutacji kolorów kostki Rubrik.

Poniżej pokazano środkowy obraz górnego rzędu (ustaw 6 zdjęć poniżej). Gdy wartości w skali szarości są ustawione od najciemniejszego do najjaśniejszego, kolory to {r, gr, b, o, y, w}. Inne odmiany jednak działają.

i to oryginalny obraz w skali szarości.

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 jest oryginalnym obrazem w skali szarości pełnego znaczka Greta Garbo.

Rasterize[garbo,RasterSize->75 rasteryzuje obraz do tablicy 75 na 75.

ColorQuantize[<>, 6] redukuje wartości skali szarości do zestawu 6.

ImageDatapobiera tablicę danych z obrazu; przychodzi do góry nogami.

Reverse odwraca tablicę danych, stąd obraz, prawą stroną do góry.

garboColors to 6 wartości skali szarości w skwantowanym obrazie.

Graphics[Raster wyświetla ostateczny obraz.

rubrikColors są wartościami RGB 6 kolorów kostki Rubrika.

Podano różne kombinacje kolorów czerwonego, zielonego, niebieskiego, pomarańczowego, żółtego i białego.

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

I kod:

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

Oto 72 (z 720) zdjęć Greta Garbo, które wykorzystują 6 kolorów kostki Rubrika. Niektóre obrazy działają lepiej niż inne, nie sądzisz?

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

mnóstwo garbos

DavidC
źródło
Greta, och Greta ... Okazało się, że lepiej niż się spodziewałem. @DavidCarraher, miła praca tutaj ...
WallyWest
@WallyWest. Dzięki. To było bardzo interesujące wyzwanie.
DavidC
Byłem tak pewien, że Mathematica pokona wyobrażenie, czy nie można grać w golfa jeszcze dalej? Czy wszystkie te funkcje są wymagane?
SztupY
1
@SztupY Połowa kodu jest poświęcona prawidłowym kolorom. Reversemożna wyeliminować, pozostawiając obraz do góry nogami, ale nie widzę żadnych innych możliwości. Mathematica jest wyrazista, ale używa dużych słów. Ktoś biegły w obrazach prawdopodobnie może nieco zmniejszyć rozmiar kodu, ale wątpię, by pobił twój kod imagemagick.
DavidC
1
Rzeczywiście istniały pewne niespójności w całym kodzie. Mam nadzieję, że już ich nie ma. iprzytrzymaj oryginalny obraz. groznacza zieleń Rubrika. godnosi się do zrasteryzowanych i skwantowanych danych obrazu dla obrazu w skali szarości.
DavidC
6

Smalltalk (Smalltalk / X), 289 139 *

wejście: i; wyjście: 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)]

wkład:

wprowadź opis zdjęcia tutaj

wydajność:

wprowadź opis zdjęcia tutaj

powiększony:

wprowadź opis zdjęcia tutaj

(dla wszystkich młodych ludzi: to NIE jest Madonna ;-)

[*] Nie policzyłem powiększenia do 75x75 (pierwsza linia) - mógłbym użyć już zmienionego rozmiaru jako wejścia. Mam nadzieję, że wszystko jest w porządku.

blabla999
źródło
Uwielbiam Marilyn Monroe ... Świetny wybór ... Zmiana rozmiaru była opcjonalną funkcją ...
WallyWest
4

Postscriptum i PRAWDZIWE kolory Rubika! ;-)

Cóż, to rozwiązanie jest trochę nie na temat, ponieważ ogranicza się do nieco wysoce wyspecjalizowanej sfery. Ale po wielu frustracjach związanych np. Z „pytaniem o dziwne liczby” (niezdolność do stworzenia czegoś praktycznie działającego) postanowiłem coś opublikować, więc wyciągnąłem to ze stosu niedokończonych bazgrołów i sprawiłem, że jest to reprezentatywne.

Rozwiązanie wykorzystuje fakt, że pierwsza wersja tego pytania określa wymagane kolory poprzez link do strony, która wyraźnie stwierdza, że ​​należy stosować kolory Pantone®, a kolory RGB są jedynie przybliżeniami. Potem pomyślałem, dlaczego miałbym dokonywać przybliżeń, skoro mogę robić prawdziwy kolor? - :)

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

Ten kod należy zapisać np., rubik.psA następnie dostarczyć do Ghostscript ze zwykłą inkantacją:

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

Następnie czeka cię w następnym wierszu, aby wprowadzić nazwę pliku JPG, np

kelly.jpg

i jeśli wszystko pójdzie dobrze, zapisuje dane wyjściowe w out.psdpliku.

Wejście musi być kwadratowe RGB JPEG (dowolnego rozmiaru), wyjście to PSD z kanałami kolorów dodatkowych. Potrzebujesz programu Photoshop, aby wyświetlić plik. Zmiana urządzenia GS psdcmykna cokolwiek innego nie da nic użytecznego. JPEG jako dane wejściowe - ponieważ interpreter PostScript może bezpośrednio dekodować strumień danych. Kwadratowy kształt - ponieważ program korzysta sqrtz długości łańcucha, aby znaleźć szerokość (i wysokość) obrazu.

Pierwsze wiersze określają rozmiar obrazu wyjściowego (można zmienić z domyślnego 75) i paletę kolorów (kolory i ich liczbę można również zmienić). Wydaje mi się, że wszystko inne nie jest zakodowane na stałe.

Co się dzieje? Strumień trypletów RGB jest konwertowany w locie na ciąg wartości w skali szarości (za pomocą prostej formuły), budowany jest zwykły 8-bitowy słownik obrazków contone i używany do malowania 5 identycznych obrazów na sobie w 5 Separationprzestrzeniach kolorów. Sztuką jest zastosowanie funkcji przenoszenia przed każdym wywołaniem imageoperatora. Np. W przypadku żółtej farby funkcja zwraca 0 dla wartości wejściowych tylko w zakresie 0,167 .. 0,333, a w przeciwnym razie 1.

Wkład:

wprowadź opis zdjęcia tutaj

Zrzut ekranu wyjścia 75x75 otwartego w Photoshopie, powiększony 800%:

wprowadź opis zdjęcia tutaj

I paleta kanałów Photoshop:

wprowadź opis zdjęcia tutaj

użytkownik 2846289
źródło
1
+1 za używanie Grace Kelly ... masz mój pełny szacunek ...
WallyWest
3

DO#

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

Musisz uruchomić go z 3 parametrami:

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

Gdzie 75jest maks. szerokość / wysokość d:\test.jpgjest plikiem wejściowym i d:\out.pngplikiem wyjściowym.

Dane wyjściowe dla różnych zdjęć w tym konkursie:

WallyWest Sztuczka 1 Sztuczki 2 blabla999

Moja własna celebrytka:

Garth!

Wydajność:

Garth 75 Garth 225

Jednak inne (większe niż 75 x 75) rozmiary dają lepsze obrazy:

150 300

A jeśli będziemy trzymać się prezydentów:

DubbaYa 294 DubbaYa 75 DubbaYa 225

Ponieważ nie jest to (już?) Kodegolf, nie zadałem sobie trudu, aby zbytnio „zminimalizować” kod. Ponadto, ponieważ instrukcje nie wspominały wyraźnie o tym, że obraz musi mieć tę samą szerokość co wysokość (kwadrat), nie zawracałem sobie głowy kadrowaniem; I zrobić , więc upewnij się, że obraz jest wielokrotnością szerokości 3 pikseli / high. Jeśli chcesz kwadratowe obrazy, użyj kwadratowych danych wejściowych : PWreszcie; algorytm jest daleki od optymalnego.

Jeszcze kilka (ponieważ ludzie głosują na gorące laski / bohaterów internetowych więcej : P)

Kari Byron 300 Kari Byron 75 Kari Byron 225 Hoff 300 Hoff 75 Hoff 225

RobIII
źródło
3

Brainfuck

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

Wymaga to interpretera / kompilatora BF, który ma -1 jako EOF i który ma więcej niż 8 bitów komórek JEŻELI jeden z czerwonych pikseli ma 255. W przeciwnym razie przestanie przedwcześnie, ponieważ nie będzie mógł różnić się między EOF a wartością 0xFF . Z jitbf masz wszystko, co maszyna ma jako liczbę całkowitą i możesz to zrobić, aby wymusić -1 jako EOF:

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

Renderowany format pliku obrazu to pełny plik RGB PNM (P6), nieprzetworzony jako opcja w Gimp.

Używa tylko kanału zielonego (który jest jednym z wielu sposobów konwersji kolorowego obrazu na skalę szarości). Zmniejsza wartość o 43 bez zmniejszania wartości poniżej zera, aby dowiedzieć się, którego koloru rubika użyć, i ma przełącznik, który drukuje odpowiedni kolor RBG, który odpowiada.

Zdjęcie Angeliny Jolie z Hackers (1995) zmniejszone do 75x75 i przetworzone za pomocą aplikacji:

Angelina Jolie 75x75 / dozwolony użytek Angelina Jolie 75x75 w kolorach kostki Rubika / dozwolony użytek Ten sam skalowany 6x

To samo, tylko użyłem oryginalnego rozmiaru :

To samo tylko nie zmniejszono w pierwszej kolejności / dozwolonego użytku

A ponieważ jestem medium, oto także prezydent:

Arnold Schwarzenegger CC z Wikipedii

Sylwester
źródło
Poza tematem, ale dzisiejszy xkcd ma również odniesienia do hakerów (1995)
Sylwester
1
Ten również: xkcd.com/1247
Cień
1

Cel C

Widziałem to wyzwanie zeszłej nocy i miałem trochę nieco mylący czas -[NSArray indexOfObject:inSortedRange:options:usingComparator:], stąd opóźnienie.

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

Uruchomiłem go na iPadzie tak:

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

Przed Danny DeVito Wcześniej Po Danny DeVito After

Przed Grace Kelly wcześniej Po Grace Kelly After

Max Chuquimia
źródło
1

Pyton

Format: python rubik.py <input> <max_cubes> <output>.

Obejmuje piksele do skali szarości przy użyciu sugerowanego algorytmu.

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

Wkład:

Sandro Pertini
(źródło: ilmamilio.it )

Wyjście z max_cubes = 25:

Sandro Pertini, Rubik'd 1

Wyjście z max_cubes = 75:

Sandro Pertini, Rubik'd 2

Wyjście z max_cubes = 225:

Sandro Pertini, Rubik'd 3

Oberon
źródło
Nie brakuje białego koloru? Najciemniejsze powinny być niebieskie, ale, jak teraz widzę, dotyczy to również niektórych innych obrazów.
user2846289
@VAdimiR Ups! Mapowano je w niewłaściwej kolejności. Jeśli chodzi o biel, która się nie pokazuje, wynika to z precyzji FP (1.055 - 0.055 = 0.9999999999999999). Myślę, że będę musiał zakodować na biało, co nie jest trudne, ponieważ i tak pokaże się tylko przy oryginalnej wartości #FFFFFF.
Oberon
Jeśli chodzi o biel, moim zdaniem zakres 0..1 (jasności) jest podzielony na 6 części i wszystko 0,83..1,00 jest mapowane na biały, w przeciwnym razie nie będzie większego sensu robienie zdjęcia 6 kolorów kostki , ale tak to czytam.
user2846289
@Oberon Interesujący wybór za pomocą Pertini ... Prawie dożył wieku 94 lat ... I świetna robota za pomocą Pythona, i muszę przyznać, że nie jest to jeden z najłatwiejszych języków, z jakim się spotkałem, więc dobrze zrobione!
WallyWest