|
|
2022/9/5(Mon) 23:36:52|NO.97073
はじめまして。
指定色のパレットで減色をしたいです。
画像内に使用されている色を、パレット内の近似色に置き換えるといった感じでしょうか。
イメージとしては、「ドット絵ナニカ」のどうぶつの森モードのような動作をさせたいです。
ドット絵ナニカ http://dot-e-nanika.com/
配列変数にパレットの色を代入し、1つ1つ計算するのも考えましたが、上手くいかなかったので、どのようにすれば上手くいくか教えていただきたいです。
|
|
2022/9/6(Tue) 05:02:51|NO.97076
特にオリジナルの減色方法を試みたい訳でないのであれば、
Windowsの機能をそのまま使うのが早いかもしれません。
パレットモードの画面にフルカラー画像をコピーすると勝手に減色されます。
一例ですがどうぞ。
; メイン画面をパレッドで処理化
screen 0, 640, 480, 1 : title "減色" : color : boxf
button gosub "読み込み", *Load
mref pallet1, 69 ;パレット取得
; 画像読み込み用バッファ
buffer 2, 640, 480, 0
picload dir_exe+"\\hsptv\\tamane_y2.png" : sx = ginfo_sx : sy = ginfo_sy
; パレッド編集画面
screen 1,256,256, 1 : title "パレット"
mref pallet2, 69 ;パレット取得
repeat 256 : palette cnt,0,0,0, (cnt==255) : loop; 全部黒に
palette 1,255,255,255 : palette 2,128, 0, 0
palette 3, 0,128, 0 : palette 4, 0, 0,128, 1
*MAIN
;パレッド変更
stick pad,,1
; 左クリックで変更
if (pad=256) & (ginfo_act=1){
pn = (mousex/16) + (mousey/16*16)
dialog "",33
if stat { palette pn,ginfo_r,ginfo_g,ginfo_b, 1 }
}
; Zでグレイスケール
if (pad=2048) & (ginfo_act=1){ repeat 256 : palette cnt,cnt,cnt,cnt, (cnt==255) : loop }
; Xで赤グラデーション
if (pad=4096) & (ginfo_act=1){ repeat 256 : palette cnt,cnt,0,0, (cnt==255) : loop }
; Cで全黒
if (pad=8192) & (ginfo_act=1){ repeat 256 : palette cnt,0,0,0, (cnt==255) : loop }
;メイン画面
gsel 0 : redraw 0
memcpy pallet1,pallet2,256*3 ;パレットコピー
palette 0,peek(pallet2,0),peek(pallet2,1),peek(pallet2,2),1 ;更新
pos 0,0 : gcopy 2, 0,0, sx, sy ;フルカラーからパレットコピーで勝手に減色
redraw 1
;パレッド編集画面
gsel 1 : redraw 0
repeat 16 : y=cnt
repeat 16 : x=cnt
pn = x+(y*16) : palcolor pn
xp = x*16 : yp = y*16
boxf xp, yp, xp+16, yp+16
loop
loop
redraw 1
await 16
goto *MAIN
; 読み込み
*Load
gsel 2
dialog "*", 16, "画像ファイル"
if stat == 0 : return
picload refstr : sx = ginfo_sx : sy = ginfo_sy
return

| |
|
2022/9/10(Sat) 10:18:05|NO.97109
面白い減色方法を思いついたので投稿
こういうやり方もある、といことで一つ
#module
;画像描写
#deffunc ringdraw double cx,double cy,double inlen,double outlen,int sval,int vval
sc = 191.0/360.0
repeat 361
rad=deg2rad(cnt)
;内側の点
p1x = cx + inlen * cos(rad)
p1y = cy + inlen * sin(rad)
;外側の点
p2x = cx + outlen * cos(rad)
p2y = cy + outlen * sin(rad)
rad=deg2rad(cnt+1)
;次の内側の点
p4x = cx + inlen * cos(rad)
p4y = cy + inlen * sin(rad)
;次の外側の点
p3x = cx + outlen * cos(rad)
p3y = cy + outlen * sin(rad)
;色の設定
hsvcolor int(sc*cnt),sval,vval
;4点の四角形
x = int(p1x),int(p2x),int(p3x),int(p4x)
y = int(p1y),int(p2y),int(p3y),int(p4y)
gsquare -1,x,y
loop
return
;減色画像描写
#deffunc decleasecolor int setwinid,int setx,int sety,int getwinid,int getx,int gety,int areaw,int areah,int decleasebit
mask1=(1<<decleasebit)-1
mask2=$ffff<<(decleasebit+1)
repeat areah:j=cnt
repeat areaw:i=cnt
;描写元の色を取得
gsel getwinid
pget i+getx,j+gety
r=ginfo(16)
g=ginfo(17)
b=ginfo(18)
;減色処理
r=r|mask1
g=g|mask1
b=b|mask1
r+=1
g+=1
b+=1
r=r&mask2
g=g&mask2
b=b&mask2
r-=1:if r<0:r=0
g-=1:if g<0:g=0
b-=1:if b<0:b=0
;描写先に色を設定
gsel setwinid
color r,g,b
pset i+setx,j+sety
loop
loop
return
#global
buffer 1,160,160
ringdraw 80,80,0,20,255,125
ringdraw 80,80,20,40,255,255
ringdraw 80,80,40,60,125,255
screen 0
redraw 0
pos 0,0:gcopy 1,,,160,160
bit=256
repeat 8,0
x=(cnt\4)*160
y=(cnt/4)*160
decleasecolor 0,x,y,1,0,0,160,160,cnt
color
pos x+20,y
tbit=bit>>cnt
mes"rgb="+tbit+"*"+tbit+"*"+tbit
loop
redraw

