Challenge:

Write a program that outputs a graphic file 1920 pixels wide by 1080 pixels high. Every one of the 2,073,600 pixels within the graphic must be a unique colour and no colour values should be repeated. The colours should be specified in RGB and start at 0,0,0 and count upwards in sequence towards 255,255,255. You'll find a 1920 x 1080 pixel image will contain lots of blacks, blues and greens only.

For example, (a smaller cut down version). If the height was set to 5 and the width was set to 5 a 25 pixel square graphic would be output and each pixel would be a unique colour. The RGB colour array would look like this:

Array (
[0] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 0
    )

[1] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 1
    )

[2] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 2
    )

[3] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 3
    )

[4] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 4
    )

[5] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 5
    )

[6] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 6
    )

[7] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 7
    )

[8] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 8
    )

[9] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 9
    )

[10] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 10
    )

[11] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 11
    )

[12] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 12
    )

[13] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 13
    )

[14] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 14
    )

[15] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 15
    )

[16] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 16
    )

[17] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 17
    )

[18] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 18
    )

[19] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 19
    )

[20] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 20
    )

[21] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 21
    )

[22] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 22
    )

[23] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 23
    )

[24] => Array
    (
        [0] => 0
        [1] => 0
        [2] => 24
    )

)

Rules:

  • Any programming language can be used to generate the image.

  • The answer with the most upvotes wins.

  • Colours must only be used once.

  • Pixel in position 0,0 must start with colour 0,0,0

  • Colours must fall within the true color 24 bit range.

  • Image must be 1920 x 1080 pixels in size.

  • Colours must be in RGB format.

  • Using a library to output the image is ok.

  • Output must be in the format of a graphic file e.g. output.png

  • Output as text which represents the colour values doesn't count, the code must output a graphic file.

  • File size of the output image doesn't matter.

  • You must be able to view the output by opening it as a graphic in the chrome web browser.

I would be impressed if you mange to do this with really short code, your program also outputs the time in elapsed seconds taken to generate the image embedded within the image itself overlaid on the sequential pixels, your program outputs the image within 10 seconds. I would be really impressed if your program outputs the image within 1 second.

  • 3
    If this is code golf, how do the bonuses factor in? A 10-character bonus seems very very small for code that (effectively) predicts the future. – Kendall Frey Jan 22 '14 at 21:36
  • 1
    Now there are no bonus values! How are we supposed to take those bonuses? Ignore them? – Kendall Frey Jan 22 '14 at 21:39
  • 3
    Choose a terse language and terse PNG API (critical!) and then count to 2,073,600. Sorry to be so critical, @BenPaton, but I predict the choice of language and API will be the biggest factor here, not a display of clever programming. But I'm often wrong and even less often clever. :-) – Darren Stone Jan 23 '14 at 1:54
  • 2
    The requirement for a black pixel at x==y==0 seems a bit arbitrary. In any case, it's ambiguous because these coordinates could refer to either the top left or bottom left corner of the image. – squeamish ossifrage Jan 24 '14 at 22:38
  • 3
    Duplicate of Images with all colors; the only difference is the limitation in the color palette to just be the blues and greens, rather than all of them, which doesn't make a huge difference to the problem but makes the output less pretty. – user62131 Dec 1 '16 at 0:27

15 Answers 15

up vote 36 down vote accepted

Python - 660+ bytes

Incremental Version

Full Size: http://www.pictureshack.net/images/57626_all_colors.png (4.52MB)

This is an image based on a Julia Set fractal. Each color is added to the image incrementally, although there is a substantial amount of pre-calculation.


Luminosity Version

Full size: http://www.pictureshack.net/images/95389_all_colors4.png (5.24MB)

I've added an option to iterate each color by luminosity, rather than by index. This doesn't qualify as "counting up" from zero, but this seems to be a lax requirement. It's interesting that these two orderings expose completely different structures in the image. To use this, set the use_luminosity flag to True.


Source

Requires PIL.

Be warned: this will take several minutes to execute. Using PyPy with Pillow runs in about one fifth the time of CPython with PIL, so I would recommend that, if possible.

