Fractals/kallesfraktaler

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

Kalles Fractales

Images[edit]

See commons category: Created with Kalles Fraktaler

install[edit]


run[edit]

 wine ./kf.64.exe


Set the image size the same as window size ( in View)

doc[edit]

videos[edit]

variables[edit]

  • T: the number type, double or long double or floatexp (used when more range is needed)
  • Zr, Zi: the final escaped Z value
  • Jxa, Jxb, Jya, Jyb: the running derivative (for complex analytic formulas Jxa = Jyb and Jxb = - Jya, aka Cauchy-Riemann conditions) Jxa = Jyb = Re(dz/dc), Jya = -Jxb = Im(dz/dc)
  • s: the pixel spacing
  • TK: the rotation and skew matrix (if you don't rotate or skew then this should be the identity matrix)

status bar[edit]

  • D%pixels done with current reference
  • G%pixels guessed by neighboring interior
  • R% reference iterations vs maxiters
  • A% series approximation skipped vs maxiters

Menu[edit]

menu depends on the version of KF

File[edit]

  • File->Open is for KFR
  • File->Open Map is for KFB

Fraktal[edit]

View[edit]

Navigation[edit]

Advanced[edit]

?[edit]

Parameters[edit]

  • seed value:
    • for the fractal type = Z0
  • Fractal type



Dialog box Iterations:

  • "Maximum number of iterations";
  • "Minimum number of iteration in current view";
  • "Maximum number of iteration in current view";
  • "Iterations skipped by Series Approximation";
  • "Bailout value for iterations";
  • "Power of Mandelbrot function";
  • "Maximum of extra references for glitch correction";
  • "Checked for low tolerance of Series Approximation\nComplex images may need this to be checked to be rendered correctly\nThe render time may be faster if this checkbox is not checked";
  • "Terms for Series approximation is adjusted\nbased on the number of pixels to be rendered.";
  • "List of type of Mandelbrot based Fractals\nSome of them have additional Power options";
  • "Terms for Series approximation.\nMore terms usually yield more skipped iterations and faster rendering,\nhowever is more time consuming to be processed";
  • "Display number of calculations performed";
  • "Include real part when checking bailout.\nUncheck for variation";
  • "Include imaginary part when checking bailout.\nUncheck for variation";
  • "Real seed value (0 is standard)";
  • "Imaginary seed value (0 is standard)";


bailout value and type[edit]

p-norm with weights:[1]

  

all of { a b p R } are configurable, with a special case for p = infinity (using max)

Seed values for the fractal type[edit]

To change open dialog window using:

  • Menu/Actions/Iterations
  • Keys: Ctrl+I

Fractal type = m_nFractalType[edit]

One can change it in the Iterations menu

  • Menu/Fractal/Iterations
  • Ctrl+I

Types:

  • 0 = Mandelbrot ( standard setting)
  • 1 = Burning Ship
  • 2 = Buffalo
  • 3 = Celtic
  • 4 = Mandelbar
  • 5 = Mandelbar Celtic
  • 6 = Perpendicular Mandelbrot
  • 7 = Perpendicular Burning Ship
  • 8 = Perpendicular Celtic
  • 9 = Perpendicular Buffalo
  • 10 = Cubic Quasi Burning Ship
  • 11 = Cubic Partial BS Real
  • 12 = Cubic Partial BS Imag
  • 13 = Cubic Flying Squirrel (Buffalo Imag)
  • 14 = Cubic Quasi Perpendicular
  • 15 = 4th Burning Ship Partial Imag
  • 16 = 4th Burning Ship Partial Real
  • 17 = 4th Burning Ship Partial Real Mbar
  • 18 = 4th Celtic Burning Ship Partial Imag
  • 19 = 4th Celtic Burning Ship Partial Real
  • 20 = 4th Celtic Burning Ship Partial Real Mbar
  • 21 = 4th Buffalo Partial Imag
  • 22 = 4th Celtic Mbar
  • 23 = 4th False Quasi Perpendicular
  • 24 = 4th False Quasi Heart
  • 25 = 4th Celtic False Quasi Perpendicular 25
  • 26 = 4th Celtic False Quasi Heart 26
  • 27 = 5th Burning Ship Partial 27
  • 28 = 5th Burning Ship Partial Mbar 28
  • 29 = 5th Celtic Mbar 29
  • 30 = 5th Quasi Burning Ship (BS/Buffalo Hybrid) 30
  • 313 = 5th Quasi Perpendicular 31
  • 32 = 5th Quasi Heart 32
  • 33 = SimonBrot 4th 33
  • 34 = 4th Imag Quasi Perpendicular / Heart 34
  • 35 = 4th Real Quasi Perpendicular 35
  • 36 = 4th Real Quasi Heart 36
  • 37 = 4th Celtic Imag Quasi Perpendicular / Heart 37
  • 38 = 4th Celtic Real Quasi Perpendicular 38
  • 39 = 4th Celtic Real Quasi Heart 39
  • 40 = SimonBrot 6th 40
  • 41 = HPDZ Buffalo : Z = |Z0|^2 - |Z| + C
  • 42 = TheRedshiftRider 1: a*z^2+z^3+c"); // 42
  • 43 = TheRedshiftRider 2: a*z^2-z^3+c"); // 43
  • 44 = TheRedshiftRider 3: 2*z^2-z^3+c"); // 44
  • 45 = TheRedshiftRider 4: a*z^2+z^4+c"); // 45
  • 46 = TheRedshiftRider 5: a*z^2-z^4+c"); // 46
  • 47 = TheRedshiftRider 6: a*z^2+z^5+c"); // 47
  • 48 = TheRedshiftRider 7: a*z^2-z^5+c"); // 48
  • 49 = TheRedshiftRider 8: a*z^2+z^6+c"); // 49
  • 50 = TheRedshiftRider 9: a*z^2-z^6+c"); // 50
  • 51 = SimonBrot2 4th // 51

files[edit]

exr[edit]

EXR file channels:

  • raw iteration data = normalized iteration count[2]
    • N = integer iteration count ( uint32 )
    • NF = fractional iteration count, float in range [0.0 .. 1.0)
  • T = phase = the argument of the first Z value to escape, measured in turns
  • DE = directional Distance Estimation (when derivatives have been calculated)
  • RGB = colours (half float)
  • Metadata


The channel names are strings


normalized iteration count[edit]

uint32 N integer iteration count

0xFFFFFFFF is non-escaped before header metadata field int Iterations (or string Iterations, as it can exceed the range of int)

0x00000000 is uncalculated/glitch/no-data-available.

If actual iteration values can be zero or negative, add a bias constant to each count and store it in the header metadata field int IterationsBias (or string IterationsBias, it can exceed the range of int). The bias could be negative, this might allow you to store high iteration counts without necessarily needing two channels if the actual min/max range is small enough)

