パレット再配置スクリプト
(2009.03.25)
ImageF/Xでフルカラーを5プレーンCMAPに変換すると、パレットはその画像に最適化されます。複数の画像を変換すると、画像毎に異なるRGB値、パレット順となります。これらの画像を連続で、例えば「画像表示→パレット変更」の順で処理すると画像を表示した際は、まだパレットを変更していなくて、つまり前の画像に合ったパレットのままなので表示色がハチャメチャとなります。もちろん、パレット変更が終了すれば、きちんと見えます。画像を高速(25fps)で切り換えると、ハチャメチャな瞬間が1秒間に25回、現れます。この瞬間を無くすには、画像毎に異なるパレットを統一しておけばいいです。はじめにImageF/Xで固定したパレットに合わせてRGB→CMAPに変換しようと試みましたが失敗です。つぎにAminetを捜索、しかしながら見つけ方が下手っぴなので見つけられません。そこでImageF/Xから呼び出すARexxスクリプトを使って異なる画像間でパレットのマッチング、ピクセルのパレット再配置をやってみました。この機能では複数の画像を使うのが前提なので、複数画像の一括処理ソフトAutoFX用にしました。
変換開始の際にパレットの基準となる画像を指定、1枚目を処理する際に開いてパレットを取得、あとは1枚ずつ、基準パレットとマッチングして変更しています。マッチングは単純にRGBの3次元色空間で最寄のパレットを捜します。
/*
* $VER: RelocatePalette.ifx.pre 1.0 (24.03.09)
* Freely re-distributed.
* Written by olfa
*
* Relocate CMAP to same CMAP.
*
* Inputs:
* Word(Arg(1),1) = Sequence number (?)
* Word(Arg(1),2) = Total number of frames (N)
*
* Returns:
* 0 if successful, non-zero on failure
*
*/
OPTIONS RESULTS
ADDRESS IMAGEFX.1
base = 'Autofx_RelocatePalette_'
basename = base || 'Base'
basepath = GETCLIP(basename)
palettename = base || 'palette_'
IF basepath = "" THEN DO
GetPrefs SavePath
basepath = result
END
Gadget.1 = 'STRING 175 5 200 14 "Palette Base Image:" "'basepath'"'
Gadget.2 = 'FILEREQ 366 5 20 14 "Palette Base Image:" "'basepath'" AT=1'
Gadget.3 = 'END'
NewComplexRequest '"Relocate Palette"' Gadget 405 27
IF rc ~= 0 THEN DO
EXIT rc
END
CALL SETCLIP(basename, result.1)
CALL SETCLIP(base || 'palnum', '')
i = 0
DO WHILE i < 256
SETCLIP(palettename || i, '')
i = i + 1
END
EXIT 0
/*
* $VER: RelocatePalette.ifx.pre 1.0 (24.03.09)
* Freely re-distributed.
* Written by olfa
*
* Relocate CMAP to same CMAP.
*
* Inputs:
* Word(Arg(1),1) = Frame number (1 - N)
* Word(Arg(1),2) = Main filename ("-" if not specified)
* Word(Arg(1),3) = Swap filename ("-" if not specified)
* Word(Arg(1),4) = Sequence number (?)
* Word(Arg(1),5) = Total number of frames (N)
*
* Returns:
* 0 if successful, non-zero on failure
*
*/
OPTIONS RESULTS
ADDRESS IMAGEFX.1
framenum = Word(Arg(1),1)
mainname = Word(Arg(1),2)
swapname = Word(Arg(1),3)
seq = Word(Arg(1),4)
framemax = Word(Arg(1),5)
base = 'Autofx_RelocatePalette_'
base.path = GETCLIP(base || 'Base')
base.palnum = GETCLIP(base || 'palnum')
base.palettename = base || 'palette_'
/* gracefully exit if no buffer */
GetMain
IF rc ~= 0 THEN DO
EXIT 0
END
org.name = WORD(RESULT, 1)
org.width = WORD(RESULT, 2)
org.height = WORD(RESULT, 3)
org.palnum = WORD(RESULT, 13)
base.palnum = GETCLIP(base || 'palnum')
IF '' == base.palnum THEN DO
LoadBuffer base.path new
IF rc ~= 0 THEN DO
EXIT rc
END
GetMain
base.palnum = WORD(RESULT, 13)
SETCLIP(base || 'palnum', base.palnum)
i = 0
DO WHILE i < base.palnum
GetPalette i
SETCLIP(base.palettename || i, RESULT)
i = i + 1
END
KillBuffer Force
SelectBuffer org.name
END
i = 0
DO WHILE i < base.palnum
rgb = GETCLIP(base.palettename || i)
base.palette.i.r = WORD(rgb, 1)
base.palette.i.g = WORD(rgb, 2)
base.palette.i.b = WORD(rgb, 3)
i = i + 1
END
Menu Palette
org.menu = RESULT
i = 0
DO WHILE i < org.palnum
GetPalette i
org.r = WORD(RESULT, 1)
org.g = WORD(RESULT, 2)
org.b = WORD(RESULT, 3)
foundit = 0
target = (255 ** 2) * 3 + 1
j = 0
DO WHILE j < base.palnum
try_val = (org.r - base.palette.j.r) ** 2 + (org.g - base.palette.j.g) ** 2 + (org.b - base.palette.j.b) ** 2
IF try_val < target THEN DO
target = try_val
foundit = j
END
j = j + 1
END
palconv.i = foundit
SetPalette i base.palette.i.r base.palette.i.g base.palette.i.b
RedrawPalette
i = i + 1
END
Menu org.menu
BeginBar "ReLoc_Pal" org.height
y = 0
DO WHILE y < org.height
x = 0
DO WHILE x < org.width
GetPixel x y
oldpal = WORD(RESULT, 1)
newpal = palconv.oldpal
PutPixel x y newpal newpal newpal
x = x + 1
END
Bar y
y = y + 1
END
EndBar
Redraw
EXIT 0