2024/02/09(金) [n年前の日記]
#1 [basic] FreeBASICで反転描画。その4
Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit で、標準機能のグラフィック描画で反転描画する方法について調べてる。
imgput() を改造して、透明色を有効にしたり、描画元領域を指定できるようにしてみたけれど、ウインドウ外に描画すると見た目がおかしくなることに気づいて修正していた。水平垂直反転の描画時は動作するようになったと思ったら、回転描画時にクラッシュしたりして…。まあ、どうにか動く状態になった気がする。
実処理部分をライブラリファイル(lib*.a)化して、ヘッダファイル(.bi)を include すれば使えるようにしてみた。ライブラリファイルは gas ではなく gcc + 最適化有効でコンパイルしたので、Put() と比べて4倍遅かったのが、1.5〜2倍程度の遅さに改善された。
せっかくだから、現状の成果を置いときます。
_imgputt2_20240209.zip
ただ、 _元ファイル(imgput()) のライセンスが不明で…。「改良する元ソースにはなるだろう」とか書いてあった気もするから、自由に使っていいのではと勝手に思ってるけど…。
imgput() を改造して、透明色を有効にしたり、描画元領域を指定できるようにしてみたけれど、ウインドウ外に描画すると見た目がおかしくなることに気づいて修正していた。水平垂直反転の描画時は動作するようになったと思ったら、回転描画時にクラッシュしたりして…。まあ、どうにか動く状態になった気がする。
実処理部分をライブラリファイル(lib*.a)化して、ヘッダファイル(.bi)を include すれば使えるようにしてみた。ライブラリファイルは gas ではなく gcc + 最適化有効でコンパイルしたので、Put() と比べて4倍遅かったのが、1.5〜2倍程度の遅さに改善された。
せっかくだから、現状の成果を置いときます。
_imgputt2_20240209.zip
ただ、 _元ファイル(imgput()) のライセンスが不明で…。「改良する元ソースにはなるだろう」とか書いてあった気もするから、自由に使っていいのではと勝手に思ってるけど…。
◎ サンプルのスクリーンショット :
◎ ライブラリのソースとヘッダーファイル :
◎ 簡単な使い方 :
簡単なサンプル。imgputt.bi を include すれば、imgputt() が使えるようになる。
_simple_sample.bas
_simple_sample.bas
#include once "imgputt.bi" screenres 512, 288, 32 Dim As Any Ptr p = ImageCreate(288, 288) Bload "obj_24bit.bmp", p Put (10, 10), p, (0, 96) - Step(96, 96), Trans imgputt(p, , 10, 10 + 100, TRANSFORM_VFLIP, IMGPUT_TRANS, 0, 96, 96, 96) imagedestroy p sleep
[ ツッコむ ]
#2 [basic] FreeBASICでbmp画像のサイズを調べたい
FreeBASIC を使って画像の反転描画の実験をしていた際、指定したサイズで画像が描画されなくて、数時間悩んでしまった。
原因はしょーもないことだった。bload でbmp画像を読み込むその前に、ImageCreate() を使って画像と同じサイズの画像バッファを用意しなきゃいけないのだけど。以前の実験で使ってた、小さい画像のサイズのままだった、というオチで…。
でも、そのあたりは自動でやってほしいよなあ…。フツー(?)のライブラリなら、画像ファイル名を指定するだけで、サイズ取得、バッファ確保、ファイル読み込みを全部やってくれるものではないか…。
ということで、bmp画像のファイル名を指定するだけで、サイズ取得、バッファ確保、画像をロードする処理を書いてみた。
環境は Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。
原因はしょーもないことだった。bload でbmp画像を読み込むその前に、ImageCreate() を使って画像と同じサイズの画像バッファを用意しなきゃいけないのだけど。以前の実験で使ってた、小さい画像のサイズのままだった、というオチで…。
でも、そのあたりは自動でやってほしいよなあ…。フツー(?)のライブラリなら、画像ファイル名を指定するだけで、サイズ取得、バッファ確保、ファイル読み込みを全部やってくれるものではないか…。
ということで、bmp画像のファイル名を指定するだけで、サイズ取得、バッファ確保、画像をロードする処理を書いてみた。
環境は Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。
◎ ソース :
実処理部分。
_loadbitmapimage.bi
使用サンプル。
_getbitmapsize.bas
使用画像は以下。
_obj_24bit.bmp
_obj_16bit.bmp
_obj_8bit.bmp
_loadbitmapimage.bi
' load bitmap image file #ifndef __LOADBITMAPIMAGE__ #define __LOADBITMAPIMAGE__ Function LoadBitmapImage(ByRef fname As Const string) As Any Ptr Dim As Integer f Dim As Long w, h ' open bitmap file f = FreeFile() Open fname For Binary Access Read As #f If Err > 0 Then Print "Error: Can not open file" : Return 0 Get #f, 19, w ' get width Get #f, , h ' get height Close #f ' Print "Bitmap : " & fname & " (w,h)=(" & w & "," & h & ")" ' create image Dim As Any Ptr img = ImageCreate(w, h, RGB(0, 0, 0)) If img = 0 Then Print "Error: Can not ImageCreate()" : Return 0 ' load bitmap to image bload fname, img Return img End Function #endif
使用サンプル。
_getbitmapsize.bas
' get bitmap image size #include "loadbitmapimage.bi" ScreenRes 512, 288, 32 Dim As String fname = "obj_8bit.bmp" 'Dim As String fname = "obj_16bit.bmp" 'Dim As String fname = "obj_24bit.bmp" ' load bitmap image Dim img As Any Ptr = LoadBitmapImage(fname) ' get image width, height, bpp Dim As Integer w, h, bpp ImageInfo(img, w, h, bpp) Put (0, 0), img Print "Load: " & fname & " (" & w & ", " & h & ")" Print "Push Any Key" ImageDestroy(img) sleep
使用画像は以下。
_obj_24bit.bmp
_obj_16bit.bmp
_obj_8bit.bmp
◎ 雑感 :
一応動作はしたのだけど、この処理、bmp画像をサイズ取得のためだけに1度オープンしてからクローズして、bload でまたオープンするという、実にトンチキな作りで…。
本来なら、1度ファイルをオープンしてメモリ上に読み込んでから、サイズ取得、バッファ確保、バッファ上に展開、とかするのが妥当なのだろうな…。画像ファイルをオープンする処理と、メモリ上に存在する画像データを展開する処理は、別れてたほうが都合がいいはず。
本来なら、1度ファイルをオープンしてメモリ上に読み込んでから、サイズ取得、バッファ確保、バッファ上に展開、とかするのが妥当なのだろうな…。画像ファイルをオープンする処理と、メモリ上に存在する画像データを展開する処理は、別れてたほうが都合がいいはず。
◎ 参考ページ :
_BMP ファイルフォーマット
_BMP画像のファイル構造(ヘッダ部・データ部) | 西住工房
bmp画像の横幅、縦幅は、ファイル先頭を0バイト目とした場合、18バイト目から4バイトずつ並んでる。
FreeBASIC で get を使って、ファイルから値を読み込む際、一番最初のバイトにアクセスするなら1を指定するので…。前述のソースでは以下のような記述になっている、とメモ。
_BMP画像のファイル構造(ヘッダ部・データ部) | 西住工房
bmp画像の横幅、縦幅は、ファイル先頭を0バイト目とした場合、18バイト目から4バイトずつ並んでる。
FreeBASIC で get を使って、ファイルから値を読み込む際、一番最初のバイトにアクセスするなら1を指定するので…。前述のソースでは以下のような記述になっている、とメモ。
Get #f, 19, w ' get width Get #f, , h ' get height
[ ツッコむ ]
以上、1 日分です。