トップページ > 記事閲覧
BltStringSoftImageの拡大縮小について
名前:lego hasiri 日時: 2023/01/01 19:51

あけましておめでとうございます 現在こちら(dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=past&no=1366)を参考にエッジ付きフォントのグラデーション表示の実装をしています。 また、フォントをきれいに拡大縮小表示もできるようにしようと、フォントサイズを大きめ(100程度)でロードしています。 この条件下でやろうとすると、12文字程度の文字列で、横に大きすぎるのかCreateGraphFromRectSoftImageがエラー(-1)を返してしまいます。 そこでDrawModiStringやDrawExtendStringのようにBltStringSoftImageで文字列を書き込む段階で、目的の大きさまで縮小できればと考えております。 急ぎではないのですが、もしよろしければBltStringSoftImageの拡大縮小に対応したようなものの追加を検討していたらければと思います。 あるいは別の手段で実現可能だったりするのでしょうか? 大変読みづらい文章になってしまいましたがよろしくお願いしますm(_ _)m
メンテ

Page: 1 |

Re: BltStringSoftImageの拡大縮小について ( No.1 )
名前:管理人 日時:2023/01/02 21:26

あけましておめでとうございます! 仮に BltStringSoftImage の拡大縮小に対応したものを追加したとしても、 大きな画像をCPUでバイリニアフィルタリングなどを伴った縮小処理を行うと 非常に処理負荷が高くなるので、DrawString で縁だけ、若しくは本体だけ描画できるようにするための 機能を追加して、BltStringSoftImage を使用しなくても『文字のグラデーション』のスレッドの No.2 の処理が 行えるようにしてみました というわけで、よろしければこちらの機能を追加した暫定最新バージョンを ダウンロードしてください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい) 以下の関数を追加しました // フォントの描画で縁のみ、又は本体のみ描画を行うかどうかを設定する // OnlyType 0:通常描画 1:本体のみ描画 2:縁のみ描画 int SetFontOnlyDrawType( int OnlyType ) ; DrawString 等の文字列描画関数を使用する前に SetFontOnlyDrawType( 1 ); を実行していれば 縁付きフォントでも本体だけが描画され、 SetFontOnlyDrawType( 2 ); を実行していれば 本体は描画されず縁だけが描画されますので、これで BltStringSoftImage と CreateGraphFromRectSoftImage で 行っていた『本体と縁を別々のグラフィックハンドルとして作成する』を BltStringSoftImage などを使用しなくても 実現することが出来ます そしてこちらが 『文字のグラデーション』の No.2 に書かれている処理を BltStringSoftImage を 使用せずに実装したものとなります #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int FontHandle, ImageHandle, EdgeImageHandle, DrawWidth ; int TempScreen, EdgeTempScreen ; VERTEX Vertex[ 6 ] ; ChangeWindowMode( TRUE ) ; // 32bitカラーを設定 SetGraphMode( 640, 480, 32 ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) { // エラーが発生したら直ちに終了 return -1 ; } // 乗算済みアルファタイプの縁つきアンチエイリアスフォントの作成 SetFontCacheUsePremulAlphaFlag( TRUE ) ; FontHandle = CreateFontToHandle( NULL, 24, -1, DX_FONTTYPE_ANTIALIASING_EDGE ) ; // 文字列イメージを描き込む仮画面を作成( 縁用と二つ ) TempScreen = MakeScreen( 640, 480, TRUE ) ; EdgeTempScreen = MakeScreen( 640, 480, TRUE ) ; // 文字列の本体を仮画面に描き込む SetDrawScreen( TempScreen ) ; ClearDrawScreen() ; SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, 255 ) ; // 乗算済みアルファ版のアルファブレンドに設定 SetFontOnlyDrawType( 1 ) ; DrawStringToHandle( 0, 0, "グラデーションテスト", GetColor( 255,255,255 ), FontHandle, GetColor( 255,255,255 ) ) ; // 文字列の縁を仮画面に描き込む SetDrawScreen( EdgeTempScreen ) ; ClearDrawScreen() ; SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, 255 ) ; // 乗算済みアルファ版のアルファブレンドに設定 SetFontOnlyDrawType( 2 ) ; DrawStringToHandle( 0, 0, "グラデーションテスト", GetColor( 255,255,255 ), FontHandle, GetColor( 255,255,255 ) ) ; // 描画幅を取得する DrawWidth = GetDrawStringWidthToHandle( "グラデーションテスト", strlenDx( "グラデーションテスト" ), FontHandle ) ; // 描画幅と描画高さの派生グラフィックハンドルを作成する ImageHandle = DerivationGraph( 0, 0, DrawWidth, 26, TempScreen ) ; EdgeImageHandle = DerivationGraph( 0, 0, DrawWidth, 26, EdgeTempScreen ) ; // 描画先を表画面に戻す SetDrawScreen( DX_SCREEN_FRONT ) ; // 縁の部分は緑色で描画 SetDrawBright( 0, 255, 0 ) ; SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, 255 ) ; // 乗算済みアルファ版のアルファブレンドに設定 DrawGraph( 0, 0, EdgeImageHandle, TRUE ) ; SetDrawBright( 255, 255, 255 ) ; // 本体部分は DrawPolygon を使用して上下に赤から青にグラデーションさせながら描画 Vertex[ 0 ].x = 0.0f ; Vertex[ 0 ].y = 0.0f ; Vertex[ 1 ].x = DrawWidth ; Vertex[ 1 ].y = 0.0f ; Vertex[ 2 ].x = 0.0f ; Vertex[ 2 ].y = 26.0f ; Vertex[ 3 ].x = DrawWidth ; Vertex[ 3 ].y = 26.0f ; Vertex[ 0 ].u = 0.0f ; Vertex[ 0 ].v = 0.0f ; Vertex[ 1 ].u = 1.0f ; Vertex[ 1 ].v = 0.0f ; Vertex[ 2 ].u = 0.0f ; Vertex[ 2 ].v = 1.0f ; Vertex[ 3 ].u = 1.0f ; Vertex[ 3 ].v = 1.0f ; Vertex[ 0 ].b = 0 ; Vertex[ 0 ].g = 0 ; Vertex[ 0 ].r = 255 ; Vertex[ 0 ].a = 255 ; Vertex[ 1 ].b = 0 ; Vertex[ 1 ].g = 0 ; Vertex[ 1 ].r = 255 ; Vertex[ 1 ].a = 255 ; Vertex[ 2 ].b = 255 ; Vertex[ 2 ].g = 0 ; Vertex[ 2 ].r = 0 ; Vertex[ 2 ].a = 255 ; Vertex[ 3 ].b = 255 ; Vertex[ 3 ].g = 0 ; Vertex[ 3 ].r = 0 ; Vertex[ 3 ].a = 255 ; Vertex[ 4 ] = Vertex[ 2 ] ; Vertex[ 5 ] = Vertex[ 1 ] ; DrawPolygon( Vertex, 2, ImageHandle, TRUE, TRUE ) ; // キー入力待ち WaitKey() ; // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; } MakeARGB8ColorSoftImage をはじめとしたソフトウェアイメージは使用せずに MakeScreen や DrawString を使用して実装しています ソフトウェアイメージに対する文字列描画である BltStringSoftImage では拡大縮小描画を行うことは出来ませんが、 通常の文字列描画の場合は DrawExtendStringToHandle という拡大縮小描画の関数がありますので これで lego hasiriさんの望まれる処理が行えるのではないかと思います // フォントハンドルを使用して文字列を拡大描画する int DrawExtendStringToHandle( int x, int y, double ExRateX, double ExRateY, const char *String, unsigned int Color, int FontHandle, unsigned int EdgeColor = 0, int VerticalFlag = FALSE ) ; 因みにきれいに拡大縮小表示ができるようにフォントサイズを100にされているとのことですが、 SetDrawMode( DX_DRAWMODE_BILINEAR ); を設定してバイリニアフィルタリングを伴う縮小描画を行った場合でも バイリニアフィルタリングのアルゴリズムの性質上 1/2 以下のサイズへの縮小は SetDrawMode( DX_DRAWMODE_NEAREST ); の 最近点フィルタリングと同様に潰れたドットの情報が欠落した縮小描画となりますので、きれいに縮小して描画を行う場合は フォントサイズ 100 のフォントハンドル → サイズ 51 〜 100 の範囲の描画用 フォントサイズ 50 のフォントハンドル → サイズ 26 〜 50 の範囲の描画用 フォントサイズ 25 のフォントハンドル → サイズ 12 〜 25 の範囲の描画用 ↑ こちらのように、幾つかのサイズのフォントハンドルを用意して使い回す必要がありますのでご注意ください m(_ _)m
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.2 )
名前:lego hasiri 日時:2023/01/04 04:50

