跳轉到內容

分形/kallesfraktaler

來自華夏公益教科書,開放的書籍,開放的世界

Kalles Fraktaler

參見 公共領域分類:用 Kalles Fraktaler 建立

啟動

wine ./kf.x86_64.exe 



將影像大小設定為與視窗大小相同(在檢視中)


只需儲存您的設定 KFS(如果您想要 640x360 之外的尺寸),位置 KFR(如果您想要未縮放的 M 集之外的任何內容),調色盤 KFP(可選,覆蓋來自 KFR 的內容),然後呼叫 KF,例如

/path/to/kf.exe -s my.kfs -l my.kfr -c my.kfp -x my.exr

然後您就可以透過 OpenEXR(C++)或其他庫在您的程式中載入 EXR。

對於(重新)為包含原始迭代資料的現有 EXR 檔案著色,請嘗試

/path/to/kf.exe -s old.exr -l old.exr -o old.exr -c new-palette.kfp  -x new.exr

參見 KF 的手冊(接近末尾)以獲取 EXR 通道文件,對於處理來自 KF 的 EXR 的第三方軟體,請檢視 zoomasm。

也支援另存為其他格式:檢視 kf.exe --help 以獲取詳細資訊。


製作影片的步驟

 mkdir ~/work
cd ~/work
wine32 ~/windows/fraktal_sft.exe
# render zoom out sequence with kalles fraktaler, saving to ~/work
for i in *.kfb ; do ~/code/maximus_kf-extras/pseudo-de < ${i} | pgmtoppm white > ${i%kfb}ppm done
# count number of kfb files, (ls *.kfb | tail -n 1) gives a hint, I had 311
ls *.kfb | ~/code/maximus_kf-extras/expmap 311 > expmap.pgm
ghc -e "100 / sqrt ( 565 * 19820 / (120 * 8000) )"
# or your favourite calculator program if you don't have ghc
# prints 29.27922435677391
# where 565 * 19820 is the size of the expmap
# 8000 is desired sample rate
# 120 is desired movie length in seconds
gimp expmap.pgm
# downscale by 29.27922435677391% (output from ghci)
# flip vertically
# make sure it's greyscale with no alpha
# save as expmap-downscaled.png
# gimp saves comments in its netpbm writers, my bad code doesn't handle it
pngtopnm < expmap-downscaled.png > expmap-downscaled.pgm
audacity
# import raw expmap-downscaled.pgm as raw unsigned 8bit PCM mono 8000Hz
# set project sample rate to 48000Hz
# select the track, mix and render
# select the track, apply filter DC Offset Removal (maybe needs a plugin)
# select the track, select amplify and apply to normalize the volume
# duplicate the track twice
# for each of the duplicates in turn, select it and apply a reverb (GVerb plugin)
# use slightly different reverb settings for each track (for stereo effect)
# normalize the duplicates by select track, select amplify, apply
# make one duplicate a left channel and the other a right channel
# set the levels of each track to -3dB
# select all tracks, mix and render
# normalize volume if needed
# select track, export as stereo wav 16bit PCM to expmap.wav
# note down the length (my test gave 1m56s)
ghc -e "1 * 60 + 56"
# to get the audio length in seconds (116)
# check the size of the kfb files (here I used 640 by 360)
# remember we have 311 kfb files
ls 00*.ppm | tac | xargs cat | ~/code/maximus_book/code/zoom 640 360 311 116 |
  avconv -f yuv4mpegpipe -i - -i expmap.wav -acodec vorbis -ab 192k -vb 2M out.ogv
# finally!
mplayer out.ogv
  • 在 Kalle's Fraktaler 中,影像每半秒鐘更新一次

影像大小

[編輯 | 編輯原始碼]

不考慮影像大小(畫素加上原始迭代資料):[1]

對於 KF 2.15.2.2

  • 如果使用雙精度:每個迭代 24 位元組(到縮放深度 e300,或對於 Mandelbrot 冪 2 僅縮放雙精度到 e600)
  • 如果使用長雙精度:在 64 位上每個迭代 40 位元組,在 32 位上每個迭代 32 位元組(到縮放深度 e4900,或對於 Mandelbrot 冪 2 僅縮放長雙精度到 e9800)
  • 如果使用 floatexp:每個迭代 40 位元組(“無限”縮放)

