Fractals/kallesfraktaler

From Wikibooks, open books for an open world
Jump to navigation Jump to search

install[edit]

doc[edit]

files[edit]

jpg[edit]

kfc[edit]

kfb[edit]

These filea sre created:

  • when saving the jpg files, there is also a kfb file created for each image
  • save a map

Description:

  • "KFB files store raw uncompressed (ie huge but high quality) iteration data (the results of the fractal calculations before colouring is applied)." Claude at FF, for example raw float32 DE images (scaled to pixel spacing)
  • "the KFB files are images used as maps to store iteration data. No location, palette, etc" youhn


Claude on FF: [1]


They are strings found inside .kfb files (the first 3 bytes) to distinguish different versions of the data format stored in the file.

"KFB" is bNewFormat 0, vertical lines of int32 iteration plane followed by float32 smooth colouring plane.
"KFC" is bNewFormat 1, vertical lines of float32 combined data (int32 iteration + float32 smooth)
"KFD" is bNewFormat 2, horizontal lines of float32 combined data (int32 iteration + float32 smooth)

As far as I can tell, only "KFB" is actually saved by current versions of Kalles Fraktaler.

"KFB" is also the only format that preserves smooth colouring at high iteration counts, because single precision float32 can only represent integers after 2^24 = 16M, can only represent even integers after 2^25 = 33M, etc, with gradual degradation before that.




// from fractal_sftp.cpp  Kalles Fraktaler 2 © 2014-2015 Karl Runmo
void CFraktalSFT::SaveMapB(char *szFile)
{
	if (!m_nPixels)
		return;
	DWORD dw;
	HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
	int x;
	WriteFile(hFile, "KFB", 3, &dw, NULL);
	WriteFile(hFile, &m_nX, sizeof(m_nX), &dw, NULL);
	WriteFile(hFile, &m_nY, sizeof(m_nY), &dw, NULL);
	for (x = 0; x<m_nX; x++)
		WriteFile(hFile, m_nPixels[x], m_nY*sizeof(int), &dw, NULL);
	int div = m_nIterDiv;
	WriteFile(hFile, &div, sizeof(m_nParts), &dw, NULL);
	WriteFile(hFile, &m_nParts, sizeof(m_nParts), &dw, NULL);
	WriteFile(hFile, m_cKeys, sizeof(COLOR14)*m_nParts, &dw, NULL);
	WriteFile(hFile, &m_nMaxIter, sizeof(int), &dw, NULL);
	for (x = 0; x<m_nX; x++)
		WriteFile(hFile, m_nTrans[x], m_nY*sizeof(float), &dw, NULL);
	CloseHandle(hFile);
}

Here is the octave/matlab code by Gerrit:[2]

function [width,height,counts,trans,maxiter,parts,keys] = readKFB(fn)

% counts are iterations
% trans is the correction to smooth iteration count based on escape time
% (see wiki) 
% parts is number of colors, keys are the colors.
% to make a colormap(cmap):
% > cmap = reshape(keys,3,parts)'/255.;
% > cmap = flipud(fliplr(cmap));

info = dir(fn);
fid = fopen(fn,'r');
d = fread(fid, [1, info.bytes], '*uint8');
fclose(fid);
%d(1:3) == 'KFB' test skipped
k = 4;
nBytes = 4;
width = typecast(uint8(d(k:k+nBytes-1)),'uint32');
width = double(width);
k = k + nBytes;
height = typecast(uint8(d(k:k+nBytes-1)),'uint32');
height = double(height);
k = k + nBytes;
nCounts = width*height; %32 bit ints
nBytes = 4 * nCounts;
counts = typecast(uint8(d(k:k+nBytes-1)),'uint32');
counts = reshape(counts,height,width);
counts = single(counts);
k = k + nBytes;
nBytes = 4;
iterdiv = typecast(uint8(d(k:k+nBytes-1)),'uint32');
k = k + nBytes;
parts = typecast(uint8(d(k:k+nBytes-1)),'uint32');
parts = double(parts);
k = k + nBytes;
nBytes = parts * 3;
% r,g,b,... parts triples
keys = typecast(uint8(d(k:k+nBytes-1)),'uint8');
keys = double(keys);
k = k + nBytes;
nBytes = 4;
maxiter = typecast(uint8(d(k:k+nBytes-1)),'uint32');
maxiter = double(maxiter);
k = k + nBytes;
nBytes = 4 * nCounts;
trans = typecast(uint8(d(k:k+nBytes-1)),'single');
trans = reshape(trans,height,width);