from PIL import Image, ImageDraw

use_luminosity = True

dim = (1920,1080)

img = Image.new('RGB', dim)
draw = ImageDraw.Draw(img)

xstart = -.776707
ystart = -.134663

a = []

xd = 1.6 / 8192 / dim[0]
yd = 0.9 / 8192 / dim[1]

for x in range(dim[0]):
  print x
  for y in range(dim[1]):
    z = d = complex(xstart + x*xd, ystart + y*yd)
    c = 0
    while abs(z) < 2 and c < 5000:
      z = z*z + d
      c += 1
    a += [(c, -abs(z), x, y)]

a = a[1:]
a.sort(reverse = True)

t = [(i>>16, 255&i>>8, 255&i) for i in range(1, dim[0]*dim[1])]
if use_luminosity:
  t.sort(key = lambda c: c[0]*3 + c[1]*10 + c[2], reverse = True)

r = 0
for c,d,x,y in a:
  draw.point((x,y), t[r])
  r += 1

img.show()

Edit: updated so that #000000 is at the upper-left, as specified.
Edit: added a flag to iterate colors by luminosity.
Edit: switched to native complex calculations, and integer luminosity weights, which are slightly faster.


Solutions I worked on before the primary criterion became

PHP - 161 bytes

<?header('Content-type: image/bmp');
ob_start();
echo'BM'.pack('I5S2',0,0,26,12,70780800,1,24);
for(;$i=($i-256)%2073601;)echo pack('CS',~$i,~$i>>8);
ob_end_flush();

This is going for fastest output possible. No library is used, just a pre-computed header, and direct byte output. Runs in less than 2s on my comp. By incrementing by 256 rather than 1, it produces a pseudo-gradient effect, with no real computation needed. The only downfall is that (0, 0) is not black, but the result looks a lot nicer.

ob_start(); and ob_end_flush(); aren't strictly necessary, but buffering the output makes it run a lot faster.

Other interesting increments include:

17: http://i.stack.imgur.com/ieyyZ.png
103: http://i.stack.imgur.com/WD2wa.png
326: http://i.stack.imgur.com/c4DSF.png
557: http://i.stack.imgur.com/eTTWE.png
943: http://i.stack.imgur.com/7rrmR.png
2125: http://i.stack.imgur.com/Ct1kM.png

And many others. Although, most patterns that look like anything resemble stripes of some sort


PHP - 105 bytes

<?=BM.pack(I5S2,header('Content-type:'),0,26,12,70780800,1,24);
for(;$i<2073600;)echo pack(CS,$i,$i++>>8);

Reckless disregard version.

  • Given a broken Content-type header, Chrome will do its best to figure out what it was sent. In this case, it correctly identifies it as image/bmp. The lastest versions of FireFox and IE are also able to fix the broken header.
  • The barewords BM, I5S2, and CS will generate a NOTICE error. To prevent corruption of the image, error reporting in php.ini will need to be set to prevent this (e.g. error_reporting = E_ALL & ~E_NOTICE).
  • No output buffering. The image is constructed 3 bytes at a time, which is noticeably slower.
  • The point (0, 0) is considered to be the lower left, rather than upper left.


PHP-CLI - 83 bytes

<?=BM.pack(I5S2,0,0,26,12,70780800,1,24);
for(;$i<2073600;)echo pack(CS,$i,$i++>>8);

Run directly from the command line and piped to a file (e.g. $ php all-colors.php > out.bmp), no Content-type header is necessary. The resulting file is identical to the 105 byte version, and can be viewed in Chrome.

  • 2
    I really like the pattern, very trippy! – Ben Paton Jan 24 '14 at 15:15
  • I love the first image, but it appears to violate the rule which calls for pixel 0,0 to be RGB 0,0,0. – Iszi Jan 24 '14 at 19:44
  • @primo Looks good now to me. – Iszi Jan 24 '14 at 20:44
  • 1
    I like the luminosity version so much I have set it as my desktop wallpaper :) – Ben Paton Jan 25 '14 at 20:10