ご対応ありがとうございます。 なんとかやりたいことはできそうです。 フォントサイズの件も了解しました。 ただ提示いただいたコードで問題点(?)があって、PMA_ALPHAを使って20程度の大きさの縁付きグラデーションの文字を描画すると、にじんだような感じになってしまいました。(フォントはMSゴシック、ブレンドはPMA_ALPHA、α値は255、本体のほうが広がった感じになっていた) まだしっかりと検証したわけではないのでこちら側の問題なのかもしれませんが、管理人さんのほうで確認していただければと思います。 また少し別件なのですが、DrawModiString系で文字列を描画すると最初の描画時の文字数分しか描画されませんでした。 以下のコードをすると int i = 0; while(ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) { auto s = std::format("{}", i + 50); auto w = GetDrawStringWidth(s.c_str(), s.length()); DrawModiString(0, 0, w, 0, w, 20, 0, 20, 0xffffff, 0, 0, s.c_str()); DrawModiFormatString(0, 64, w, 64, w, 84, 0, 84, 0xffffff, 0, 0, "%d", i + 1000); i++; } 2つとも上位の2桁が、横幅がwで描画されています。グラデーションと同様にスクリーンを使ってやれば回避はできると思いますが、これはバグかなと思うのでこちらも確認いただければと思います。
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.3 )
名前:lego hasiri 日時:2023/01/04 04:55

