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


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
1104
空気(非急)hsp3utilの縁取りの品質を僅かに改善してみましたが・・・4解決


空気

リンク

2015/11/4(Wed) 00:57:57|NO.72768

hsp3utilの縁取りの品質にどうにも満足できなかったので、僅かながら改善を試みて見ましたが、

太さ5以上の縁取りをした場合はエッジに凸凹が出現する。(文字サイズ100の場合)
丸ゴシックのように縁が丸い文字でないと、文字の角の部分の縁取りが甘い。
と完璧な物にはなりませんでしたが、一応ながら、公表してみます。

他の方の実装を調べてみても、GDIを使った場合は縁が文字の内側にめり込むようで、
http://elega.php.xdomain.jp/2014/06/hsp-character-fuchi/で公開なされている
縁取り処理についてもはみ出したところがカットされているような感じになるようです。

綺麗な縁取り処理が無いことでそれほど困っている訳ではないのですが、
縁取り処理について話し合えると個人的にはいいかなと思い、
スレッドを建てさせていただきました。


以下、私の製作したサブルーチンです。(非モジュール)
#include "hsp3util.as"
;(お試しになられる方でedge_fontとfontの部分につきましては、 ;丸ゴシックをお持ちの方は所持しているフォント名に変更してください。} *draw_text;文字描画 redraw 0 edge_pos = 0,0 edge_font = "モトヤLマルベリ3等幅" edge_fontsize = 100 edge_color = 0,0,0 edge_mes = "縁取り+αです。" gosub *text_edge_w3_pass1 pos 0,0 color 0,0,0 gosub *text_edge_w3_pass2 font "モトヤLマルベリ3等幅",100 color 255,255,255 emes "縁取り+αです。" redraw 1 stop /*縁取り*/ *text_edge_w3_pass1;縁取り処理1パスへ edge_weight = 5 gosub*text_edge return *text_edge_w3_pass2;縁取り処理2パスへ;hsp3utilを兼用しないと凸凹が増加する。 textmode 2,4 color 0,0,0 return /*縁取り処理2パス*/ *text_edge;文字縁取りルーチン ecR = edge_color(0) ecG = edge_color(1) ecB = edge_color(2) ex = edge_pos(0) ey = edge_pos(1) repeat edge_weight pos ex,ey-cnt color ecR,ecG,ecB font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey-cnt font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex-cnt,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex-cnt,ey font edge_font,edge_fontsize mes edge_mes pos ex-cnt,ey+cnt font edge_font,edge_fontsize mes edge_mes loop ;逆から1周させないと品質が低下する。同じ方向でループは駄目 repeat edge_weight pos ex-cnt,ey font edge_font,edge_fontsize mes edge_mes pos ex-cnt,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey+cnt font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey font edge_font,edge_fontsize mes edge_mes pos ex+cnt,ey-cnt font edge_font,edge_fontsize mes edge_mes pos ex,ey-cnt color ecR,ecG,ecB font edge_font,edge_fontsize pos ex-cnt,ey-cnt font edge_font,edge_fontsize mes edge_mes await 0 loop return



この記事に返信する


774

リンク

2015/11/6(Fri) 21:31:32|NO.72817

内側は元のを貼り付けるだけだと思うので、太い縁を作る方法をいくつか。

A.上下左右に1〜縁幅分ずらした画像を重ねる
 お手軽に太い縁になります。参照先もこれですね。
 アルゴリズム的に、縦横に直線状の部分が出来ます。
 また、斜め方向の縁が太くなります。
 (この辺りがカットされたように見える所以かと思います)

B.縁幅を半径とする円状に画像を重ねる
 Aとほぼ同様ですが、ずらして重ねる位置を円の範囲内に限定します。
 縁の太さが均一となり直線状の部分も出来難いです。
 但し、書体に関係無く角が丸くなります。

C.1pxずつ周囲の色を調べて拡張していく
 時間が掛かる割にBとほぼ同じでした。
 拡張判定のさじ加減でもう少し違うかもですが、時間対効果が覆る事は無さそうです。

