Skip to content

Instantly share code, notes, and snippets.

@zanders3
Last active May 16, 2020 07:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zanders3/9a690443bc4b22340e00 to your computer and use it in GitHub Desktop.
Save zanders3/9a690443bc4b22340e00 to your computer and use it in GitHub Desktop.
A rainbow rendering of the mandelbrot set. This created by sorting every colour by Hue, then randomly shuffling each set of pixels that share the same iteration in the fractal via histogram generation. Posted on http://allrgb.com/rainbow-fractal.
// AllRGB.cpp
// Calculates an image containing every RGB color
// once and once only in a vague mandelbrot kind of shape.
// To use:
// gcc allrgb.cpp
// ./a.out > allrgb.ppm
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cstdlib>
const int iters = 256;
int mandelbrot(float x0, float y0)
{
x0 = (x0 * 2.0f) - 1.5f;
y0 = (y0 * 2.0f) - 1.0f;
float x = 0.0f, y = 0.0f;
int i = 0;
float pow16 = pow(2.0f, 16.0f);
while (x*x + y*y < pow16 && i<iters)
{
float xtemp = x*x - y*y + x0;
y = 2*x*y + y0;
x = xtemp;
i++;
}
return i;
}
const int histCount = iters;
int histogram[histCount+1];
int histogramInd[histCount+1];
const int size = 4096;
int image[size*size];
struct color
{
union
{
int col;
struct
{
char r;
char g;
char b;
} c;
} colors;
float hue;
};
color colormap[size*size];
int compareColor(const void* a, const void* b)
{
int ahue = ((color*)a)->hue;
int bhue = ((color*)b)->hue;
if (ahue < bhue)
return -1;
else if (ahue == bhue)
return 0;
else
return 1;
}
float rgb2hue(const color& in)
{
double min, max, delta;
float r = in.colors.c.r * 100.0f, g = in.colors.c.g * 100.0f, b = in.colors.c.b * 100.0f;
min = r < g ? r : g;
min = min < b ? min : b;
max = r > g ? r : g;
max = max > b ? max : b;
delta = max - min;
if( max <= 0.0 )
return 0.0f;
float outh;
if( r >= max )
outh = ( g - b ) / delta; // between yellow & magenta
else if( g >= max )
outh = 2.0 + ( b - r ) / delta; // between cyan & yellow
else
outh = 4.0 + ( r - g ) / delta; // between magenta & cyan
outh *= 60.0; // degrees
if( outh < 0.0 )
outh += 360.0;
return outh;
}
void makecolormap()
{
float sqrt3 = sqrt(3.0f);
//Generate uniform colormap
for (int i = 0; i<size*size; i++)
{
colormap[i].colors.col = i;
colormap[i].hue = -rgb2hue(colormap[i]);
}
//Sort by hue
qsort(colormap, size*size, sizeof(color), compareColor);
}
int main()
{
fprintf(stderr, "Make colormap\n");
makecolormap();
for (int i = 0; i<=histCount; i++)
{
histogram[i] = 0;
histogramInd[i] = 0;
}
fprintf(stderr, "Calculate mandelbrot\n");
printf("P6 %d %d 255 ", size, size);
int i = 0;
int highestC = 0;
for(int y=size;y--;)
for(int x=size;x--;)
{
int c = mandelbrot(x/(float)size, y/(float)size);
image[i++] = c;
if (c > highestC)
highestC = c;
histogram[c]++;
}
//Cumulative sum each histogram bucket
int sum = 0;
for (int i = 0; i<=histCount; i++)
{
int hVal = histogram[i];
histogram[i] = sum;
sum += hVal;
}
fprintf(stderr, "Total Colours: %d, Highest C: %d\n", sum, highestC);
fprintf(stderr, "Randomising buckets\n");
for (int i = 0; i<=histCount; i++)
{
int offset = histogram[i];
int nextOffset = (i==histCount) ? sum : histogram[i+1];
int delta = nextOffset - offset;
for (int j = offset; j<nextOffset; j++)
{
color tmp = colormap[j];
int other = offset + (rand() % delta);
colormap[j] = colormap[other];
colormap[other] = tmp;
}
}
fprintf(stderr, "Output image\n");
i = 0;
int highestCol = 0;
for(int y=size;y--;)
for (int x=size;x--;)
{
int mandelInd = image[i++];
int col = histogram[mandelInd] + histogramInd[mandelInd]++;
if (col > highestCol)
highestCol = col;
printf("%c%c%c", colormap[col].colors.c.r, colormap[col].colors.c.g, colormap[col].colors.c.b);
}
fprintf(stderr, "Highest Color Index: %d\n", highestCol);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment