Last active
May 16, 2020 07:07
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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