Cubify This! Una lezione in scala di grigi ... ehm ... colore ... ehm ... qualunque cosa


27

Essendo un grande fan del cubo di Rubik e della bella arte, ho lavorato per combinare i due insieme per fare delle cose davvero fantastiche. Fondamentalmente risolvendo i cubi di Rubik in miniatura per formare pixel rudimentali nella formazione del cubo di Rubik. Esempi di tale arte possono essere visti tramite questo link: http://google.com/search?q=rubik%27s+cube+art

Ora, lo scopo di questo Code Golf è quello di creare un codice che accetti un'immagine come input e quindi la converta nel modo seguente:

L'immagine viene inizialmente ridotta a colori in scala di grigi sicuri per il Web. Il motivo è dovuto al fatto che dobbiamo isolare la tavolozza di scala di grigi sicura per il Web (ad esempio 000000, 333333, 666666, 999999, CCCCCC e FFFFFF). Un algoritmo sul metodo colorimetrico di conversione in scala di grigi è disponibile su: http://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-preserving.29_conversion_to_grayscale , se desideri usarlo come ispirazione.

Uno quindi renderebbe la scala di grigi ai colori appropriati. Per scomporlo rapidamente: 000000 farà riferimento al blu di Rubik, 333333 farà riferimento al rosso di Rubik, 666666 farà riferimento al verde di Rubik, 999999 farà riferimento all'arancia di Rubik, CCCCCC farà riferimento al giallo di Rubik e FFFFFF farà riferimento al bianco di Rubik.

Preferirei che il codice risultante potesse essere riprodotto dalla tavolozza della foto direttamente ai colori di Rubik. Il metodo in due fasi dal passaggio alla scala di grigi sicura per il web e quindi alla corrispondente palette di Rubik è solo quello di darti un'idea della logica alla base del processo, ma se è più facile per te farlo, lo fai sicuramente.

I valori RGB effettivi per la tavolozza di Rubik devono corrispondere a quanto segue:

  • Rosso: # C41E3A
  • Verde: # 009E60
  • Blu: # 0051BA
  • Arancione: # FF5800
  • Giallo: # FFD500
  • Bianco: #FFFFFF

Per fare un esempio, ho ritagliato la testa di Abraham Lincoln dalla seguente immagine: inserisci qui la descrizione dell'immaginee ho reso l'algoritmo per produrre quanto segue:

inserisci qui la descrizione dell'immagine

La griglia è lì in modo che tu possa vedere come ogni singolo cubo di Rubik in miniatura dovrebbe essere configurato per creare l'immagine. La dimensione reale dell'immagine risultante è 45 pixel per 45 pixel, il che significa che (45/3) * (45/3) = 15 * 15 = 225 cubi di Rubik in miniatura verrebbero utilizzati per creare questa immagine. Non mi aspetto che tu presenti l'immagine risultante con una griglia come ho fatto io.

Quindi questo è ciò che è richiesto:

  1. L'immagine che deve essere elaborata da questo algoritmo deve avere una larghezza di x pixel per un'altezza di y pixel, in modo tale che xey siano multipli di 3. Questo serve per facilitare il rendering come parte del mosaico del cubo di Rubik. Se l'immagine è piuttosto grande, si consiglia di ridurla a qualcosa di circa 45 x 45 a 75 x 75 o di dimensioni approssimative prima dell'elaborazione. Tieni presente che questo componente di ridimensionamento è FACOLTATIVO.

  2. L'immagine deve essere convertita nella tavolozza del cubo di Rubik sestacolata per creare il mosaico.

  3. L'immagine risultante deve essere un file grafico valido dopo l'elaborazione. Per dimostrare che il tuo codice funziona, eseguilo contro un'immagine di uno dei presidenti degli Stati Uniti d'America o di una celebrità di Hollywood ben nota. Ho già usato Abraham Lincoln nel mio esempio, quindi questo presidente non può più essere usato. Assicurati di fornire la lingua che hai usato, il conteggio dei byte e il presidente / celebrità utilizzato per testare il tuo codice, compresi gli scatti prima e dopo ...

  4. Ogni voce deve avere un unico presidente / celebrità come test case. Non accetterò duplicati. Ciò garantirà che i risultati duplicati non vengano utilizzati per testare diverse voci di codice. Va benissimo dire che il tuo codice funziona, è un'altra cosa per dimostrarlo.