對於 KF 2.15.3(正在開發中,大部分工作完成,未釋出)

  • 如果使用雙精度:每個迭代 24 位元組(到縮放 e300)
  • 如果使用縮放的雙精度:每個迭代 24 位元組,加上每個迭代 48 位元組,接近於 0(“無限”縮放)
  • 如果使用長雙精度:在 64 位上每個迭代 48 位元組;在 32 位上每個迭代可能是 36 位元組(到縮放 e4900)
  • 如果使用 floatexp:每個迭代 48 位元組(“無限”縮放)

對於 KF 2.15.3(可能,需要測試在實現之後是否真的有效,正在開發中,尚未釋出,更不用說完成了)

  • 如果使用單精度浮點數:每個迭代 12 位元組(最多縮放深度 1e38)
  • 如果使用單精度縮放浮點數:每個迭代 12 位元組,加上每個迭代 24 位元組,接近於 0(“無限”縮放)
  • 如果使用單精度 floatexp:每個迭代 24 位元組(“無限”縮放)

KF 沒有實現記憶體最佳化以僅在級數逼近後儲存參考,它儲存了整個軌道。但是,如果使用 OpenCL,它確實只將級數逼近後的部分上傳到裝置。

請注意,32 位程式的地址空間限制為 4GB,這對於 10 億次迭代來說是不夠的,每次迭代需要 4 個位元組;這些數字僅供完整性參考。

要將 10 億次迭代(10 億)的 N 位元組/畫素進行轉換,很簡單,就是 N 吉位元組。

  • T:數字型別,雙精度或長雙精度或 floatexp(在需要更多範圍時使用)
  • Zr,Zi:最終逃逸的 Z 值
  • Jxa,Jxb,Jya,Jyb:執行導數(對於復解析公式,Jxa = Jyb 和 Jxb = - Jya,即柯西-黎曼條件)Jxa = Jyb = Re(dz/dc),Jya = -Jxb = Im(dz/dc)
  • s:畫素間距
  • TK:旋轉和傾斜矩陣(如果您不旋轉或傾斜,則這應該是單位矩陣)
  • 設定縮放級別,CTRL-左鍵單擊放大,右鍵單擊縮小。

狀態列

[編輯 | 編輯原始碼]
  • D% 畫素已使用當前參考完成
  • G% 畫素透過相鄰內部畫素猜測
  • R% 參考迭代次數與最大迭代次數之比
  • A% 級數逼近跳過的迭代次數與最大迭代次數之比

選單取決於 KF 的版本

  • 檔案->開啟 用於 KFR
  • 檔案->開啟地圖 用於 KFB

指數對映

[編輯 | 編輯原始碼]

應用 指數對映座標變換。為了獲得最佳(更保形)的結果,請使用寬縱橫比(9:1 很好,視窗大小 1152x128 或 1536x170)。

您可以儲存指數對映縮小序列(將縮放大小設定為 2),並將它們組合成一個使用 zoomasm 縮放影片組裝器的電影。這比儲存平面關鍵幀要高效得多。

  • 種子值
    • 對於分形型別 = Z0
  • 分形型別



對話方塊 迭代次數

  • "最大迭代次數"
  • "當前檢視中的最小迭代次數"
  • "當前檢視中的最大迭代次數"
  • "級數逼近跳過的迭代次數"
  • "迭代次數的逃逸值"
  • "曼德勃羅函式的冪"
  • "用於故障校正的額外參考的最大值"
  • "已檢查級數逼近的低容差\n複數影像可能需要選中此選項才能正確渲染\n如果未選中此複選框,則渲染時間可能會更快"
  • "級數逼近的項根據要渲染的畫素數量進行調整."
  • "基於曼德勃羅的分形型別的列表\n其中一些具有額外的冪選項"
  • "級數逼近的項.\n更多項通常會導致更多跳過的迭代次數和更快的渲染,\n但處理起來更耗時"
  • "顯示執行的計算次數"
  • "在檢查逃逸值時包含實部.\n取消選中以進行變體"
  • "在檢查逃逸值時包含虛部.\n取消選中以進行變體"
  • "實數種子值(0 為標準)"
  • "虛數種子值(0 為標準)"


逃逸值和型別

[編輯 | 編輯原始碼]

p-範數,帶權重:[2]


所有 { a b p R } 都可配置,p = 無窮大(使用 max)為特例

分形型別的種子值

[編輯 | 編輯原始碼]