C with the GD graphics library (err, about 2.5 KB?)

The rules didn't prohibit modifying an existing image. I made a program to replace all of an image's pixels with sequential RGB values from #000000 to #1fa3ff, and I'm quite pleased with the results. Here's what it produced from from a photo posted to Flickr by Michael Carian (cc-by-sa 2.0):

640x360 pixel thumbnail of test results

(The raw output image is rather large (5.6 MB))

Here's a close-up of the top left corner (scaled up 400%):

Enlarged view of top left corner

The processing time is about 3 seconds for an image of this size:

$ time ./a.out foodface.png outfile.png
File accepted; 1920x1080 pixels
Saving...
Finished

real    0m3.251s
user    0m2.392s
sys 0m0.169s

and yes, all the pixels are different colours:

$ identify -format %k outfile.png
2073600

(identify is an ImageMagick utility; the -format %k option counts the number of unique colours in an image)

Here's the source code:

#include <stdio.h>
#include <stdlib.h>
#include <gd.h>

#define FIRST_PIXEL_MUST_BE_BLACK 1

#define luminance(rgb) (((rgb>>16)&0xff)*77+((rgb>>8)&0xff)*150+(rgb&0xff)*29)

typedef struct { int lum; int rgb; } pal;      /* Colour palette */
typedef struct { int lum; int x; int y; } pix; /* Pixel list */

/* Callback function for qsort */
int pcomp(const void *a, const void *b) {
  return ((pal *)(a))->lum-((pal *)(b))->lum;
}

int main(int argv, char *argc[]) {
  FILE        *infile,*outfile;
  gdImagePtr  img;
  int         img_width;
  int         img_height;
  int         npixels;
  int         x,y,i;
  int         rgb,colour_ref,c;
  pal         *palette;
  pix         *pixels;

  if (argv!=3) return printf("Usage: %s <source> <destination>\n",argc[0]);

  if (!(infile=fopen(argc[1],"r"))) {
    return printf("Can't open source file <%s>\n",argc[1]);
  }
  if (!(img=gdImageCreateFromPng(infile))) {
    return printf("Bad PNG file <%s>\n",argc[1]);
  }
  fclose(infile);

  img_width=img->sx;
  img_height=img->sy;
  npixels = img_width * img_height;
  printf("File accepted; %dx%d pixels\n",img_width,img_height);

  /* Allocate storage for palette and pixel data */
  palette = malloc(npixels * sizeof(pal));
  if (!palette) return printf("Out of memory\n");
  pixels = malloc(npixels * sizeof(pix));
  if (!pixels) return printf("Out of memory\n");

  /* Create palette and sort by luminance */
  for (i=0; i<npixels; i++) {
    palette[i].rgb=i;
    palette[i].lum=luminance(i);
  }
  qsort(palette,npixels,sizeof(pal),pcomp);

  /* Sort image pixels by luminance */
#if FIRST_PIXEL_MUST_BE_BLACK == 1
  colour_ref = gdImageColorAllocate(img,0,0,0);
  gdImageSetPixel(img,0,0,colour_ref);
#endif

  for (x=y=i=0;i<npixels;i++) {
    rgb = gdImageGetTrueColorPixel(img,x,y);
    pixels[i].x=x;
    pixels[i].y=y;
    pixels[i].lum=luminance(rgb);
    if (!(x=++x%img_width)) y++;
  }
#if FIRST_PIXEL_MUST_BE_BLACK == 1
  qsort(pixels+1,npixels-1,sizeof(pix),pcomp);
#else
  qsort(pixels,npixels,sizeof(pix),pcomp);
#endif

  /* Now use the palette to redraw all the pixels */
  for (i=0;i<npixels;i++) {
    c = palette[i].rgb;
    colour_ref = gdImageColorAllocate(img,c>>16,(c>>8)&0xff,c&0xff);
    gdImageSetPixel(img,pixels[i].x,pixels[i].y,colour_ref);
  }

  printf("Saving...\n");
  if (!(outfile=fopen(argc[2],"w"))) {
    return printf("Can't open <%s> for writing\n",argc[2]);
  }
  gdImagePng(img,outfile);
  fclose(outfile);
  gdImageDestroy(img);
  printf("Finished\n");
  return 0;
}
  • Woah, that's amazing! :D +1 Also, 2.463 KB :P – Doorknob Jan 25 '14 at 23:55