For images with biased iteration counts above 0xFFFFFFFE, split into two channels:

uint32 N0 least significant 32 bits

uint32 N1 most significant 32 bits

(0xFFFFFFFF, 0xFFFFFFFF) is interpreted as non-escaped

For future supercomputers, this can be extended with N2 etc…


The continuous iteration count (when escaped) is N+NF-IterationsBias. This is stored separately to avoid losing precision at high iteration counts

phase of first escaped Z value, measured in turns

float T in [0.0 .. 1.0)

It is desirable that this aligns with NF to give 2D exterior grid cell coordinates, KF versions before 2.15 align only with Linear smoothing.

DE[edit]

directional DE (when derivatives have been calculated)

float DEX, float DEY directional distance estimate in cartesian form, normalized such that distance to a neighbouring boundary pixel sqrt(DEX^2 + DEY^2) is approximately 1.0.

If some pixels have no directional DE the missing data can be written as (0.0, 0.0), but readers should also handle NaNs in this case. The vector points away from the fractal boundary.

jpg[edit]

JPEG is lossy

kfc[edit]

"KFC" is bNewFormat 1, vertical lines of float32 combined data (int32 iteration + float32 smooth)

kfb[edit]

The map file (.kfb) contains:

  • the calculated fractal data:
    • iteration counts
      • N (max iterations , integer)
      • NF ( iteration , smooth part = double)
    • sometimes distance estimates if you enabled derivative calculations)
  • It also contains some colouring information (but this is not complete)