要使用以下方法更改開啟對話方塊視窗

  • 選單/操作/迭代次數
  • 鍵:Ctrl+I

分形型別 = m_nFractalType

[編輯 | 編輯原始碼]

可以在迭代次數選單中更改它

  • 選單/分形/迭代次數
  • Ctrl+I

型別

  • 0 = 曼德勃羅集(標準設定)
  • 1 = 燃燒之船
  • 2 = 水牛
  • 3 = 凱爾特
  • 4 = 曼德勃羅集共軛
  • 5 = 曼德勃羅集共軛凱爾特
  • 6 = 垂直曼德勃羅集
  • 7 = 垂直燃燒之船
  • 8 = 垂直凱爾特
  • 9 = 垂直水牛
  • 10 = 立方擬燃燒之船
  • 11 = 立方部分 BS 實部
  • 12 = 立方部分 BS 虛部
  • 13 = 立方飛翔松鼠(水牛虛部)
  • 14 = 立方擬垂直
  • 15 = 第四次燃燒之船部分虛部
  • 16 = 第四次燃燒之船部分實部
  • 17 = 第四次燃燒之船部分實部共軛
  • 18 = 第四次凱爾特燃燒之船部分虛部
  • 19 = 第四次凱爾特燃燒之船部分實部
  • 20 = 第四次凱爾特燃燒之船部分實部共軛
  • 21 = 第四次水牛部分虛部
  • 22 = 第四次凱爾特共軛
  • 23 = 第四次偽擬垂直
  • 24 = 第四次偽擬心臟
  • 25 = 第四次凱爾特偽擬垂直 25
  • 26 = 第四次凱爾特偽擬心臟 26
  • 27 = 第五次燃燒之船部分 27
  • 28 = 第五次燃燒之船部分共軛 28
  • 29 = 第五次凱爾特共軛 29
  • 30 = 第五次擬燃燒之船(燃燒之船/水牛混合體) 30
  • 31 = 第五次擬垂直 31
  • 32 = 第五次擬心臟 32
  • 33 = SimonBrot 第四次 33
  • 34 = 第四次虛部擬垂直/心臟 34
  • 35 = 第四次實部擬垂直 35
  • 36 = 第四次實部擬心臟 36
  • 37 = 第四次凱爾特虛部擬垂直/心臟 37
  • 38 = 第四次凱爾特實部擬垂直 38
  • 39 = 第四次凱爾特實部擬心臟 39
  • 40 = SimonBrot 第六次 40
  • 41 = HPDZ 水牛 : 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 第四次 // 51
  • KF 可以將原始迭代資料匯出為 EXR(和過時的 KFB)格式,因此您可以使用其他軟體對其進行著色
  • 包含迭代資料的對映檔案 (*.kfb, *.exr)
  • 包含當前位置和設定的引數檔案 (*.kfr)(也包含在影像元資料中)
  • fraktal_sft.exe(舊版 kf)

EXR 檔案通道

  • 原始迭代資料 = 歸一化的迭代次數[3]
    • N = 整數迭代次數(uint32)
    • NF = 小數迭代次數,範圍在 [0.0 .. 1.0) 內的浮點數
  • T = 相位 = 第一個逃逸的 Z 值的自變數,以轉數計量
  • Jxa, Jxb, Jya, Jyb:執行導數
    • 對於複分析公式,Jxa = Jyb 且 Jxb = - Jya,即柯西-黎曼條件
    • Jxa = Jyb = Re(dz/dc),Jya = -Jxb = Im(dz/dc)
  • DE = 方向距離估計(在計算出導數後)
  • RGB = 顏色(半浮點數):線性光照中的一半 R、一半 G、一半 B
  • 元資料


通道名稱是字串


pnmcat -tb *.exr > *.ppm

歸一化迭代次數

[編輯 | 編輯原始碼]

uint32 N 整數迭代次數

0xFFFFFFFF 在標題元資料欄位 int Iterations(或字串 Iterations,因為它可以超過 int 的範圍)之前未逃逸

0x00000000 未計算/故障/無可用資料。

如果實際迭代值可以為零或負數,則向每個計數新增一個偏差常數,並將其儲存在標題元資料欄位 int IterationsBias(或字串 IterationsBias 中,它可以超過 int 的範圍)。偏差可以為負數,這可能允許你儲存高迭代次數,而無需在實際最小/最大範圍足夠小的情況下,特別需要兩個通道。