C++, 750 bytes

Mandelbrot set A Full resolution PNG (5.1MB)

The code creates a collection of all integers from 0-1080*1920, then sorts them by overall brightness. It then creates a Mandelbrot set, and sorts the positions based on their escape iteration and value. Then it walks through both sets, assigning colors in order from dark to bright to the Mandelbrot values smallest to largest. Finally, it writes a 32 bit per pixel BMP image to the output filename specified as a command line parameter.

#include <windows.h>
#include <vector>
#include <algorithm>
#define X _complex
#define U int
#define S(j,g)std::sort(j.begin(),j.end(),g);
U w=1920,h=1080;
WORD q[27]={'MB',36918,126,0,0,54,0,40,0,w,0,h,0,1,32,0,0,36864,126};
#define V(a,b)((a>>b)&255)
#define L(z)V(z,16)*.3+V(z,8)*.6+V(z,0)*.1
#define F for(c=0;c<w*h;c++)
U C(U a,U b){return L(a)<L(b);}
U M(X a,X b){return a.x<b.x;}
U main(U c,char**v){
std::vector<U>l;
std::vector<X>D;
F l.push_back(c);
U*i=new U[c];
DWORD p;
F{float r=0,i=0,R;p=0;
for(;p<w&&r*r+i*i<4;p++){R=r*r-i*i;i=2*r*i+(c/w-h/2)/400.;r=R+(c%w-w/2)/400.;}
X d={-p-r*r-i*i,c};
D.push_back(d);}
S(l,C)
S(D,M)
F i[(U)D[c].y]=l[c];
void*f=CreateFileA(v[1],4<<28,0,0,2,0,0);
WriteFile(f,q,54,&p,0);
WriteFile(f,i,w*h*4,&p,0);}

The code isn't fully golfed, but it's not going to get too much smaller.

C - 854 bytes (when squeezed)

I originally had something with cyan, magenta and yellow corners and smooth gradations of colors which looked really nice, but it didn't meet the specs.

The following fulfills the specs: uses the "first" 2,073,600 colors, no repetitions, and black in the top left corner.

Ooh!

How it works is kind of cool. It builds an array with the colors, then sorts vertically and horizontally by different criteria a couple of times. The end result are pleasing transitions between blue & green and between dark & light. It takes about 1.5 seconds to run. Compile using: gcc -o many many.c -lm and run using: ./many > many.ppm

#include <stdlib.h>
#include <stdio.h>

#define W 1920
#define H 1080

typedef struct {unsigned char r, g, b;} RGB;

int S1(const void *a, const void *b)
{
        const RGB *p = a, *q = b;
        int result = 0;

        if (!result)
                result = (p->b + p->g * 6 + p->r * 3) - (q->b + q->g * 6 + q->r * 3);

        return result;
}

int S2(const void *a, const void *b)
{
        const RGB *p = a, *q = b;
        int result = 0;

        if (!result)
                result = p->b - q->b;
        if (!result)
                result = p->g - q->g;
        if (!result)
                result = q->r - p->r;

        return result;
}

int main()
{
        int i, j, n;
        RGB *rgb = malloc(sizeof(RGB) * W * H);
        RGB c[H];

        for (i = 0; i < W * H; i++)
        {
                rgb[i].b = i & 0xff;
                rgb[i].g = (i >> 8) & 0xff;
                rgb[i].r = (i >> 16) & 0xff;
        }

        qsort(rgb, H * W, sizeof(RGB), S1);

        for (n = 0; n < 2; n++)
        {
                for (i = 0; i < W; i++)
                {
                        for (j = 0; j < H; j++)
                                c[j] = rgb[j * W + i];
                        qsort(c, H, sizeof(RGB), S2);
                        for (j = 0; j < H; j++)
                                rgb[j * W + i] = c[j];
                }

                for (i = 0; i < W * H; i += W)
                        qsort(rgb + i, W, sizeof(RGB), S1);
        }

        printf("P6 %d %d 255\n", W, H);
        fwrite(rgb, sizeof(RGB), W * H, stdout);

        free(rgb);

        return 0;
}