5. Vince il codice più corto.

Sto cambiando questo in un concorso di popolarità ... Preferirei vedere chi può farlo senza dover competere sul conteggio dei byte ... Quindi assegnerò questo insieme a un premio dopo il 28 febbraio 2014.


4
Penso che sarebbe meglio se aggiungessi i valori di Rubik RGB al post invece di fare affidamento su un link.
SztupY,

Fa "immagine da elaborare deve essere x pixel di larghezza di pixel y alto" significano che il ridimensionamento è parte di codice o l'immagine viene pre-elaborato per dimensioni richieste?
user2846289,

Ci sono stati impossibili di un cubo di Rubik se vincoli solo una faccia?
Nick T,

1
@WallyWest ADORERAI la mia app MineCam, lo fa, ma piuttosto che creare quadrati, usa i miei blocchi artigianali e lo fa anche 15 volte al secondo con la fotocamera dell'iPhone in tempo reale, convertendo così tutto il mondo intorno a te in un il mio universo artigianale. itunes.apple.com/us/app/minecam/id675845303?mt=8 (Se solo potesse anche generare un seme per detto mondo hahahaha)
Albert Renshaw,

2
@WallyWest: non si tratta di pigrizia. Il problema dovrebbe fornirti tutte le informazioni necessarie per iniziare, anche se il resto di Internet è inattivo. Tra un anno o due, quel collegamento potrebbe essere rimosso e nessuno aggiornerà il collegamento. Se fornisci informazioni sufficienti su come creare colori in scala di grigi sicuri per il web (che non è necessario per risolvere il problema), avresti potuto facilmente aggiungere una piccola tabella di mappatura, come #000000 => #0051BA, ecc.
SztupY,

Risposte:


16

Imagemagick (108)

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

La seguente chiamata:

$ 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

dove inpute outputdevono essere modificati per il nome file di input e output.

Ho contato solo i caratteri tra -resizee #FFF", se pensi che questo non sia valido, sentiti libero di commentare.

Ho usato Lenna come immagine (è apparsa in un Playboy, e chiunque lo faccia dovrebbe essere considerato una celebrità di Hollywood, giusto?)

Ingresso:

Immagine di input

Produzione:

$ 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

Immagine generata

Uscita ingrandita:

Immagine ingrandita

Note: secondo i documenti di imagemagick non è possibile avere più di un operatore condizionale in un'istruzione, ma la chiamata sembra funzionare ancora bene, quindi probabilmente questo è stato risolto e i documenti non sono stati aggiornati.

Esegui l'identificazione sull'immagine del risultato (per mostrare che i colori vanno davvero bene):

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

Se pensi che Lenna non sia considerata una vera celebrità, ecco Bruce Willis:

Bruce Original

Bruce Small

Bruce Large


+1 Penso che la tua risposta sia quasi imbattibile (o addirittura imbattibile). Ti suggerirò solo di scattare qualche foto indiscutibilmente della celebrità di Hollywood o del presidente americano e aggiungere a questo (non è necessario rimuovere Lenna, tenere entrambi). Altrimenti alcune persone noiose potrebbero lamentarsi e ridimensionare solo per quello.
Victor Stafusa,

@Victor: penso che Mathematica, Matlab o Octave potrebbero facilmente batterlo, poiché le condizioni all'interno della fxparte possono essere ulteriormente compresse in un linguaggio che ha una migliore espressività. E quelle lingue hanno anche il supporto dell'immagine nativa (quindi nessun carattere si perde se si deve importare imagemagick / gd / ecc.)
SztupY,