對於迭代次數偏差高於 0xFFFFFFFE 的影像,將其拆分為兩個通道

uint32 N0 最低有效 32 位

uint32 N1 最高有效 32 位

(0xFFFFFFFF, 0xFFFFFFFF) 被解釋為未逃逸

對於未來的超級計算機,這可以透過 N2 等進行擴充套件…


  • 連續迭代次數(在逃逸時)是 N+NF-IterationsBias。為了避免在高迭代次數時丟失精度,它被單獨儲存
  • 希望這與 NF 對齊以給出二維外部網格單元座標,2.15 之前的 KF 版本僅與線性平滑對齊。
  • genType NF 分數迭代次數,預計在 [0.0 .. 1.0) 之間,對於 float32 和 half(float16)來說,以及透過除以 0x100000000 對 uint32 進行歸一化的整個範圍。連續迭代次數(在逃逸時)是 N+NF-IterationsBias。為了避免在高迭代次數時丟失精度,它被單獨儲存


  • 第一個逃逸 Z 值的相位,以轉數計量。
  • 基於最終迭代的自變數角度的相位通道(EXR 中的 T)
  • float T 在 [0.0 .. 1.0) 之間

方向 DE(在計算出導數後)

float DEX,float DEY 方向距離估計,以笛卡爾形式歸一化,使得相鄰邊界畫素的距離 sqrt(DEX^2 + DEY^2) 大致為 1.0。

如果一些畫素沒有方向 DE,則缺少的資料可以寫為 (0.0, 0.0),但讀取器也應該處理這種情況下的 NaN。該向量指向遠離分形邊界。



floatType DE 有符號距離估計,歸一化使得相鄰邊界畫素的距離對於外部距離估計大致為 1.0,對於內部距離估計大致為 -1.0。如果存在外部 de 但沒有內部 de 可用(反之亦然),則缺少的資料可以寫為 0.0,但讀取器也應該處理這種情況下的 NaN。

floatType DEX,floatType DEY 方向距離估計,以笛卡爾形式歸一化,使得相鄰邊界畫素的距離 sqrt(DEX^2 + DEY^2) 大致為 1.0。如果一些畫素沒有方向 DE,則缺少的資料可以寫為 (0.0, 0.0),但讀取器也應該處理這種情況下的 NaN。該向量應該指向遠離分形邊界。

floatType ZX,floatType ZY 第一次逃逸迭代時的座標。影像應該具有一個標題屬性 floatType EscapeRadius。


軌道陷阱可以作為具有 TRAP 的路徑中的層進行處理

uint32 TRAP.N 命中陷阱時的迭代次數,有關大型迭代次數,請參見上文

floatType TRAP.TD 到陷阱的距離(例如,x 軸陷阱將具有 |y 座標|)(以你喜歡的任何方式進行歸一化,因為深度影像可能具有微小的值(也許?),但應該是單調的,例如,如果你取對數以獲得比 float32 更大的範圍,它可能是負數。

floatType TRAP.ZX,floatType TRAP.ZY 陷阱迭代時的座標,應該進行歸一化,以使陷阱邊緣的幅度為 1.0(不能僅使用 X 和 Y,因為 Y 在 EXR 中已經被用作顏色亮度)。

JPEG 是有損的

"KFC" 是 bNewFormat 1,float32 組合資料的垂直線(int32 迭代 + float32 平滑)

過時格式,參見 exr


地圖檔案 (.kfb) 包含

  • 計算出的分形資料
    • 迭代次數
      • N(最大迭代次數,整數)
      • NF(迭代次數,平滑部分 = 雙精度)
    • 如果啟用了導數計算,有時還會估計距離)
  • 它還包含一些顏色資訊(但這不是完整的)

它不包含座標。

這些檔案是在

  • 儲存 jpg 檔案時,還會為每個影像建立一個 kfb 檔案
  • 儲存地圖

描述

  • "KF 可以將原始迭代資料匯出為 EXR(以及過時的 KFB)格式,因此你可以在其他軟體中對其進行著色"
  • "KFB 檔案儲存原始未壓縮(即巨大但高質量)的迭代資料(在應用著色之前分形計算的結果)。" FF 上的克勞德,例如原始 float32 DE 影像(按畫素間距縮放)
  • "KFB 檔案是影像,用作地圖來儲存迭代資料。沒有位置、調色盤等" youhn