D.WinAPIを利用してみる
 縁取り用ではないですが、外郭をなぞるAPIで描いてみました。
 結果はBと同じ様なものでした。(ちょっとジャギが出やすいかも)
 APIなので高速です。

E.◆状にずらして重ねてみる
 斜め方向の縁が細くなり、やや歪な感じで汎用性は低そうです。
 ホラーモノなんかには向いてるかも知れません。

F.フォントファイルから文字のパスを抜き出し、各ポイントを外側へ移動した図形を得る
 理想に近い形状を得られるかも知れませんが面倒過ぎてやってられません。

以下は、A〜Eの比較用サンプルです。

#define global cFontName msGothic ;フォント名 #define global cFontSize 60 ;文字サイズ #define global cFontType 0 ;フォントスタイル #define global cFontCol $ff8000 ;文字色 #define global cEdgeCol $0000c0 ;縁の色 #define global cFontCol2 -1 #define global cEdgeCol2 -1 #define global cGradType 3 #const global _buf 10 ;作業用バッファID #module #uselib "gdi32.dll" #func _BeginPath "BeginPath" sptr #func _EndPath "EndPath" sptr #func _StrokePath "StrokePath" sptr #cfunc _CreatePen "CreatePen" int,int,int #func _SelectObject "SelectObject" sptr,sptr #func _DeleteObject "DeleteObject" sptr #deffunc _ef_Init int p0 ;Screen _buf,gInfo.20*4,gInfo.21,8 :Title "BUF" Buffer _buf,gInfo.20*4,gInfo.21 _tmp_=1 :gSel p0 Return ;--縁取り文字用フォント設定("FontName",Size,Style) #deffunc ef_Font str p0, int p1, int p2, local a If(_tmp_==0){_ef_Init gInfo.3} a=gInfo.3 :gSel _buf :Font p0,p1*2,p2 :gSel a Return ;--縁取り文字描画("Text",Type,EdgeW,fCol,eCol,fCol2,eCol2) #define global ef_Mes(%1,%2=0,%3=1,%4=-1,%5=-1,%6=-1,%7=-1) _ef_Mes %1,%2,%3,%4,%5,%6,%7 #deffunc _ef_Mes str p0, int p1, int p2, int p3, int p4, int p5, int p6, local a, local b If(_tmp_==0){_ef_Init gInfo.3} :If(p2<1){Mes p0 :Return 0} Dim a,9 :a=p3&$ffffff,p4&$ffffff,p5&$ffffff,p6&$ffffff,p1&7,p2*2 :a.8=gInfo.3 If(p3<0){a.0=(gInfo.16<<16)|(gInfo.17)<<8|gInfo.18} :If(p4<0){a.1=a.0^$ffffff} If(p5<0){a.2=a.0} :If(p6<0){a.3=a.1} :gSel _buf :Color :BoxF Pos a.5,a.5 :HsvColor ,,255 :Mes p0+" " :a.6=gInfo.14+a.5*2,gInfo.15+a.5*2 If(a.4==0){ef_Mes1 a.5,a.6,a.7} If(a.4==1){ef_Mes2 a.5,a.6,a.7} If(a.4==2){ef_Mes3 a.5,a.6,a.7} If(a.4==3){ef_Mes4 a.5,a.6,a.7,p0+" "} If(a.4==4){ef_Mes5 a.5,a.6,a.7} gMode 0 :Pos a.6/2,0 :gZoom a.6/2,a.7,_buf,0,0,a.6,a.7*2,1 :a.6=a.6/2,a.7/2 GradF 0,0,a.6,a.7,p1>>4&1,a.1,a.3 :GradF 0,a.7,a.6,a.7,p1>>3&1,a.0,a.2 gMode 7,a.6,a.7 :Pos 0,0 :gCopy _buf,0,a.7 gSel a.8 :mRef b,67 :a.0=b.35,b.33,b.34,b.65 :Dim b gMode 7,a.6,a.7 :gCopy _buf,0,0 :gMode a.0,a.1,a.2,a.3 Return ;--上下左右に文字を重ねる #deffunc ef_Mes1 int p0, int p1, int p2 gMode 0,p1,p2 :Pos 0,p2 :gCopy _buf :gMode 5,p1-p0,p2-p0,255 Repeat p0,1 :Pos 0,0 :gCopy _buf,cnt,p2 :Loop Repeat p0+1 :Pos 0,p2*2 :gCopy _buf,0,cnt :Loop :Color :BoxF ,,,p2-1 Repeat 4 :Pos (cnt&1)*p0,(cnt>>1&1)*p0 :gCopy _buf,0,p2*2,p1,p2 :Loop Return ;--円形に文字を重ねる #deffunc ef_Mes2 int p0, int p1, int p2, local a gMode 0,p1,p2 :Pos 0,p2 :gCopy _buf :gMode 5,p1-p0*2,p2-p0*2,255 Repeat p0+1 :a=cnt,Int(Sqrt((p0*p0)-(cnt*cnt))+0.5) :Repeat a.1*2+1,p0-a.1 Pos p0+a,cnt :gCopy _buf,p0,p0+p2 If(a){Pos p0-a,cnt :gCopy _buf,p0,p0+p2} Loop :Loop Return ;--1pxずつ調べて拡張 #deffunc ef_Mes3 int p0, int p1, int p2, local a, local b, local c gMode 0,p1,p2 :Pos 0,p2 :gCopy _buf :mRef b,_buf+96 Dim a,10 :a.6=b.67,b.5+b.16,b.67*p2 :a.7-=a.8 Dim b :DupPtr b,a.7,a.8,2 :sDim c,a.8 Repeat p0 :Repeat p2 :a.1=cnt,cnt*a.6 :Repeat p1 :a.4=lPeek(b,a.2),0 a.3=(0<cnt)|((0<a.1)<<1)|(((p1-1)>cnt)<<2)|(((p2-1)>a.1)<<3) If((a.3&3)==3){a.5+=Peek(b,a.2-a.6-3)} :If((a.3&6)==6){a.5+=Peek(b,a.2-a.6+3)} If((a.3&9)==9){a.5+=Peek(b,a.2+a.6-3)} :If((a.3&12)==12){a.5+=Peek(b,a.2+a.6+3)} a.5>>=1 :If(a.3&1){a.5+=Peek(b,a.2-3)} :If(a.3&2){a.5+=Peek(b,a.2-a.6)} If(a.3&4){a.5+=Peek(b,a.2+3)} :If(a.3&8){a.5+=Peek(b,a.2+a.6)} a.5=Limit((a.5>>1)+(a.4&$ff),0,255) lPoke c,a.2,(a.4&$ff000000)|(a.5<<16)|(a.5<<8)|a.5 :a.2+=3 Loop :Loop :MemCpy b,c,a.8 :Loop Return ;--APIを利用して縁取り #deffunc ef_Mes4 int p0, int p1, int p2, str p3, local a gMode 0,p1,p2 :Pos 0,p2 :gCopy _buf :Color :BoxF ,,,p2-1 :HsvColor ,,255 a=_CreatePen(0,p0*2,$ffffff) :_SelectObject hDC,a :a.1=stat _BeginPath hDC :Pos p0,p0 :Mes p3 :_EndPath hDC _StrokePath hDC :_SelectObject hDC,a.1 :_DeleteObject a gMode 5,p1,p2,255 :Pos 0,0 :gCopy _buf,0,p2 Return ;--◆状に文字を重ねる #deffunc ef_Mes5 int p0, int p1, int p2, local a gMode 0,p1,p2 :Pos 0,p2 :gCopy _buf :gMode 5,p1-p0*2,p2-p0*2,255 Repeat p0+1 :a=cnt,p0-cnt :Repeat a.1*2+1,p0-a.1 Pos p0+a.0,cnt :gCopy _buf,p0,p2+p0 If(a.0){Pos p0-a.0,cnt :gCopy _buf,p0,p2+p0} Loop :Loop Return #global *start Screen 0,,,2 ef_Font cFontName,cFontSize,cFontType sDim sIpt,$100 :sIpt="はろ〜 World 24" :iIpt=5 Pos 4,4 :Input sIpt,496,20 :ObjSize 64,20 Pos 504,4 :Button gosub "MES",*Edge_Mes Pos 572,4 :Input iIpt,64,20 :gSel 0,1 Stop *Edge_Mes gSel 0 :HsvColor ,,255 :BoxF :i=Limit(Int(iIpt),1,50) Repeat 5 Title StrF("%dつ目描いてます",cnt+1) :aWait 1 :Pos 4,cnt*(i+cFontSize+4)+40 ef_Mes sIpt,cnt|(cGradType<<3),i,cFontCol,cEdgeCol,cFontCol2,cEdgeCol2 Redraw 1 :Redraw 0 Loop :Title "完了。" Return
全て2倍サイズで描画し、ハーフトーンで50%に縮小しています。