It does NOT contain the coordinates.

These files are 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: [3]


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:[4]

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]

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
ColorOffset: 0
Rotate: 0
Ratio: 363.025211
Colors: 0,0,255,0,4,255,0,8,255,0,12,255,0,16,255,0,20,255,0,24,255,0,28,255,0,32,255,0,36,255,0,40,255,0,45,255,0,49,255,0,53,255,0,57,255,0,61,255,0,65,255,0,69,255,0,73,255,0,77,255,0,81,255,0,85,255,0,89,255,0,93,255,0,97,255,0,101,255,0,105,255,0,109,255,0,113,255,0,117,255,0,121,255,0,125,255,0,130,255,0,134,255,0,138,255,0,142,255,0,146,255,0,150,255,0,154,255,0,158,255,0,162,255,0,166,255,0,170,255,0,174,255,0,178,255,0,182,255,0,186,255,0,190,255,0,194,255,0,198,255,0,202,255,0,206,255,0,210,255,0,215,255,0,219,255,0,223,255,0,227,255,0,231,255,0,235,255,0,239,255,0,243,255,0,247,255,0,251,255,0,255,255,
Smooth: 0
MultiColor: 0
BlendMC: 0
MultiColors: 
Power: 2
FractalType: 0
Slopes: 0
SlopePower: 50
SlopeRatio: 50
SlopeAngle: 45
image: 1
real: 1
SeedR: 0
SeedI: 0
FactorAR: 1
FactorAI: 0


 grep -nR "kfp"
fraktal_sft/cmdline.cpp:280:"    -c, --load-palette  [FILE.kfp]  load palette file\n"
fraktal_sft/main_color.cpp:481:			if(BrowseFile(hWnd,FALSE,"Save palette","Palette\0*.kfp\0\0",szFile))
fraktal_sft/main_color.cpp:696:			if(BrowseFile(hWnd,TRUE,"Open palette","Palette\0*.kfp\0\0",szFile)){

kfr[edit]

  • text file
  • contain parametrs

The parameter file (.kfr) before loading the map file to be able to navigate further. You can rename .kfr to .kfp and load it in the colour dialog.


Re: -1.252075014867735555974940801848588674907763636282052371316271536003707048655691466436892204807423486911208873753204122
Im: -0.008791858755657632997049331233776536713263464347924936644487037690633902732242296004830894920786698063372255536046170 
Zoom: 2.9333318059216862E91 
Iterations: 31394 
IterDiv: 0.010000 
SmoothMethod: 0 
ColorMethod: 7 
Differences: 3 
ColorOffset: 0 
Rotate: 0.000000 
Ratio: 383.431953 
Colors: 195,192,201,41,59,47,31,230,221,54,211,5,239,241,216,219,206,62,238,205,241,9,21,23, 
InteriorColor: 0,0,0, 
Smooth: 1 
MultiColor: 0 
BlendMC: 0 
MultiColors: 
Power: 2 
FractalType: 0 
Slopes: 1 
SlopePower: 50 
SlopeRatio: 20 
SlopeAngle: 45 
imag: 1 
real: 1 
SeedR: -0.5 
SeedI: 0 
FactorAR: 1 
FactorAI: 0 
Period: 0 
ZoomSize: 2 
MaxReferences: 10000 
GlitchLowTolerance: 0 
ApproxLowTolerance: 0 
AutoApproxTerms: 1 
ApproxTerms: 63 
WindowWidth: 640 
WindowHeight: 360 
WindowTop: 318 
WindowLeft: 630 
WindowBottom: 445 
WindowRight: 660 
ImageWidth: 8000 
ImageHeight: 4500 
ThreadsPerCore: 1 
AnimateZoom: 1 
ArbitrarySize: 1 
ReuseReference: 0 
AutoSolveGlitches: 1 
Guessing: 1 
SolveGlitchNear: 0 
NoApprox: 0 
Mirror: 0 
LongDoubleAlways: 0 
FloatExpAlways: 0 
AutoIterations: 1 
ShowGlitches: 1 
NoReuseCenter: 1 
IsolatedGlitchNeighbourhood: 4 
JitterSeed: 0 
JitterShape: 0 
JitterScale: 1 
Derivatives: 0 
ShowCrossHair: 0 
UseNanoMB1: 0 
UseNanoMB2: 0 
OrderM: 16 
OrderN: 16 
InteriorChecking: 0
RadiusScale: 0.100000000000000006

Examples:

kfs[edit]

This file type is for settings (.kfs), useful for configuring command line rendering or saving presets.

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;
}