FF 上的克勞德:[4]

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

這是 Gerrit 編寫的 octave/matlab 程式碼:[5]

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



十六進位制編輯器中的檔案頭 

KFB....h.

kfp = Kalles Fraktaler 調色盤檔案

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)){


使用

 /path/to/kf.exe -s my.kfs -l my.kfr -c my.kfp -x my.exr
 
 

對於(重新)為包含原始迭代資料的現有 EXR 檔案著色,請嘗試

 /path/to/kf.exe -s old.exr -l old.exr -o old.exr -c new-palette.kfp  -x new.exr
  • 文字檔案
  • 包含引數

載入地圖檔案之前,可以使用引數檔案 (.kfr) 進行更進一步的導航。你可以將 .kfr 重新命名為 .kfp,並在顏色對話方塊中載入它。

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

示例

此檔案型別用於設定 (.kfs),有助於配置命令列渲染或儲存預設。

程式可以開啟和儲存帶有註釋的 pang


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

取樣 程式碼 : https://code.mathr.co.uk/kalles-fraktaler-2/blob/d685883599f7ae795bd7667834b0d2a47c00c7ef:/fraktal_sft/fraktal_sft.cpp#l3314 第 3314 行到 3379 行 KF 會這樣做

  • 為每個 dx、dy 偏移量生成 (i,j,seed) 的雜湊值(種子對於 x 和 y 不同)
  • 使用它進行抖動。

著色方法

[編輯 | 編輯原始碼]

KF 可以將原始迭代資料匯出為 EXR(以及過時的 KFB)格式,因此您可以使用其他軟體對其進行著色,但學習 GLSL 並編寫 KF 中的著色器可能與編寫其他軟體一樣容易。Zoomasm 4(未釋出的 WIP)中的著色器比 KF 更強大,因為您可以在程式碼中新增額外的均勻變數,並從 GUI 控制它們,這使得調整事物變得更容易。但仍然只有數字輸入欄位,這有點笨拙,並且真正設計用於具有指數對映序列的動畫。

Pauldelbrot 使用了一個複雜的“多波”著色演算法,它不同於(並且優於)預設 KFP 著色演算法中的調色盤波。檢視論壇中他在 LISP 變體(可能是 Clojure?)中釋出的原始碼。也許它也存在於 UF 公式資料庫中的某個地方?關鍵是擁有多個不同速率的 RGB 或 HSV 波,可能與分形的結構(週期等)相關聯,這些波以複雜的方式相互影響(這絕對不僅僅是 R G B 或 H S V 的單獨波,而是 3D 色彩的波)。此外,這在不同的色彩空間中完成,因為混合 sRGB 值(如影像檔案中的那樣)是錯誤的(它們必須首先轉換為線性以使混合有意義)。

Claude 在他的分形探索機器人 Rodney 中實現了一些可能類似的東西(但可能不如它好)。



可以更改它 

  • 主選單 / 操作/ 設定顏色
  • 鍵:Ctrl+C


可用的顏色方法是(在 main.cpp 檔案第 256 行,變數 m_nColorMethod) 

  • 0 = 標準 = 距離(線性):標準迭代帶著色
  • 1 = 平方根:顏色應用之前對迭代進行平方
  • 2 = 立方根:顏色應用之前應用立方根
  • 3 = 對數:顏色應用之前應用對數 = ColorMethod_Logarithm [6]:“ColorMethod_Logarithm 根本不是 DEM,而是具有非線性傳遞函式的逃逸時間。”
  • 4 = 拉伸:調色盤在最小-最大迭代值上拉伸
  • 5 = 距離:距離估計 :“ColorMethod_Distance* 有一些影像處理(查詢相鄰畫素的迭代值)來生成偽去著色。它不是真正的 DEM,但在某些情況下看起來很接近。”
  • 6 = DE+標準




描述方法的數字(變數 m_nColorMethod)在版本之間變化[7]


程式碼

  • 檔案 fraktal_sft.cpp
  • 變數 m_nColorMethod
  • 函式
    • 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;
			}
		}
	}


@color[int(($iteration/$divide_constant)%pallet_size)] -- (Perl code, % is the modulo operator)

其中除數(divide_constant)小於 1,如 0.1 或 0.01。


如何從命令列著色 KFB? 

這是一個小的 shell 指令碼,用於執行顏色迴圈