@SztupY Conosco molto bene Lenna ... Conterò che ... Bel lavoro anche con Bruce Willis ...
WallyWest,

1
Lenna è carina (r). Su.
blabla999,

+1 per l'utilizzo dello strumento giusto per il lavoro. Per quanto ne so, il modo giusto di usare imagemagick è chiamare prima l'immagine, rispetto alle opzioni, rispetto al file di output.
CousinCocaine,

14

matematica

Lavoreremo con una regione quadrata da un francobollo americano con Greta Garbo. Verrà indicato come 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]]

La funzione f accetta 3 parametri:

  • i che si riferisce all'immagine
  • rs, la dimensione raster
  • m, una variabile booleana che indica se utilizzare le linee Mesh. (L'impostazione predefinita è True).

Utilizzando dimensioni raster di 15, 30, 45 e 75:

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

4 ceci

Non riesco a immaginare nessuno che crei un cubo di Rubrik con così tanti pezzi! Esercizio interessante comunque.


Giocare con i colori

Questo proviene da una voce precedente. Il codice è leggermente diverso. Graphicsviene utilizzato al posto di ArrayPlot. Inoltre, utilizziamo il timbro completo anche se non è quadrato.

Ci sono 6! = 720 permutazioni dei colori del cubo di Rubrik.

Di seguito viene visualizzata l'immagine centrale della riga superiore (impostare 6 immagini di seguito). Quando i valori della scala di grigi sono disposti dal più scuro al più chiaro, i colori sono {r, gr, b, o, y, w}. Altre varianti funzionano comunque.

i è l'immagine originale in scala di grigi.

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 è l'immagine originale in scala di grigi dell'intero timbro Greta Garbo.

Rasterize[garbo,RasterSize->75 rasterizza l'immagine in un array 75 per 75.

ColorQuantize[<>, 6] riduce i valori della scala di grigi a un set di 6.

ImageDatarecupera l'array di dati dall'immagine; viene capovolto.

Reverse inverte l'array di dati, quindi l'immagine, con il lato destro rivolto verso l'alto.

garboColors sono i 6 valori in scala di grigi nell'immagine quantizzata.

Graphics[Raster visualizza l'immagine finale.

rubrikColors sono valori RGB dei 6 colori del cubo di Rubrik.

Sono fornite varie permutazioni di colore di rosso, verde, blu, arancione, giallo e bianco.

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

E il codice:

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

Ecco 72 (delle 720) immagini di Greta Garbo che usano i 6 colori del cubo di Rubrik. Alcune immagini funzionano meglio di altre, non credi?

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

garbos a bizzeffe


Greta, oh Greta ... È andata meglio di quanto mi aspettassi. @DavidCarraher, bel lavoro qui ...
WallyWest,

@WallyWest. Grazie. È stata una sfida molto interessante.
DavidC,

Ero così sicuro che Mathematica avrebbe battuto l'immagine, non si può giocare ancora a golf? Sono necessarie tutte queste funzioni?
SztupY,

1
@SztupY La metà del codice è dedicata a ottenere i colori giusti. Reversepotrebbe essere eliminato, lasciando il quadro sottosopra, ma non vedo altre opportunità. Mathematica è espressiva ma usa grandi parole. Qualcuno abile nelle immagini potrebbe probabilmente ridurre un po 'le dimensioni del codice, ma dubito che potrebbero battere il tuo codice imagemagick.
DavidC,

1
Vi erano effettivamente alcune incongruenze nel codice. Spero che ora non ci siano più. itieni l'immagine originale. grsta per Rubrik's green. gsi riferisce ai dati di immagine rasterizzati e quantizzati per l'immagine in scala di grigi.
DavidC,

6

Smalltalk (Smalltalk / X), 289 139 *

input: i; uscita: 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)]

ingresso:

inserisci qui la descrizione dell'immagine

produzione:

inserisci qui la descrizione dell'immagine

allargata:

inserisci qui la descrizione dell'immagine

(per tutti i giovani: questa NON è Madonna ;-)

[*] Non ho contato l'ingrandimento su 75x75 (la prima riga) - avrei potuto usare un input già ridimensionato. Spero che vada bene per te.


Adoro Marilyn Monroe ... Ottima scelta ... Il ridimensionamento era una funzione opzionale ...
WallyWest,

4

Postscript e VERO colori Rubik! ;-)