sampling[edit]

sampling code : https://code.mathr.co.uk/kalles-fraktaler-2/blob/d685883599f7ae795bd7667834b0d2a47c00c7ef:/fraktal_sft/fraktal_sft.cpp#l3314 lines 3314 through 3379 KF does it:

  • generates a hash of (i,j,seed) for each of dx,dy offset (seed is different for x and y)
  • uses that to jitter.

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, variable m_nColorMethod ) :

  • 0 = Standard = Distance (Linear): Standard iteration band coloring
  • 1 = Square root: Iterations are squared before colors are appplied
  • 2 = Cubic root: Cube root is applied before colors
  • 3 = Logarithm: Logarithm is applied before colors = ColorMethod_Logarithm [5]: "ColorMethod_Logarithm is not DEM at all, it's escape time with non-linear transfer function."
  • 4 = Stretched: The palette is stretched over min-max iteration values
  • 5 = 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."
  • 6 = DE+Standard




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


Code:

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


// fraktal_sft.h
enum ColorMethod
{
	ColorMethod_Standard = 0,
	ColorMethod_SquareRoot = 1,
	ColorMethod_CubicRoot = 2,
	ColorMethod_Logarithm = 3,
	ColorMethod_Stretched = 4,
	ColorMethod_DistanceLinear = 5,
	ColorMethod_DEPlusStandard = 6,
	ColorMethod_DistanceLog = 7,
	ColorMethod_DistanceSqrt = 8,
	ColorMethod_LogLog = 9,
	ColorMethod_ATan = 10,
	ColorMethod_FourthRoot = 11
};

enum Differences
{
	Differences_Traditional = 0,
	Differences_Forward3x3 = 1,
	Differences_Central3x3 = 2,
	Differences_Diagonal2x2 = 3,
	Differences_LeastSquares2x2 = 4,
	Differences_LeastSquares3x3 = 5,
	Differences_Laplacian3x3 = 6,
	Differences_Analytic = 7
};




