Fractals/MandelMachine
< Fractals
Mandel Machine Mandel Machine is a highly efficient Mandelbrot set explorer developed by Botond Kósa.[1]
Description
editcode
edit- the c++ part ( mm64.cpp ) is only to declare functions that are implemented in assembly language and the rest is in java.
- FractalCanvas.java is the most important file
Algorithms
editcolor
editFractalCanvas.java line 1996 and further:
if(itTransferFunction==1) ;
else if(itTransferFunction==2) it = Math.sqrt(it+1);
else if(itTransferFunction==3) it = Math.cbrt(it+1);
else if(itTransferFunction==4) it = Math.sqrt(Math.sqrt(it+1));
else if(itTransferFunction==5) it = Math.log(it+1);
else if(itTransferFunction==6) it = Math.log(Math.log(it+1)+1);
else if(itTransferFunction==7) it = Math.atan(it);
else it = -1;
Bump mapping
edit"bump mapping. It allows fake-3D visualization of subtle details previously hidden by the slow gradients in the palette.
Bump mapping is controlled by 3 parameters:
- Direction of lighting (in degrees): specifies the angle of the simulated lighting. Surfaces facing the light are highlighted, the ones blocked from lighting are darkened.
- Depth: controls how much the structures emerge from the background of slow gradients. Shallow depth causes a relief/emboss-like look. Greater depth values result in deeper valleys between structures (see the examples below).
- Strength: controls the amount of color shift caused by highlights and shadows.
The parameters are continuously adjustable to give instant feedback." [2]
Data format
edit"The Mandel Machine MMIT compressed iteration data file format:
- every datatype needs to be written in big endian notation.
- The following streamed through a Deflater (raw zlib format)" Dinkydau[3]
<int 4 bytes> Program Version <int 4 bytes> Canvas Width <int 4 bytes> Canvas Height <byte> Supersampling <double> Magnification <double> Rotation <int 4 bytes> Number of coordinate digits represented by long ints <long long array> array 2 times as long as the above int <int 4 bytes> Iteration limit <byte> Bytes per sample <double> minimum iteration count <double> granularity (equal to iterRange / (2^(bytes_per_sample*8) - 6), where iterRange is maxIt - minIt) <int array> row by row encoded samples (one int value per pixel)
KFB to MMIT converter
editSource code (written in C) that depends on kfb.h and kfb.c from kf-extras:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include "kfb.h"
void asserts(){
assert(sizeof(char)==1);
assert(sizeof(short)==2);
assert(sizeof(int)==4);
assert(sizeof(float)==4);
assert(sizeof(double)==8);
assert(sizeof(long)==4);
assert(sizeof(long long)==8);
return;
}
//data_size counts how large the mmit data is before zlib formatting
int data_size = 0;
const char one = 1;
union DoubleBytes {//to interpret double as char array and inverse byte order
double d;
char b[8];
};
union IntBytes {//to interpret int as char array
int i;
char b[4];
};
//functions to write data in big endian notation
int le_to_be_int(int input){
int num = input;
int b0,b1,b2,b3;
int res;
b0 = (num & 0x000000ff) << 24u;
b1 = (num & 0x0000ff00) << 8u;
b2 = (num & 0x00ff0000) >> 8u;
b3 = (num & 0xff000000) >> 24u;
res = b0 | b1 | b2 | b3;
return res;
}
void write_be_int(int input, FILE *outfile){
int res = le_to_be_int(input);
fwrite(&res, 4, 1, outfile);
data_size += 4;
}
void write_be_char(char input, FILE *outfile){
fwrite(&input, 1, 1, outfile);
data_size += 1;
}
void write_be_double(double input, FILE *outfile){
union DoubleBytes doublebytes;
doublebytes.d = input;
for(int i=0; i<4; i++){//reverse byte order in the double with char array interpretation
char temp = doublebytes.b[i];
doublebytes.b[i] = doublebytes.b[7-i];
doublebytes.b[7-i] = temp;
}
fwrite(&doublebytes.d, 8, 1, outfile);
data_size += 8;
}
int main(int argc, char **argv) {
//Check and load KFB file-----------------------------------------------------------------------------------
asserts();
if (argc < 2)
{
printf("This program converts a given KFB file to MMIT. Program version: 1.0
");
printf("Usage: "); printf(argv[0]); printf(" path_to_KFB [path_to_MMIT]
");
printf("Default for path_to_MMIT: MMIT-convert.mmit
");
return 1;
}
printf("Loading KFB file...
");
kfb *in = kfb_load(argv[1]);
if (! in) { printf("Loading KFB file failed.
"); return 1; }
int width = kfb_width(in);
int height = kfb_height(in);
//Writing all relevant mmit data to tempoutfile without zlib format--------------------------------------------
FILE *tempoutfile;
tempoutfile=fopen("tempoutfile", "wb");
//Get min and max iteration values present in KFB
double max_iters = 0;
double min_iters = 800100100;
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
double ij = kfb_get(in, j, i);
if(ij<min_iters) min_iters = ij;
if(ij>max_iters) max_iters = ij;
}
}
printf("Lowest iteration count: %lf
", min_iters);
printf("Highest iteration count: %lf
", max_iters);
//Parameters and settings
write_be_int(one, tempoutfile); //Program version
write_be_int(width, tempoutfile); //Canvas width
write_be_int(height, tempoutfile); //Canvas height
char supersampling = 0; write_be_char(supersampling, tempoutfile); //Supersampling (Always 0 for no supersampling)
double magnification = 512; write_be_double(magnification, tempoutfile); //Fake magnification default to arbitrary value;
double rotation = 256; write_be_double(rotation, tempoutfile); //Fake rotation default to arbitrary value;
int coord_digits = 11; write_be_int(coord_digits, tempoutfile); //Fake number of coordinate digits
int coords[44] = {-1, -1, -1, -1, -1768346623, 1239184185, -1450836726, -1610156628, -1160793342, 1122682978, 1750969101, 1468815386, -86691575, -319241320, -141699069, 731720154, -1302511102, 2092147506, 1358717447, -121412270, -362838523, 1906712988, 218032387, 147395776, 1528659973, -1874890155, 1817790991, 431114295, 1763611407, -389200653, 1363516937, 1455562147, 707986444, -847133922, 1130970381, 1568324293, 1567881485, -580086891, 1843248142, 1016614712, 1950251523, -75377623, -1674907892, 1914116203};
for(int i=0; i<44; i++){ //Fake array of coordinate digits
fwrite(&coords[i], 4, 1, tempoutfile);
data_size += 4;
}
int iteration_limit = 799999999; write_be_int(iteration_limit, tempoutfile); //default one below MM's 800M limit, seems safe
char bytesPerSample = 4; write_be_char(bytesPerSample, tempoutfile); //always 4 (the max) for simplicity
write_be_double(min_iters, tempoutfile); //minimum number of iterations in the data
double granularity = (799999999 - min_iters)/4294967290; write_be_double(granularity, tempoutfile); //(equal to iterRange / 4294967290, where iterRange is maxIt - minIt)
printf("Writing iteration data...
");
//Iteration data
double granRec = 0; if(granularity != 0) granRec = 1/granularity;
long long prevEncoded = 0;
char buffer[width*4];
union IntBytes intbytes;
for(int row=0; row<height; row++){
for(int col=0; col<width; col++){
double it = kfb_get(in, col, row);
long long encoded;
if (it == max_iters) encoded = 3; //Point inside minibrot
else encoded = round((it-min_iters)*granRec) + 5; //encodeSample
int diff = encoded - prevEncoded;
//writeSample:
intbytes.i = diff;
buffer[col+3*width] = intbytes.b[3];
buffer[col+2*width] = intbytes.b[2];
buffer[col+width] = intbytes.b[1];
buffer[col] = intbytes.b[0];
//
prevEncoded = encoded;
}
fwrite(&buffer, width*4, 1, tempoutfile);
data_size += width*4;
}
fclose(tempoutfile);
kfb_free(in);
printf ("Total data size: %d
", data_size);
//read uncompressed MMIT data into array a---------------------------------------------------------------------
char* a = malloc(data_size);
if(a==NULL){ printf ("Allocation of memory failed.
"); return 1;}
FILE *readbackfile;
readbackfile=fopen("tempoutfile", "rb");
fread(a, data_size, 1, readbackfile);
printf("Writing zlib format...
");
//Convert to zlib format and write to file---------------------------------------------------------------------
FILE *outfile;
if(argc > 2) outfile=fopen(argv[2], "wb");
else outfile=fopen("MMIT-convert.mmit", "wb");
int bytes_written = 0;
char header_more[] = {0, 86, 129, 169, 126}; // hardcoded zlib header for a block size of 33110;
while(bytes_written<data_size)
{
if(data_size - bytes_written > 33110)
{ //not the last block header
fwrite(&header_more, 5, 1, outfile);
for(int j=0; j<33110; j++)
{
fwrite(&a[bytes_written+j], 1, 1, outfile);
}
bytes_written += 33110;
}
else
{ //the last block header
short to_go = data_size - bytes_written;
short complement = 65535 - to_go;
fwrite(&one, 1, 1, outfile);
fwrite(&to_go, 2, 1, outfile);
fwrite(&complement, 2, 1, outfile);
for(int j=0; j<to_go; j++)
{
fwrite(&a[bytes_written+j], 1, 1, outfile);
}
bytes_written += to_go;
}
}
//-----------------------------------------------------------------------------------
fclose(readbackfile);
if(remove("tempoutfile") != 0) printf("Deleting the temporary file failed.");
printf ("Done");
return 0;
}