Generate a 1920 x 1080 graphic with 2,073,600 unique colours
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 popularity-contest
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 asimage/bmp
. The lastest versions of FireFox and IE are also able to fix the broken header. - The barewords
BM
,I5S2
, andCS
will generate aNOTICE
error. To prevent corruption of the image, error reporting inphp.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.
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):
(The raw output image is rather large (5.6 MB))
Here's a close-up of the top left corner (scaled up 400%):
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;
}
C++, 750 bytes
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.