空気

リンク

2015/11/8(Sun) 15:03:25|NO.72845

774さん>
綺麗な縁取り処理を考案して頂き、ありがとうございます。
活用させて頂きます。

『C.1pxずつ周囲の色を調べて拡張していく』の方法は
仰るとおり、Corei7でもリアルタイム処理は不可能なぐらい重いので
低スペPCも配慮すると、リアルタイム性がなくても使うのはなかなか難しいですね。
ほぼ効果の同じBや、速度が非常に速く中々の品質のDを使うのがいいかもしれませんね。

私自身、ベジェ曲線を扱かった事がありますので、
Fの処理も理論上は可能程度には思っていましたが、
実装するとなると、フォントファイルのアウトラインを取得し、
アンカーポイントやハンドルを計算で移動することになりそうですので、
やはり、現実的では無いでしょうね。

WindowsのようにWinAPIが利用できる端末では高速な「D」を
HSP3DishのようなWinAPIが使えない端末では「B」をベースに使っていこうかと思います。

これから機会があれば、ゲームタイトル等に使おうと思いますので、
(処理を改変させて頂く事もあるかと思います。)
ライセンスについて教えて頂ければ、幸いです。

「Adobe®illustrator」と774さんの「HSPによる縁取り処理」を比較してみました
(似ていない等と表記しているのは批評や優劣を決めるものではございませんので、
 ご理解の程をよろしくお願い致します。)