| |
|
2022/9/10(Sat) 18:31:16|NO.97118
>雪月夜さん
おおぉ、奇麗に色数下がってますね!
単純にビット落としたのではこうならないので感動しました。
>たくちゃさん
”配列変数にパレットの色を代入し、1つ1つ計算”というの考えてみました。
#module
#define WEIGHT_R 0.3 ; 色の重みづけ
#define WEIGHT_G 0.6 ; ここを好きに変えると結果が変わる
#define WEIGHT_B 0.1
; パレット配列から近い色番号を見つける関数
#defcfunc palfind array _pal, int _col
result = 0
dist = 2147483647
c = (_col >> 16) & $FF, (_col >> 8) & $FF, _col & $FF
; 一番近いパレット番号を求める
foreach _pal
pc = peek(_pal.cnt, 2), peek(_pal.cnt, 1), peek(_pal.cnt, 0)
; 色の距離
pd = powf(double(pc.0 - c.0)*WEIGHT_R, 2)
pd += powf(double(pc.1 - c.1)*WEIGHT_G, 2)
pd += powf(double(pc.2 - c.2)*WEIGHT_B, 2)
if pd < dist {
result = cnt
dist = pd
}
loop
return result
#global
;画像読み込み
file_name = dir_exe+"\\hsptv\\tamane_y2.png"
gosub *読み込み
; 今回は適当にパレット作成
#define PALLET_MAX 16
dim pallet, 16
randomize
pallet = 0, $FFFFFF
repeat PALLET_MAX-2,2
pallet.cnt = rnd(255)<<16 ; R
pallet.cnt |= rnd(255)<<8 ; G
pallet.cnt |= rnd(255) ; B
loop
; パレット表示
bgscr 1, 32*PALLET_MAX, 32
repeat PALLET_MAX
color peek(pallet.cnt, 2), peek(pallet.cnt, 1), peek(pallet.cnt, 0)
boxf cnt*32, 0, cnt*32+32, 32
loop
bgscr 3, 128,64, 8 : gsel 3, 2
*メイン
; マウスカーソルの下の色を取得してパレット検索
gsel 0
pget mousex, mousey
r = ginfo_r : g = ginfo_g : b = ginfo_b
index = palfind(pallet, (r<<16)|(g<<8)|b)
title strf("x %d: y %d: PAL %d", mousex, mousey, index )
x = ginfo_wx1 : y = ginfo_wy2
gsel 1 : width ,, x ,y
;パレットの情報表示
gsel 3
color r, g, b : boxf 0,0,64,64
color peek(pallet.index, 2), peek(pallet.index, 1), peek(pallet.index, 0) : boxf 64,0,128,64
width ,, ginfo_mx+32 ,ginfo_my+32
await 16
goto *メイン
*減色
gsel 0
repeat ginfo_sy : y = cnt
title strf("減色中: %d%", y*100/ginfo_sy)
redraw 0
repeat ginfo_sx : x = cnt
pget x, y
r = ginfo_r : g = ginfo_g : b = ginfo_b
index = palfind(pallet, (r<<16)|(g<<8)|b)
color peek(pallet.index, 2), peek(pallet.index, 1), peek(pallet.index, 0)
pset x, y
loop
redraw 1 : wait 0
loop
title "減色完了!"
return
*読み込みダイアログ
gsel 0
dialog "*", 16, "画像ファイル"
if stat == 0 : return
file_name = refstr
*読み込み
picload file_name
button gosub "読み込み", *読み込みダイアログ
button gosub "減食", *減色
return

| |
|
2022/9/12(Mon) 11:42:00|NO.97122
>雪月夜 様
>usagi 様
御二方のスクリプトを参考になんとか想像していた動作を実装することが出来ました。
この度はありがとうございました!
これにて解決済みとさせていただきます。
|
|