Bene, questa soluzione è un po 'fuori tema qui, poiché è limitata a una sfera un po' altamente specializzata. Ma dopo molta frustrazione per es. "Domanda con numeri strani" (non potendo produrre qualcosa praticamente funzionante) ho deciso di pubblicare qualcosa e così l'ho tirato fuori dalla mia pila di scarabocchi finiti a metà e l'ho reso presentabile.

La soluzione sfrutta il fatto che la prima revisione di questa domanda definisce i colori richiesti tramite il collegamento a un sito, il che afferma chiaramente che i colori Pantone (R) devono essere utilizzati e i colori RGB sono solo approssimazioni. Poi ho pensato, perché dovrei fare approssimazioni, quando posso fare il colore genuino? - :)

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

Questo codice deve essere salvato come ad es. rubik.psE quindi inviato a Ghostscript con il solito incantesimo:

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

Ti attende quindi sulla riga successiva, per l'immissione del nome del file JPG ad es

kelly.jpg

e, se tutto va bene, salva l'output su out.psdfile.

L'ingresso deve essere quadrato RGB JPEG (qualsiasi dimensione), l'output è PSD con canali di colori spot. Photoshop è necessario per visualizzare il file. La modifica del dispositivo GS da psdcmykqualsiasi altra cosa non produrrà nulla di utilizzabile. JPEG come input - perché l'interprete PostScript può decodificare il flusso di dati direttamente da esso. Forma quadrata: perché il programma si basa sulla sqrtlunghezza della stringa per trovare la larghezza (e l'altezza) dell'immagine.

Le prime righe definiscono la dimensione dell'immagine in uscita (può essere modificata dall'impostazione predefinita 75) e la tavolozza dei colori (anche i colori e il loro numero possono essere cambiati). Qualcos'altro non è codificato, credo.

Cosa sta succedendo? Il flusso di terzine RGB viene convertito al volo nella stringa di valori in scala di grigi (con formula semplice), il normale dizionario di immagini contone a 8 bit viene creato e utilizzato per dipingere 5 immagini identiche una sopra l'altra in 5 Separationspazi colore. Il trucco è applicare le funzioni di trasferimento prima di ogni invocazione imagedell'operatore. Ad esempio per la vernice gialla questa funzione restituisce 0 per i valori di input solo nell'intervallo 0,167 .. 0,333 e 1 altrimenti.

Ingresso:

inserisci qui la descrizione dell'immagine

Schermata dell'output 75x75 aperta in Photoshop, ingrandita dell'800%:

inserisci qui la descrizione dell'immagine

E palette di canali Photoshop:

inserisci qui la descrizione dell'immagine


1
+1 per l'utilizzo di Grace Kelly ... hai il mio completo rispetto ...
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;
    }
}

Devi eseguirlo con 3 parametri:

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

Dov'è 75max. larghezza / altezza, d:\test.jpgè il file di input ed d:\out.pngè il file di output.

Uscita per varie immagini in questo concorso:

Wally West SztupY 1 SztupY 2 blabla999

La mia celebrità:

Garth!

Produzione:

Garth 75 Garth 225

Tuttavia, altre dimensioni (maggiori di 75x75) producono immagini migliori:

150 300

E, se restiamo con i presidenti:

DubbaYa 294 DubbaYa 75 DubbaYa 225