画像は下記アドレス
http://s3.gazo.cc/up/49106.png
又は
http://nagamochi.info/src/up157181.png.html

・B〜Dは非常に「Adobe®illustrator」の縁取りを
 ラウンド結合に設定したものに非常によく似ていると思います。
・Eはベベル結合に似ているかと思いましたが、並べてみると意外と差異がありました。
・Fの処理がマイター結合のようになるかと思われます。



空気

リンク

2015/11/8(Sun) 15:19:32|NO.72847

個人的な話ですが、
HSP公式の縁取りモジュール「hsp3util」も
774さんのモジュールぐらいの品質になると嬉しいですね。
もちろん、HSP3DishのマルチプラットフォームとWindowsオンリーの処理は
別の処理で搭載してほしいですが。



774

リンク

2015/11/8(Sun) 19:12:52|NO.72857

あくまで私個人の意見ですが、ライセンス云々言うくらいなら掲示板に貼ってません。
という事で、煮るなり焼くなりご自由にお使い下さい。
改変に付きましても、色々と無駄が多い内容ですので寧ろお勧め致します。

ついでに、改変の参考になるかは判りませんが…
B〜Dの品質差は、4倍や8倍サイズから縮小する事で軽減できそうです。
Bはコピー時の不透明度を下げる事で、アンチエイリアスのような効果を期待できるかも知れません。

Eは■●のついでに◆もやってみただけのお遊びのようなものですので、
まともなペイントソフトの処理とちょっと似ていた事の方に驚きです(w


hsp3utilのはノベルゲームなんかで使う細い縁取りを想定したもののような気がします。
そういう用途であれば、あれはあれでベストなんじゃないでしょうか。



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