FYI, this was the original image...

Ooh!

And for those interested in the code used to generate this image:

#include <stdio.h>
#include <math.h>

int main(int argc, char **argv)
{
        int x, y;
        int w = (argc > 1)? atoi(argv[1]): 1920;
        int h = (argc > 2)? atoi(argv[2]): 1080;
        double l = hypot(w, h);

        fprintf(stdout, "P6 %d %d 255\n", w, h);

        for (y = 0; y < h; y++)
        {
                for (x = 0; x < w; x++)
                {
                        unsigned char v[3];
                        v[0] = floor(256 * hypot(0 - x, h - y) / l);
                        v[1] = floor(256 * hypot(w - x, h - y) / l);
                        v[2] = floor(256 * hypot(w - x, 0 - y) / l);
                        fwrite(v, sizeof(unsigned char), 3, stdout);
                }
        }

        return 0;
}
  • The graduation of the colour in this is really nice. I find the output from this computationally generated image actually quite aesthetically pleasing. I could quite easily use this as a desktop wallpaper. Well done! – Ben Paton Jan 24 '14 at 23:01
  • Looks nice, but has some problems (1) non-unique pixel values (easily checked: ./a.out | hexdump | head shows 7d ff de repeated lots of times), (2) doesn't use sequential RGB values from 000000 thru 1dffff, and (3) pixel at (x=0,y=0) is not black. (Although I can't see the point of (3) myself.) – squeamish ossifrage Jan 24 '14 at 23:04
  • @squeamishossifrage Yeah, I thought the specs were overly restrictive and at the same time didn't allow for file formats with more than 8 bits per primary or 4 channels per pixel, which, if I used 16 bits per primary, would guarantee uniqueness. Since it is a popularity contest, I'll leave it up, maybe it gets a vote or two... – Yimin Rong Jan 25 '14 at 0:14
  • @squeamishossifrage It doesn't say you need to iterate from 0 to x1dffff, only that it starts with black and go upwards towards white but not how exactly. – Sylwester Jan 25 '14 at 0:18
  • @Sylwester It says you're supposed to count in sequence, and the next sentence says You'll find a 1920 x 1080 pixel image will contain lots of blacks, blues and greens only. Which bit have I misunderstood? (Apart from getting 0x1dffff wrong; should have been 0x1fa3ff.) – squeamish ossifrage Jan 25 '14 at 0:23

Racket

Never used racket object oriented programming before (message passing) so I'm not sure this is optimal, but it seems to get the job done.