File header in hexadecimal editor :

KFB....h.

kfd[edit]

kfr[edit]

Examples:

kfp[edit]

kfp = Kalles Fraktaler palette files

On the file naming convention used a file name such as
"p512bcgwmryk.kfp" is a 512 colour palette a 3bit colour cube sorted into Blue, Cyan, Green, White, Magenta, Red and yellow groups, then sub sorted within these groups to get a smooth changes in colour.
Most files will have a striping ending "p512bcgwmrykof8.kfp" shifts each 2nd colour 8 places.
"p512bcgwmrykpm4816"  is a more complex striping, the 2nd colour is shifted 4 paces, the 4th 8 places, the 6th 4 places and the 8th 16 places and so on.
"p512X2bcgwyrmkof32" duplicates the 512 colour palette into light and dark halves.
"p1024bmwmbcgyrk" the "bm" stands for bit mix a more satisfactory way of sampling the 8 bit colour cube into 1024 colours.
There are a few other oddball palettes, "LenaSoderburg.kfp" is a palette that is a 32x32 low resolution version of the famous "Lena" picture use in early image processing development.

Jeremy Thomson


png[edit]

Program can open and sve pang with comments:


/*
Kalles Fraktaler 2
Copyright (C) 2013-2017 Karl Runmo
Copyright (C) 2017-2018 Claude Heiland-Allen

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <string>
#include <png.h>
#include <zlib.h>

#include "png.h"

static void kf_png_error_handler(png_structp png, png_const_charp msg)
{
	// FIXME make this display in the GUI or something
	fprintf(stderr, "PNG ERROR: %s\n", msg);
	longjmp(*static_cast<jmp_buf *>(png_get_error_ptr(png)), 1);
}

static void kf_png_warning_handler(png_structp png, png_const_charp msg)
{
	(void) png;
	// FIXME make this display in the GUI or something
	fprintf(stderr, "PNG WARNING: %s\n", msg);
}

static bool skip_png_image(png_structp png, png_infop info);

extern int SavePNG(const std::string &szFileName, char *Data, int nHeight, int nWidth, int nColors, const std::string &comment)
{
	jmp_buf jmpbuf;
	if (nColors != 3)
		return 0;
	FILE *file = fopen(szFileName.c_str(), "wb");
	if (! file)
		return 0;
	png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, &jmpbuf, kf_png_error_handler, kf_png_warning_handler);
	if (! png)
		return 0;
	png_infop info = png_create_info_struct(png);
	if (! info)
	{
		png_destroy_write_struct(&png, 0);
		fclose(file);
		return 0;
	}
	if (setjmp(jmpbuf))
	{
		png_destroy_write_struct(&png, &info);
		fclose(file);
		return 0;
	}
	png_init_io(png, file);
	png_set_compression_level(png, Z_BEST_COMPRESSION);
	png_set_IHDR(png, info, nWidth, nHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_time mtime;
	png_convert_from_time_t(&mtime, time(0));
	png_set_tIME(png, info, &mtime);
	png_text text;
	text.compression = PNG_TEXT_COMPRESSION_NONE;
	const std::string &key = "Comment";
	text.key = const_cast<char *>(key.c_str());
	text.text = const_cast<char *>(comment.c_str());
	png_set_text(png, info, &text, 1);
	png_write_info(png, info);
	png_bytepp row = new png_bytep[nHeight];
	for (int y = 0; y < nHeight; ++y)
		row[y] = (png_bytep)(Data + nWidth * nColors * y);
	png_write_image(png, row);
	png_write_end(png, 0);
	delete [] row;
	fclose(file);
	return 1;
}

extern std::string ReadPNGComment(const std::string &filename)
{
	jmp_buf jmpbuf;
	FILE *file = fopen(filename.c_str(), "rb");
	if (! file)
		return "";
	png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, &jmpbuf, kf_png_error_handler, kf_png_warning_handler);
	if (! png)
	{
		fclose(file);
		return "";
	}
	png_infop info = png_create_info_struct(png);
	if (! info)
	{
		png_destroy_read_struct(&png, 0, 0);
		fclose(file);
		return "";
	}
	png_infop enfo = png_create_info_struct(png);
	if (! enfo)
	{
		png_destroy_read_struct(&png, &info, 0);
		fclose(file);
		return "";
	}
	if (setjmp(jmpbuf))
	{
		png_destroy_read_struct(&png, &info, 0);
		fclose(file);
		return "";
	}
	png_init_io(png, file);
	png_read_info(png, info);
	png_textp text;
	int count = 0;
	std::string comment = "";
	if (png_get_text(png, info, &text, &count) > 0)
		for (int t = 0; t < count; t++)
			// we save as capitalized, but processing with ImageMagick downcases
			if (0 == stricmp("Comment", text[t].key))
				comment = text[t].text; // copy
	if (comment == "")
	{
		if (skip_png_image(png, info))
		{
			png_read_end(png, enfo);
			png_textp etext;
			int ecount = 0;
			if (png_get_text(png, enfo, &etext, &ecount) > 0)
				for (int t = 0; t < ecount; t++)
					// we save as capitalized, but processing with ImageMagick downcases
					if (0 == stricmp("Comment", etext[t].key))
						comment = etext[t].text; // copy
		}
	}
	png_destroy_read_struct(&png, &info, &enfo);
	fclose(file);
	return comment;
}

coloring methods[edit]

One can change it :

  • Main Menu / Actions/ Set Colors
  • keys: Ctrl+C


Available color methods are ( in main.cpp file line 256) :

  • Standard = Distance (Linear): Standard iteration band coloring
  • Square root: Iterations are squared before colors are appplied
  • Cubic root: Cube root is applied before colors
  • Logarithm: Logarithm is applied before colors = ColorMethod_Logarithm [3]: "ColorMethod_Logarithm is not DEM at all, it's escape time with non-linear transfer function."
  • Stretched: The palette is stretched over min-max iteration values
  • Distance: Distance Estimation : "ColorMethod_Distance* have some image processing (looking up iteration values of neighbouring pixels) to generate a pseudo-de colouring. It's not true DEM but looks pretty close sometimes."

Numbers describing methods ( variable m_nColorMethod) are changing between versions[4]


Code:

  • file fraktal_sft.cpp
  • variable m_nColorMethod
  • functions:
    • CFraktalSFT::SetColorMethod
    • void CFraktalSFT::SetColor
    • CFraktalSFT::OpenFile
    • CFraktalSFT::SaveFile


tools[edit]

./kfb-expmap n < x.txt > x.pgm    # exponential map (log polar) with pseudo-de colour ; x.txt lists kfb files one per line, in order ; n is number of kfb files listed in x.txt
./kfb-histogram d < a.kfb > a.pgm # histogram equalize (sort and search, O(N log N)) ; d is density >= 1.0, affects the brightness curve
./kfb-to-mmit < a.kfb > a.mmit  # convert to Mandel Machine iteration data format
./kfb-pseudo-de < a.kfb > a_pde.pgm   # pseudo distance estimate colouring
./kfb-rainbow < a.kfb > a.ppm   # rainbow based on slope direction, plus pseudo-de
./kfb-resize w h < x.kfb > x.kfb  # resize to new (w,h) using bi-cubic interpolation
./kfb-stretch < a.kfb > as.pgm    # simple iteration count stretching

Scripts included ('bash' shell and common linux utilities required):

kfbtoogv.sh s work tmp      # automatic movie maker with sound generation
                              s is desired movie length in seconds
                              work is absolute path to dir containing *.kfb
                              tmp is absolute path to dir for output
                              it checks for the less-common programs it needs

references[edit]

  1. fractalforums org: KF file-types
  2. fractalforums org : matlaboctave-code-for-kfb-reading
  3. fractalforums : distance-logarithm-test
  4. fractalforums : kalles-fraktaler/backwards-compatibility