#!/bin/bash
f=0
for i in $(seq 0 32 1023)
do
  t=$((i * 360 / 1024))
  echo $f $i $t
  cat template.kfp |
  sed "s/ColorOffset: 0/ColorOffset: $i/" |
  sed "s/SlopeAngle: 45/SlopeAngle: $t/" > tmp.kfp
  ./kf.exe -o input.kfb -c tmp.kfp -p "$(printf %02d $f).png"
  f=$((f + 1))
done
for i in *.png
do
  convert $i -colorspace RGB -geometry 320x180 -colorspace sRGB $i.gif
done
gifsicle --colors 256 --delay 4 --loop --optimize *.png.gif > output.gif


這是另一個示例

  • 找到一個不錯的 位置
  • 在您的 OpenGL GLSL 著色器中使用 KFP_ColorOffset
  • 找出使顏色迴圈與分形對齊的魔數(此示例使用 30.0)
vec3 colour()
{
  if (getInterior()) { return KFP_InteriorColor; }
  float49 N = getN();
  N = div(N, 30.0);
  N = add(N, KFP_ColorOffset / 1024.0);
  return mix(vec3(0.0), texture(KFP_Palette, to_float(N)).rgb,
    tanh(clamp(0.25 * length(getDE()), 0.0, 4.0)));
}
  • 將分形儲存為 EXR 對映檔案,尺寸為所需大小(可能比最終輸出大,用於超取樣以進行抗鋸齒)。
  • 執行一個 bash 指令碼,以動畫化 KFP_ColorOffset 並儲存幀
#!/bin/bash
seq 0 32 1023 |
cat -n |
while read frame ColorOffset
do
  echo -e "ColorOffset: ${ColorOffset}\r" > palette.kfp
  /path/to/kf.x86_64.exe -s map.exr -l map.exr -o map.exr -c palette.kfp -t "$(printf %04d "${frame}").tif"
done

這將渲染 32 幀,對於 16 幀,將 0 32 1023 更改為 0 64 1023,對於 64 幀,更改為 0 16 1023 - 通常二的冪將是最平滑的迴圈

  • 使用 ImageMagick 將幀轉換為帶有伽馬校正降尺度的 GIF
for i in *.tif
do
   convert "${i}" -colorspace RGB -geometry 256x256 -colorspace sRGB "${i}.gif"
done
  • 將幀組裝到動畫 GIF:gifsicle --delay 5 --loop --optimize --colors 256 *.tif.gif > output.gif
  • 在 Firefox 或其他軟體中檢視 GIF

後處理效果

[edit | edit source]

斜率

[edit | edit source]
  "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


變數

  • m_bSlopes = FALSE; 是布林變數
  • m_nSlopePower = 50; 是斜率陰影深度,整數
  • m_nSlopeRatio = 50; 是斜率陰影強度,整數
  • m_nSlopeAngle = 45; 是斜率陰影角度(0-360),整數


顯示斜率

  • 啟用斜率編碼以實現 3D 效果。
  • 第一個值是斜率的放大倍數。100 的起始值適用於未縮放的檢視。深檢視需要高几個數量級的值。
  • 第二個值是將斜率編碼應用於著色的百分比。100 是最大值,但平坦區域仍然會顯示調色盤顏色。


演算法


 grep -nR "Slope"

工具

[edit | edit source]


KFMovieMaker

[edit | edit source]

影片

效果


混合

 grep -nR "Blend"

縮寫

[edit | edit source]
  • ADE = 分析 DE = 分析距離估計
  • NDE = 數值 DE
  • DDE = 方向 DE
  • NR = 牛頓-拉夫森縮放
  • SMB
  • BLA 雙線性近似加速方法
  • SA = 級數逼近
  • SSA
  • SFT = K.I. Martin 的超級分形
  • ET = 逃逸時間
  • ETA
    • 逃逸時間演算法(?)

參考文獻

[編輯 | 編輯原始碼]
  1. fractalforums.org : 如何渲染一個超過 10 億次迭代的影像所需記憶體
  2. fractalforums.org : Kalle 分形上的額外逃逸變化
  3. 邁向二維逃逸時間迭代資料的通用檔案格式
  4. fractalforums org: KF 檔案型別
  5. fractalforums org : matlaboctave-code-for-kfb-reading
  6. fractalforums : 距離對數測試
  7. fractalforums : kalles-fraktaler/向後相容性
華夏公益教科書