追記で、PMAを使わず普通にアルファブレンドをした場合は期待通りに描画できました。
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.4 )
名前:管理人 日時:2023/01/05 00:47

> ただ提示いただいたコードで問題点(?)があって、PMA_ALPHAを使って20程度の大きさの縁付きグラデーションの文字を描画すると、にじんだような感じになってしまいました。(フォントはMSゴシック、ブレンドはPMA_ALPHA、α値は255、本体のほうが広がった感じになっていた) > まだしっかりと検証したわけではないのでこちら側の問題なのかもしれませんが、管理人さんのほうで確認していただければと思います。 手元の環境ではそのままのプログラムでも、サイズを 20 に変更しても滲むことはありませんでした 20程度の大きさの縁付きグラデーションの文字とのことですが No.1 のプログラムを一切変更せずに 実行しても lego hasiriさんの環境では滲んでしまうでしょうか? > また少し別件なのですが、DrawModiString系で文字列を描画すると最初の描画時の文字数分しか描画されませんでした。 すみません、DrawModiStringにバグがありました( ある if文で > とすべきところが < となっていました… ) 修正版をアップしましたので、何度も申し訳ありませんがよろしければこちらをお試しください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい) > 追記で、PMAを使わず普通にアルファブレンドをした場合は期待通りに描画できました。 MakeScreen で作成した画像に対して半透明の描画を行う場合は、DX_BLENDMODE_PMA_ALPHA を 使用しないと正しい計算が行われないので、今回の文字描画についても文字の半透明部分の 見た目が厳密には正しくない状態となります ( ただ、文字の半透明の部分は輪郭部分だけなのであまり気にならないかもしれませんが… ) どのような仕組みで『MakeScreen で作成した画像に対して半透明の描画を行う場合は DX_BLENDMODE_PMA_ALPHA を 使用しないと正しい計算が行われない』のかについては、こちらで解説していますので よろしければご覧ください m(_ _)m <乗算済みアルファのすすめ> https://dxlib.xsrv.jp/lecture/PremulAlpha/PremulAlpha.html
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.5 )
名前:lego hasiri 日時:2023/01/06 23:55

DrawModiStringの修正ありがとうございます。無事描画されてました。 滲みの件ですが、実行結果を張ります。見れますでしょうか? (共にMSゴシックのサイズは16、縁は黒で上が白、下が青のグラデーション、その他は変えてません) gyazo.com/258d681c2b62b05f1f8b1967ca32301d 上がPMAを使わないほうで下がPMAを使ったほうです。 滲みという言い方があれだったかもしれませんが、上のほうが縁が濃いように感じます。それで縁がみにくくなっていて滲んでるように感じたのだと思います。 この場合下のほうが正しい描画結果ということなのでしょうか?
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.6 )
名前:管理人 日時:2023/01/07 01:23