Dato che questo non è (più?) Codegolf non mi sono preoccupato di "minimizzare" troppo il codice. Inoltre, poiché le istruzioni non menzionavano specificamente l'immagine doveva avere la stessa larghezza dell'altezza (quadrata), non mi sono preoccupato del ritaglio; Io faccio , però, assicurarsi che l'immagine è un multiplo di 3 pixel di larghezza / alta. Se vuoi immagini quadrate, usa gli input quadrati : PInfine; l'algoritmo è tutt'altro che ottimale.

Qualche altro (dal momento che le persone votano di più hot chicks / internet heroes : P)

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


3

Brainfuck

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

Ciò richiede un interprete / compilatore BF che ha -1 come EOF e che ha celle più alte di 8 bit SE uno dei pixel rossi è 255. Altrimenti si fermerà prematuro poiché non sarà in grado di differire tra EOF e valore 0xFF . Con jitbf hai tutto ciò che la macchina ha come dimensione intera e puoi farlo per forzare -1 come EOF:

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

Il formato del file immagine renderizzato è il file PNM RGB completo (P6), grezzo come opzione in Gimp.

Utilizza solo il canale verde (che è uno dei molti modi per convertire un'immagine a colori in scala di grigi). Riduce il valore di 43 senza ridurre il valore sotto lo zero per scoprire quale colore rubik utilizzare e avere un interruttore che stampa il colore RBG corretto che corrisponde.

Immagine di Angelina Jolie di Hackers (1995) ridotta a 75x75 ed elaborata con l'applicazione:

Angelina Jolie 75x75 / Uso corretto Angelina Jolie 75x75 nei colori del cubo di Rubik / Fair Use Stesso ridimensionato 6x

Lo stesso, ho usato solo le dimensioni originali :

Stesso solo non ridimensionato per primo / Uso corretto

E poiché sono un sensitivo, ecco anche un presidente:

Arnold Schwarzenegger CC da Wikipedia


Fuori tema, ma oggi xkcd ha anche riferimenti a Hackers (1995)
Sylwester

1
Questo vale
Shade,

1

Objective-C

Ho visto questa sfida la scorsa notte e ho avuto un tempo così leggermente confuso con -[NSArray indexOfObject:inSortedRange:options:usingComparator:], quindi il ritardo.

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

L'ho eseguito sul mio iPad in questo modo:

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

Prima Danny DeVito prima dopo Danny DeVito After

Prima Grace Kelly Prima dopo Grace Kelly After


1

Pitone

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

Copre i pixel in scala di grigi usando l'algoritmo suggerito.

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

Ingresso:

Sandro Pertini
(fonte: ilmamilio.it )

Uscita con max_cubes = 25:

Sandro Pertini, Rubik'd 1

Uscita con max_cubes = 75:

Sandro Pertini, Rubik'd 2

Uscita con max_cubes = 225:

Sandro Pertini, Rubik'd 3


Non manca il colore bianco? E il più scuro dovrebbe essere blu, ma, come vedo ora, questo è il problema anche con alcune altre immagini.
user2846289

@VAdimiR Whoops! Li ho mappati nell'ordine sbagliato. Per quanto riguarda il bianco che non appare, è a causa della precisione FP (1.055 - 0.055 = 0.9999999999999999). Penso che dovrò codificare il bianco, il che non è difficile, dal momento che verrebbe visualizzato solo con un valore originale di #FFFFFF.
Oberon

A proposito del bianco, la mia opinione era che l'intervallo 0..1 (luminosità) è diviso in 6 parti e qualsiasi cosa 0,83..1,00 è mappata sul bianco, altrimenti non avrebbe molto senso creare un'immagine di 6 colori del cubo , ma è così che l'ho letto.
user2846289

@Oberon Interessante scelta usando Pertini ... Ha quasi vissuto all'età di 94 anni ... E un ottimo lavoro usando Python, e devo ammettere che non è una delle lingue più semplici che abbia mai incontrato, così ben fatto!
WallyWest
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.