#lang racket
(require racket/draw)
(let* ((x 1920) (y 1080) (b 256) (bb (* b b)) (pic (make-object bitmap% x y)))
  (let loop ((c 0) (v 0))
    (when (> (* x y) c)
      (send pic set-argb-pixels (modulo c x)   ; x
                                (quotient c x) ; y
                                1              ; width
                                1              ; height
                                (list->bytes 
                                 (list 0                            ; alpha
                                       (modulo v b)                 ; red
                                       (quotient v bb)              ; green 
                                       (modulo (quotient v b) b)))) ; blue
      (loop (+ c 1) (+ v 8))))
  (send pic save-file "image.png" 'png))

Image with many colors

By not using the 3 first bits in the red channel I get all three colors in my result image.

Brainfuck

The code prints out a 24bit BMP image to STDOUT for 8 bit cell BF interpreters. It creates the same image as the Racket version. It's based on the pnm version.

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

Ubuntu ships with bf that has 8 bit cells:

bf img.bf > image.bmp

Old version that violates being able to open from Chrome. It makes a .pnm file that are compatible with most image viewers.

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

Ruby, 109

require'chunky_png';i=ChunkyPNG::Image.new 1920,1080
i.area.times{|v|i[*(v.divmod(1080))]=v<<8|255};i.save ?i

EDIT: I should note that I submitted this when the question was still tagged , before it became a so I was going for short code. This is not very imaginative but I believe it to be a valid submission.

Color values range from 00 00 00 to 1f a3 ff, incrementing by 1, so the lack of red in the result is not surprising.

output1

For the cost of adding 1 character to the source code length (replace <<8 with <<11), the following output can be had. This covers more range of the spectrum at the cost of blue resolution. It increments through RGB space at eight times the rate. Color values range from 00 00 00 to fd 1f f8.

enter image description here

  • 1
    Your entry is really good. Your first image looks exactly like I was expecting it to. Well done and thanks for having a go. Impressed you did this so quickly and with so little code. – Ben Paton Jan 23 '14 at 21:49

Updated, first version did not have all colors unique in 24-bit space:

Mathematica: 110

x = 1920; y = 1080; Image[
 ParallelTable[
  List @@ ColorConvert[Hue[h, 1, (b + h)/2], "RGB"], {h, 0, 1 - 1/y, 
   1/y}, {b, 0, 1 - 1/x, 1/x}]]

unique colors

Rules verification:

list = ParallelTable[
  List @@ ColorConvert[Hue[h, 1, (b + h)/2], "RGB"], {h, 0, 1 - 1/y, 
   1/y}, {b, 0, 1 - 1/x, 1/x}]

First pixel is black:

list[[1, 1]]
{0., 0., 0.}

All colors are unique:

id = ImageData[Image[list], "Bit16"]]
Length[DeleteDuplicates[Flatten[id, 1]]] == 1920*1080
True

Mathematica: 146

x = 1920; Image[
 Partition[
  ParallelTable[
   List @@ ColorConvert[Hue[c, 1, c^.01], "RGB"], {c, 0, 1, 1/(
    x*1080)}], x]]

colors

Takes 14.778 seconds.

Rules verification:

list = Partition[
  ParallelTable[
   List @@ ColorConvert[Hue[c, 1, c^.01], "RGB"], {c, 0, 1, 1/(
    x*1080)}], x];

First pixel is black:

list[[1, 1]]
{0., 0., 0.}

All colors are unique:

Length[DeleteDuplicates[Flatten[list, 1]]] == 1920*1080
True

  • Your image has only 394,460 unique colours. Convert your RGB values to 8-bit integers before flattening and you'll see why. – squeamish ossifrage Jan 25 '14 at 12:04
  • @squeamishossifrage updated. – shrx Jan 25 '14 at 13:17

Python - 104

from PIL import Image
a=list(range(2073600))
i=Image.new("RGB",(1920,1080))
i.putdata(a)
i.save("o.png")

This is the version, which would have been for the code-golf challenge. As it is just increasing the value from 0 up to 2073599, it contains only unique colors.

short version

Python - 110

As I didn't like the above version (the colorrange isn't fully used), I tried something like the following:

from PIL import Image
a=list(range(0,2073600*8,8))
i=Image.new("RGB",(1920,1080))
i.putdata(a)
i.save("o.png")

extended version, but better looking

Python - 122

Another extension to the above:

from PIL import Image
a=[(i<<3,i)[i%2]for i in range(2073600)]
i=Image.new("RGB",(1920,1080))
i.putdata(a)
i.save("o.png")

even nicer

  • i.show() can be used to open the image in the default viewer. There isn't a strict requirement that it be saved to a file. – primo Jan 24 '14 at 22:23
  • well. it was, when it was still a code-golf challenge. but thanks for the hint :) – Dave J Jan 24 '14 at 22:33
  • also .show() does not work for me. Dunno why. :P – Dave J Jan 24 '14 at 22:51

Processing, 301
This is not an attempt at the most terse solution, but it maintains all of the control to achieve the desired arrangement of colors. Yes, the colors are not consecutive, but that is no fun. uniqe.png

