Title: KFB to MMIT converter
Post by: Dinkydau on February 02, 2017, 05:26:19 PM
I made a program to convert KFB maps from Kalles Fraktaler to the Mandel Machine MMIT format that can be loaded in Mandel Machine. My motivation was to use Mandel Machine to save renders as PNG (Kalles Fraktaler only saves as JPEG) and to use the coloring methods available in Mandel Machine. KFB files from fractal types other than the Mandelbrot set (burning ship and others) also work but of course you can't continue zooming in Mandel Machine. Download it here: https://mega.nz/#!M40BBQLA!vAeotI2-0_kaWBMoDqyGs_wDMTIAGe1tn0yqBt_CIqU (https://mega.nz/#!M40BBQLA!vAeotI2-0_kaWBMoDqyGs_wDMTIAGe1tn0yqBt_CIqU) Information: It's a commandline program. The MMIT and KFB file formats only have iteration data in common which has consequences for the other relevant data. If you want to load the gradient in Mandel Machine, save both a KFB and KFR file. Mandel Machine can read the KFR file and load the gradient from there. Because KFB doesn't have location information, I designed the program to write some arbitrary location information to the MMIT file. Otherwise Mandel Machine doesn't understand the file. If you want the correct location information (for example to continue zooming) you will also need to load the KFR file or just copy and paste it from Kalles Fraktaler, but make sure to deselect location information when you load the MMIT. The MMIT file format was designed to allow for efficient storage of iteration data. My program generates very inefficient MMIT files because I'm too lazy to figure out how to do zlib compression and use a smaller datatype for the iteration counts when possible. This program makes use of source code from Claude's kf-extras (http://www.fractalforums.com/kalles-fraktaler/kf-extras-for-manipulating-output-from-kalles-fraktaler-2/) to read KFB files and extract iteration counts from them. Claude also helped me to find the relevant source code in Mandel Machine. Thanks for the help. If you find a location that causes problems please let me know. I will try to improve the program if I can. (I'm not an experienced programmer.) Source 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; }
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):
<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)
Title: Re: KFB to MMIT converter
Post by: Adam Majewski on February 03, 2017, 04:35:21 PM
Thx. What is the licence of your program ?
Title: Re: KFB to MMIT converter
Post by: Dinkydau on February 04, 2017, 12:28:26 AM
There is no license. Please don't sell it for money, claim it as your own creation etc. You can use it and make changes to it as you wish. When appropriate, giving credit is appreciated (if you publish an edited version for example). The same thing goes for my images and videos. I just hope that everyone who uses this is reasonable and honest.
Title: Re: KFB to MMIT converter
Post by: lycium on February 04, 2017, 03:34:35 AM
Kalles Fraktaler only saves as JPEG
Whaaaaat... that's just unbelievable. Especially in this day of public domain single-header PNG writer libraries: https://github.com/nothings/stb/blob/master/stb_image_write.h
Title: Re: KFB to MMIT converter
Post by: Adam Majewski on February 04, 2017, 12:01:02 PM
There is no license. Please don't sell it for money, claim it as your own creation etc. You can use it and make changes to it as you wish. When appropriate, giving credit is appreciated (if you publish an edited version for example). The same thing goes for my images and videos. I just hope that everyone who uses this is reasonable and honest.
I have asked because kf-extras has : "kf-extras -- extras for manipulating output from Kalles Fraktaler 2 (C) 2014 Claude Heiland-Allen, partially based on work by Karl Runmo License: attribution, with any modified source made available (no warranty)" Can I put you code here ? https://en.wikibooks.org/wiki/Fractals/MandelMachine#data_format
Title: Re: KFB to MMIT converter
Post by: Kalles Fraktaler on February 04, 2017, 01:46:36 PM
I think it would be cool to be able to do the other way, from MMIT to KFB or MMY. But I cannot run MM anyway because java is blocked on my machine :sad1:
Title: Re: KFB to MMIT converter
Post by: Dinkydau on February 05, 2017, 08:06:08 PM
I have asked because kf-extras has : "kf-extras -- extras for manipulating output from Kalles Fraktaler 2 (C) 2014 Claude Heiland-Allen, partially based on work by Karl Runmo License: attribution, with any modified source made available (no warranty)"
Can I put you code here ?
https://en.wikibooks.org/wiki/Fractals/MandelMachine#data_format That's okay but if I make changes the updated version will be in this thread. Let me make some changes to the MMIT format specification by the way. Outside of the context of this program bytes per sample doesn't have to be always 4. I think it would be cool to be able to do the other way, from MMIT to KFB or MMY. But I cannot run MM anyway because java is blocked on my machine :sad1:
How can java be "blocked"? I assume you have full control over your machine.
|