> DrawModiStringの修正ありがとうございます。無事描画されてました。 ご迷惑おかけしました、正常に動作したようで何よりです m(_ _)m > この場合下のほうが正しい描画結果ということなのでしょうか? すみません、lego hasiriさんがどのようにプログラムを変更されたのか詳細が不明なため 正しい描画結果なのかを判断することが出来ません 申し訳ありませんが、No.1 のプログラムをそのまま実行した際に正常に表示されるかをご確認いただけますでしょうか? m(_ _)m 因みに、私の環境で No.1 のプログラムをそのまま実行した際はこちらのような結果になっています https://dxlib.xsrv.jp/temp/GradationStringTest.png
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.7 )
名前:lego hasiri 日時:2023/01/07 18:06

いただいたサンプルをそのまま実行すると、画像と同じものです。 あと一応No5のプログラムも載せておきます。 #include "DxLib.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int size = 18; ChangeWindowMode(TRUE); SetBackgroundColor(255, 255, 255); // 32bitカラーを設定 SetGraphMode(640, 480, 32); // DXライブラリの初期化 if (DxLib_Init() < 0) { // エラーが発生したら直ちに終了 return -1; } { int FontHandle, ImageHandle, EdgeImageHandle, DrawWidth; int TempScreen, EdgeTempScreen; VERTEX Vertex[6]; FontHandle = CreateFontToHandle("MSゴシック", size - 2, -1, DX_FONTTYPE_ANTIALIASING_EDGE); // 文字列イメージを描き込む仮画面を作成( 縁用と二つ ) TempScreen = MakeScreen(640, 480, TRUE); EdgeTempScreen = MakeScreen(640, 480, TRUE); // 文字列の本体を仮画面に描き込む SetDrawScreen(TempScreen); ClearDrawScreen(); SetDrawBlendMode(DX_BLENDMODE_ALPHA, 255); // のアルファブレンドに設定 SetFontOnlyDrawType(1); DrawStringToHandle(0, 0, "通常のグラデーションテスト", GetColor(255, 255, 255), FontHandle, GetColor(255, 255, 255)); // 文字列の縁を仮画面に描き込む SetDrawScreen(EdgeTempScreen); ClearDrawScreen(); SetDrawBlendMode(DX_BLENDMODE_ALPHA, 255); // アルファブレンドに設定 SetFontOnlyDrawType(2); DrawStringToHandle(0, 0, "通常のグラデーションテスト", GetColor(255, 255, 255), FontHandle, GetColor(255, 255, 255)); // 描画幅を取得する DrawWidth = GetDrawStringWidthToHandle("通常のグラデーションテスト", strlenDx("通常のグラデーションテスト"), FontHandle); // 描画幅と描画高さの派生グラフィックハンドルを作成する ImageHandle = DerivationGraph(0, 0, DrawWidth, size, TempScreen); EdgeImageHandle = DerivationGraph(0, 0, DrawWidth, size, EdgeTempScreen); // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); // 縁の部分は緑色で描画 SetDrawBright(0, 0, 0); SetDrawBlendMode(DX_BLENDMODE_ALPHA, 255); // アルファブレンドに設定 DrawGraph(0, 0, EdgeImageHandle, TRUE); SetDrawBright(255, 255, 255); // 本体部分は DrawPolygon を使用して上下に赤から青にグラデーションさせながら描画 Vertex[0].x = 0.0f; Vertex[0].y = 0.0f; Vertex[1].x = DrawWidth; Vertex[1].y = 0.0f; Vertex[2].x = 0.0f; Vertex[2].y = size; Vertex[3].x = DrawWidth; Vertex[3].y = size; Vertex[0].u = 0.0f; Vertex[0].v = 0.0f; Vertex[1].u = 1.0f; Vertex[1].v = 0.0f; Vertex[2].u = 0.0f; Vertex[2].v = 1.0f; Vertex[3].u = 1.0f; Vertex[3].v = 1.0f; Vertex[0].b = 255; Vertex[0].g = 255; Vertex[0].r = 255; Vertex[0].a = 255; Vertex[1].b = 255; Vertex[1].g = 255; Vertex[1].r = 255; Vertex[1].a = 255; Vertex[2].b = 255; Vertex[2].g = 0; Vertex[2].r = 0; Vertex[2].a = 255; Vertex[3].b = 255; Vertex[3].g = 0; Vertex[3].r = 0; Vertex[3].a = 255; Vertex[4] = Vertex[2]; Vertex[5] = Vertex[1]; DrawPolygon(Vertex, 2, ImageHandle, TRUE, TRUE); } { int FontHandle, ImageHandle, EdgeImageHandle, DrawWidth; int TempScreen, EdgeTempScreen; VERTEX Vertex[6]; // 乗算済みアルファタイプの縁つきアンチエイリアスフォントの作成 SetFontCacheUsePremulAlphaFlag(TRUE); FontHandle = CreateFontToHandle("MSゴシック", size - 2, -1, DX_FONTTYPE_ANTIALIASING_EDGE); //SetFontCacheUsePremulAlphaFlag(FALSE); // 文字列イメージを描き込む仮画面を作成( 縁用と二つ ) TempScreen = MakeScreen(640, 480, TRUE); EdgeTempScreen = MakeScreen(640, 480, TRUE); // 文字列の本体を仮画面に描き込む SetDrawScreen(TempScreen); ClearDrawScreen(); SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255); // 乗算済みアルファ版のアルファブレンドに設定 SetFontOnlyDrawType(1); DrawStringToHandle(0, 0, "乗算済みグラデーションテスト", GetColor(255, 255, 255), FontHandle, GetColor(255, 255, 255)); // 文字列の縁を仮画面に描き込む SetDrawScreen(EdgeTempScreen); ClearDrawScreen(); SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255); // 乗算済みアルファ版のアルファブレンドに設定 SetFontOnlyDrawType(2); DrawStringToHandle(0, 0, "乗算済みグラデーションテスト", GetColor(255, 255, 255), FontHandle, GetColor(255, 255, 255)); // 描画幅を取得する DrawWidth = GetDrawStringWidthToHandle("乗算済みグラデーションテスト", strlenDx("乗算済みグラデーションテスト"), FontHandle); // 描画幅と描画高さの派生グラフィックハンドルを作成する ImageHandle = DerivationGraph(0, 0, DrawWidth, size, TempScreen); EdgeImageHandle = DerivationGraph(0, 0, DrawWidth, size, EdgeTempScreen); // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); // 縁の部分は緑色で描画 SetDrawBright(0, 0, 0); SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255); // 乗算済みアルファ版のアルファブレンドに設定 DrawGraph(0, 30, EdgeImageHandle, TRUE); SetDrawBright(255, 255, 255); // 本体部分は DrawPolygon を使用して上下に赤から青にグラデーションさせながら描画 Vertex[0].x = 0.0f; Vertex[0].y = 30.0f; Vertex[1].x = DrawWidth; Vertex[1].y = 30.0f; Vertex[2].x = 0.0f; Vertex[2].y = 30+ size; Vertex[3].x = DrawWidth; Vertex[3].y = 30+ size; Vertex[0].u = 0.0f; Vertex[0].v = 0.0f; Vertex[1].u = 1.0f; Vertex[1].v = 0.0f; Vertex[2].u = 0.0f; Vertex[2].v = 1.0f; Vertex[3].u = 1.0f; Vertex[3].v = 1.0f; Vertex[0].b = 255; Vertex[0].g = 255; Vertex[0].r = 255; Vertex[0].a = 255; Vertex[1].b = 255; Vertex[1].g = 255; Vertex[1].r = 255; Vertex[1].a = 255; Vertex[2].b = 255; Vertex[2].g = 0; Vertex[2].r = 0; Vertex[2].a = 255; Vertex[3].b = 255; Vertex[3].g = 0; Vertex[3].r = 0; Vertex[3].a = 255; Vertex[4] = Vertex[2]; Vertex[5] = Vertex[1]; DrawPolygon(Vertex, 2, ImageHandle, TRUE, TRUE); } // キー入力待ち WaitKey(); // DXライブラリの後始末 DxLib_End(); // ソフトの終了 return 0; }
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.8 )
名前:管理人 日時:2023/01/08 20:38

No.5 のプログラムの掲載ありがとうございます PMA の方が正常な描画結果にならない原因がわかりました すみません、乗算済みアルファを使用する場合は仮画面を必ず真っ黒( R=0 G=0 B=0 )で初期化しなければ いけないので、SetBackgroundColor の引数が 0, 0, 0 以外になっていると正常に動作しません なので、載せていただいたプログラムの DxLib_Init の呼び出し後の箇所に SetBackgroundColor(0, 0, 0); を追加した所、PMA を使用した文字列の描画も正常な描画結果になりましたので よろしければお試しください m(_ _)m
メンテ
Re: BltStringSoftImageの拡大縮小について ( No.9 )
名前:lego hasiri(解決済) 日時:2023/01/09 15:09

検証ありがとうございます。 背景を黒にする処理を追加したところ、無事描画できました。 ご対応ありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存