int w = 1920;
int h = 1080;
void setup(){
  size(w, h);
  int x = 0; int y = 0;
  for(int i=0; i<w*h; i++){
    stroke(
      (i >> 0) & 0xFF,
      (i >> 6) & 0xFF,  
      (i >> 3) & 0xFF
    );
    if (y % h == 0){
      y = 0;
      x++;
    }
    point(x, y);
    y++;
  }
  save("unique.png");
}
  • Challenge requires pixel 0,0 to be RGB 0,0,0. I see 31,31,31. In fact, the whole column zero appears to be that color. – Iszi Jan 24 '14 at 19:47

Visual Basic .NET, 273 bytes

Imports System.Drawing : Module Module1
    Sub Main()
        Dim b As New Bitmap(1920, 1080) : For i As Integer = 0 To 2073599 : Dim x = 0 : b.SetPixel(Math.DivRem(i, 1080, x), x, Color.FromArgb(i + &HFF000000)) : Next : b.Save("output.png")
    End Sub
End Module

This outputs a 5.61 MB file:

putput.png

The code above is a compressed version of this more readable code. Spaces were removed to save bytes.

Imports System.Drawing
Module Module1
    Sub Main()
        Dim b As New Bitmap(1920, 1080)
        For i As Integer = 0 To 2073599
            Dim x = 0
            b.SetPixel(Math.DivRem(i, 1080, x), x, Color.FromArgb(i + &HFF000000))
        Next
        b.Save("output.png")
    End Sub
End Module

Link to the image: http://µ.pw/k

ImageMagick - Convert 119

Lets use the convert from the ImageMagick toolbox to create images. It runs in 0 seconds. It is golfed to 119 characters. I overlay two gradients (red-blue and black-white) convert them to HSL and back to RGB.

G=gradient;convert -size 900x900 $G:red-blue \( $G: -rotate 90 \) -compose CopyRed -resize 1920x1080\! -composite o.png

Output2

Examples of gradient overlay can be found in the ImageMagick manual pages.

  • 1
    It's nice, but the colours aren't unique. Try this: identify -format %k o.png. I got 1762920, not 2073600 – squeamish ossifrage Jan 26 '14 at 21:57
  • thnx. another point is the image does not start with RGB(0,0,0) in the top left. Working on a fix... – CousinCocaine Jan 26 '14 at 21:59
  • @squeamishossifrage, thanks for the identify command. Got it fixed now. – CousinCocaine Jan 26 '14 at 22:09

PHP, 507

Image of the output

You will probably need to increase the amount of memory allocated to PHP in order to run. Uses GD. Takes around 9 seconds to generate the image.

$a=microtime(true);$c=1920;$d=1080;$e=$c*$d;$f=@imagecreatetruecolor($c,$d);$h=255;$j=2200000;$k=array();$l=1;for($m=0;$m<=$h;$m++){for($n=0;$n<=$h;$n++){for($o=0;$o<=$h;$o++){if($l<=$j){$k[]=array($m,$n,$o);$l++;}else{break;}}}}while($p<=$e){for($q=0;$q<=$c;$q++){for($s=0;$s<=$d;$s++){$t=imagecolorallocate($f,$k[$p][0],$k[$p][1],$k[$p][2]);imagesetpixel($f,$q,$s,$t);$p++;}}}$u=number_format((microtime(true)-$a),4).' seconds';imagestring($f,6,10,10,$u,$v);header('Content-Type: image/png');imagepng($f);

Link to the output image: http://i.stack.imgur.com/AAKqW.png

See it running on the web: http://ben-paton.co.uk/portfolio/pixel.php?w=1920&h=1080

  • Doesn't this validate the requirement of 2,073,600 unique colors since text for the generation time is all black? Or does that not count since it's technically an overlay? – Iszi Jan 24 '14 at 19:46
  • Yes I suppose I hadn't thought about that. When I first thought about doing this I thought it would be fun to have a desktop size wallpaper with no two pixels the same colour. Then as I started to play with code that did this I got interested in the speed the image generated. I suppose a really perfect solution would use different colour pixels for the text as well but maybe it's easier to say that doesn't count as I'm not sure it would be easy to read. – Ben Paton Jan 24 '14 at 23:10
  • I just now noticed I said "validate" when I meant "violate". Oh, well. You got it. – Iszi Jan 25 '14 at 0:28