//fraktal_sft.cpp
void CFraktalSFT::SetColor(int nIndex, int nIter, double offs, int x, int y)
{
	if (nIter<0 || (!g_bShowGlitches && offs==2))
		return;
	if (nIter == m_nMaxIter)
		m_lpBits[nIndex] = m_lpBits[nIndex + 1] = m_lpBits[nIndex + 2] = 0;
	{
		double iter = (double)nIter + (double)1 - offs; // m_nColorMethod = 0;

		if (m_nColorMethod == 1){
			iter = sqrt(iter);
		}
		else if (m_nColorMethod == 2){
			iter = pow(iter, (double)1 / (double)3);
		}
		else if (m_nColorMethod == 3){
			iter = log(iter);
		}
		else if (m_nColorMethod == 4){
			int nMin, nMax;
			GetIterations(nMin, nMax,NULL,NULL,TRUE);
			iter = (double)1024 * ((double)iter - (double)nMin) / ((double)nMax - (double)nMin);
		}
		else if (m_nColorMethod == 5 || m_nColorMethod == 6){
			double p1, p2, p3, p4;
			iter=0;
			if (x){
				p1 = (double)m_nPixels[x - 1][y] + (double)1 - m_nTrans[x - 1][y];
				p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			}
			else if (x<m_nX - 1){
				p1 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
				p2 = (double)m_nPixels[x + 1][y] + (double)1 - m_nTrans[x + 1][y];
			}
			else
				p1 = p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			double _abs_val;
			iter += _abs(p1 - p2)*1.414;

			if (x && y){
				p1 = (double)m_nPixels[x - 1][y - 1] + (double)1 - m_nTrans[x - 1][y - 1];
				p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			}
			else if (x<m_nX - 1 && y<m_nY - 1){
				p1 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
				p2 = (double)m_nPixels[x + 1][y + 1] + (double)1 - m_nTrans[x + 1][y + 1];
			}
			else
				p1 = p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			iter += _abs(p1 - p2);

			if (y){
				p1 = (double)m_nPixels[x][y - 1] + (double)1 - m_nTrans[x][y - 1];
				p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			}
			else if (y<m_nY - 1){
				p1 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
				p2 = (double)m_nPixels[x][y + 1] + (double)1 - m_nTrans[x][y + 1];
			}
			else
				p1 = p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			iter += _abs(p1 - p2)*1.414;

			if (y && x<m_nX-1){
				p1 = (double)m_nPixels[x + 1][y - 1] + (double)1 - m_nTrans[x + 1][y - 1];
				p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			}
			else if (x && y<m_nY - 1){
				p1 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
				p2 = (double)m_nPixels[x - 1][y + 1] + (double)1 - m_nTrans[x - 1][y + 1];
			}
			else
				p1 = p2 = (double)m_nPixels[x][y] + (double)1 - m_nTrans[x][y];
			iter += _abs(p1 - p2);
//			iter/=4;
//			iter*=iter;
			iter*=(double)m_nX / (double)640;
			iter=sqrt(iter);
			/*iter=log(iter);
			if(iter<0)
				iter=0;*/
			if(iter>1024)
				iter=1024;
			if(m_nColorMethod == 6 && iter>m_nIterDiv)
				iter = (double)nIter + (double)1 - offs;
		}
		if (m_nIterDiv != 1){
			iter /= m_nIterDiv;
		}
		if (m_nColorOffset)
			iter += m_nColorOffset;// = (nIter+m_nColorOffset)%1024;
		nIter = (int)iter;
		offs = 1 - (iter - (double)nIter);
		if (m_bITrans)
			offs = 1 - offs;
		if (m_bMW){
			double nH = 0, nS = 0, nB = 0;
			int nDR = 0, nDG = 0, nDB = 0;
			int i;
			for (i = 0; i<m_nMW; i++){
				double nPeriod;
				nPeriod = m_MW[i].nPeriod;
				double g;
				if (m_bTrans)
					g = sin((pi*iter) / nPeriod) / 2 + .5;
				else
					g = sin((pi*((int)iter)) / nPeriod) / 2 + .5;
				if (nPeriod<0)
					g = -(double)nPeriod / (double)100;
				if (m_MW[i].nType == 0){
					nH += g;
					nDR++;
				}
				if (m_MW[i].nType == 1){
					nS += g;
					nDG++;
				}
				if (m_MW[i].nType == 2){
					nB += g;
					nDB++;
				}
			}
			if (nDR)
				nH /= nDR;
			if (nDG)
				nS /= nDG;
			if (nDB)
				nB /= nDB;
			COLOR14 cPos;
			HSVToRGB(nH, nS, nB, cPos);

			m_lpBits[nIndex] = cPos.r;
			m_lpBits[nIndex + 1] = cPos.g;
			m_lpBits[nIndex + 2] = cPos.b;

			if (m_bBlend){
				int nR, nG, nB;
				if (m_bTrans && offs){
					double g1 = (1 - offs);
					int col = nIter % 1024;
					int ncol = (col + 1) % 1024;
					nR = m_cPos[col].r*offs + m_cPos[ncol].r*g1;
					nG = m_cPos[col].g*offs + m_cPos[ncol].g*g1;
					nB = m_cPos[col].b*offs + m_cPos[ncol].b*g1;
				}
				else{
					int col = nIter % 1024;
					nR = m_cPos[col].r;//+n;
					nG = m_cPos[col].g;//+n;
					nB = m_cPos[col].b;//+n;
				}
				m_lpBits[nIndex] = (m_lpBits[nIndex] + nR) / 2;
				m_lpBits[nIndex + 1] = (m_lpBits[nIndex + 1] + nG) / 2;
				m_lpBits[nIndex + 2] = (m_lpBits[nIndex + 2] + nB) / 2;
			}
		}
		else{
			if (m_bTrans && offs){
				double g1 = (1 - offs);
				int col = nIter % 1024;
				int ncol = (col + 1) % 1024;
				m_lpBits[nIndex] = m_cPos[col].r*offs + m_cPos[ncol].r*g1;
				m_lpBits[nIndex + 1] = m_cPos[col].g*offs + m_cPos[ncol].g*g1;
				m_lpBits[nIndex + 2] = m_cPos[col].b*offs + m_cPos[ncol].b*g1;
			}
			else{
				int col = nIter % 1024;
				m_lpBits[nIndex] = m_cPos[col].r;//+n;
				m_lpBits[nIndex + 1] = m_cPos[col].g;//+n;
				m_lpBits[nIndex + 2] = m_cPos[col].b;//+n;
			}
		}
	}

post-processing effects[edit]

slope[edit]

  "Slopes rendering is originally a screen-space post-processing effect, using differences between neighbouring pixels' smooth iteration counts.  
   More recently it can use directional distance estimate (normalized by pixel spacing) instead, which I think gerrit proved is equivalent in the   limit of infinitely fine pixel grid. 
   Relevant part of the source code: https://code.mathr.co.uk/kalles-fraktaler- 2/blob/c78c224a4a3ae7f10ed03aa3948f0cd6b740adcb:/fraktal_sft/fraktal_sft.cpp#l933 lines 933 to 998 " Claude


Variables:

  • m_bSlopes = FALSE; is boolean variable
  • m_nSlopePower = 50; is Slope shadow depth, integer
  • m_nSlopeRatio = 50; is Slope shadow strength, integer
  • m_nSlopeAngle = 45; is Slope shadow angle (0-360), integer


Show slopes

  • Enable slope encoding for 3D effect.
  • First value is the magnification of the slopes. The start value of 100 is suitable for the unzoomed view. Deep views requires a couple of magnitudes higher value.
  • The second value is the percentage with which the slope encoding is applied on the coloring. 100 is max, however flat areas will still have the palette color visible.


Algorithm:


 grep -nR "Slope"

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


KFMovieMaker[edit]

Videos:

Effects:


Blending

 grep -nR "Blend"

help[edit]

references[edit]

  1. fractalforums.org : additionnal-bailout-variations-on-kalles-fraktaler
  2. towards a common file format for 2D escape time iteration data
  3. fractalforums org: KF file-types
  4. fractalforums org : matlaboctave-code-for-kfb-reading
  5. fractalforums : distance-logarithm-test
  6. fractalforums : kalles-fraktaler/backwards-compatibility