HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0905
たくちゃ指定色パレットで減色4解決


たくちゃ

リンク

2022/9/5(Mon) 23:36:52|NO.97073

はじめまして。
指定色のパレットで減色をしたいです。
画像内に使用されている色を、パレット内の近似色に置き換えるといった感じでしょうか。
イメージとしては、「ドット絵ナニカ」のどうぶつの森モードのような動作をさせたいです。
 ドット絵ナニカ http://dot-e-nanika.com/
配列変数にパレットの色を代入し、1つ1つ計算するのも考えましたが、上手くいかなかったので、どのようにすれば上手くいくか教えていただきたいです。



この記事に返信する


usagi

リンク

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



usagi

リンク

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 様

御二方のスクリプトを参考になんとか想像していた動作を実装することが出来ました。
この度はありがとうございました!

これにて解決済みとさせていただきます。



ONION software Copyright 1997-2023(c) All rights reserved.