DELPHI/PASCAL (Version #1), 361 bytes

program P;
{$APPTYPE CONSOLE}
uses
  System.SysUtils, Vcl.Imaging.pngimage,System.UITypes;
var a : TPNGObject; h,w: Integer; c : TColor;
begin
   a :=TPNGObject.CreateBlank(COLOR_RGB, 16, 1920, 1080);
   for h := 0 to 1020 do
     for w := 0 to 1920 do
         begin
         a.Pixels[h,w]:= c ;
         inc(c);
         end;
   a.SaveToFile('e:\t.png');
end.
  • 1
    Thanks for submitting an alternative delphi solution. Are you able to upload an example image form the output? – Ben Paton Jan 28 '14 at 13:37

Tcl/Tk, 149

150

set p [image c photo -w 1920 -h 1080]
set y 0
time {set x 0
time {$p p [format #%06x [expr $y*1920+$x]] -t $x $y
incr x} 1920
incr y} 1080
$p w c.png

colors

Java 411 386+24 bytes

Golfed

import java.awt.image.*;()->new BufferedImage(1920,1080,1){{long t=System.currentTimeMillis();int q=-1;for(int i=0;i<getWidth();i++)for(int j=0;j<getHeight();j++)setRGB(i,j,q++);java.io.File f=new java.io.File(System.getProperty("user.home"),"Desktop"+System.getProperty("file.separator")+(System.currentTimeMillis()-t)+".png");javax.imageio.ImageIO.write(this,"png",f);java.awt.Desktop.getDesktop().open(f);}}

Ungolfed

import java.awt.image.*;
() -> new BufferedImage(1920, 1080, 1) {
        {
            long t = System.currentTimeMillis();
            int q = -1;
            for (int i = 0; i < getWidth(); i++)
                for (int j = 0; j < getHeight(); j++)
                    setRGB(i, j, q++);
            java.io.File f = new java.io.File(System.getProperty("user.home"),
                    "Desktop" + System.getProperty("file.separator")
                            + (System.currentTimeMillis() - t) + ".png");
            javax.imageio.ImageIO.write(this, "png", f);
            java.awt.Desktop.getDesktop().open(f);
        }
    }

Result

102.png

Explanation

This is not my attempt at the shortest solution, but rather the most portable. Only left import for BufferedImage because the other's didn't save bytes. Rather than loading the Image into a JPanel and writing on it, I saved the time it takes from beginning until writing to disk as the filename. For me, this took this resulted in filenames of about ~110 ms, whereas the time from beginning until end usually took ~500ms. Lastly, it should be platform independent as I tested in both Windows and an Ubuntu VM and it worked (It writes the file to your Desktop). Had to have the return statement due to the Callable syntax garbage. Although I'm working on the work around, I doubt I'll find a better implementation on my own due to the saves from using l and w for my for loops. I'd say half a second for java isn't too bad. My original implementation opened directly to chrome using

 (System.getProperty("os.name").toLowerCase().contains("win")) { try { Process
 * p = Runtime.getRuntime() .exec(new String[] { "cmd", "/c", "start chrome " +
 * f }); p.waitFor(); } catch (Exception e) { } } else if
 * (System.getProperty("os.name").toLowerCase().contains("ix")) { try { Process
 * p = Runtime.getRuntime().exec(new String[] { "google-chrome" + f }); } catch

But I believe it's still validated as it can still be opened by chrome, it just automatically opens to your default png viewer (version not tested on Unix based machines).

I'm aware of the byte saves possible but mainly have omitted them to qualify for bonuses. If requested I can upload shorter, platform specific examples. Thank you.

Edit

Removed Unnecessary Try Catch block and ill formatted return statement to reduce ~30 bytes.
Removed BufferedImage.TYPE_INT_RGB because it's literally just 1.

  • Looking back on this I don't think I need a try catch block as the main method has to throw an Exception for a callable lambda to work... – jfh Dec 8 '17 at 13:47

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.