mieki256's diary



2024/02/06(火) [n年前の日記]

#2 [basic] FreeBASICで反転描画。その2

Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit で、標準機能のグラフィック描画で反転描画する方法について調べてる。

_昨日 は、公式掲示板で紹介されていた、色々な実装を動作確認していたわけだけど。その中の imgput() がイイ感じだなと…。

_Put function that does simple transformations - freebasic.net

ただ、透明色を扱わない仕様だったので、透明色有りで動くようにできないかと修正を試みた。

ソース :

実処理部分。オリジナル版と混ざるとアレなので、サブルーチン名は imgput() から imgputt() にしておいた。

_imgputt.bi


imgputt()の使用サンプル。

_imgputt_test.bas
' imgput() sample. RGB = (255, 0, 255) is transparent

#include "imgputt.bi"

#define BPP  32
'#define BPP  16
'#define BPP  8

screenres 512, 288, BPP
Dim As Any Ptr p = ImageCreate(101, 101)
Select Case BPP
Case 8 : Bload "sprite_8bit.bmp", p : color 16, 16 : cls
Case 16 : Bload "sprite_16bit.bmp", p
Case 32 : Bload "sprite_24bit.bmp", p
End Select

Dim As Integer mode = 0  ' 0 Trans, 1 Pset

' Draw
imgputt( p, , 10 + 120 * 0, 10, 0,   mode)
imgputt( p, , 10 + 120 * 1, 10, 90,  mode)
imgputt( p, , 10 + 120 * 2, 10, 180, mode)
imgputt( p, , 10 + 120 * 3, 10, 270, mode)

imgputt( p, , 10 + 120 * 0, 130, TRANSFORM_HFLIP,  mode )
imgputt( p, , 10 + 120 * 1, 130, TRANSFORM_VFLIP,  mode )
imgputt( p, , 10 + 120 * 2, 130, TRANSFORM_D1FLIP, mode )
imgputt( p, , 10 + 120 * 3, 130, TRANSFORM_D2FLIP, mode )

imagedestroy p
sleep


使用画像。

_sprite_24bit.bmp
_sprite_16bit.bmp
_sprite_8bit.bmp

fbc imgputt_test.bas でコンパイル。imgputt_test.exe を実行。

imgputt_test_ss1.png

RGB = (255, 0, 255) の部分が透明になっている。

ベンチマークを取ってみた :

せっかくだから、Put() と比べてどのくらい遅いのか調べてみた。

また、ついでなので、昨日自分が書いた、縦1ライン、もしくは横1ライン毎に Put() を使って逆方向に描画する版( PutEx() )も測ってみた。

_putex.bi

_imgputt_test2.bas
#include "imgputt.bi"
#include "putex.bi"

#define BPP  32
'#define BPP  16
'#define BPP  8

screenres 512, 288, BPP
Dim As Any Ptr p = ImageCreate(101, 101)
Select Case BPP
Case 32 : Bload "sprite_24bit.bmp", p
Case 16 : Bload "sprite_16bit.bmp", p
Case 8 : Bload "sprite_8bit.bmp", p : color 16, 16 : cls
End Select

Dim As Double starttime, t0, t1, t2
Dim As Integer max_count = 3000

Sub sub1(ByVal max_count As Integer, ByVal p As Any Ptr)
    For i As Integer = 0 To max_count
        Put (10, 10), p, Trans
        ' Put (10, 10), p, Pset
    Next i
End Sub

Sub sub2(ByVal max_count As Integer, ByVal p As Any Ptr)
    For i As Integer = 0 To max_count
        'imgputt( p, , 130, 10, TRANSFORM_HFLIP, 0 )
        'imgputt( p, , 130, 10, TRANSFORM_VFLIP, 0 )
        imgputt( p, , 130, 10, TRANSFORM_HFLIP Or TRANSFORM_VFLIP, 0 )
    Next i
End Sub

Sub sub3(ByVal max_count As Integer, ByVal p As Any Ptr)
    For i As Integer = 0 To max_count
        'PutEx(10, 130, p, 0, 0, 101, 101, 1)
        'PutEx(10, 130, p, 0, 0, 101, 101, 2)
        PutEx(10, 130, p, 0, 0, 101, 101, 3)
    Next i
End Sub

starttime = Timer
ScreenLock
sub1(max_count, p)
ScreenUnlock
t0 = Timer - starttime

sleep 1000

starttime = Timer
ScreenLock
sub2(max_count, p)
ScreenUnlock
t1 = Timer - starttime

sleep 1000

starttime = Timer
ScreenLock
sub3(max_count, p)
ScreenUnlock
t2 = Timer - starttime

sleep 1000

Print "Put     : " & t0 & " sec (100%)"
Print "imgputt : " & t1 & " sec (" & int((t1 / t0) * 100) & "%)"
Print "PutEx   : " & t2 & " sec (" & int((t2 / t0) * 100) & "%)"

imagedestroy p
sleep

fbc imgputt_test2.bas でコンパイル。imgputt_test2.exe を実行。

  • imgputt() は、メモリからメモリに値をコピーするものとして処理をしている。
  • PutEx() は、横1ライン、もしくは縦1ライン毎に、Put() を使って逆方向に描画していく。水平垂直反転の時だけ、1ドット単位で Put() を呼んで描画する。

水平反転のみ、垂直反転のみ、水平垂直反転、の3つを測定。

imgputt_test2_ss1.png

imgputt_test2_ss2.png

imgputt_test2_ss3.png


フォントが小さくて読めないかもしれないけれど、大体以下のような結果になった。

  • 水平反転のみ、かつ、透明色有効の場合、Put() と比べて、imgputt() は5倍遅い。PutEx() は6倍遅い。
  • 垂直反転のみ、かつ、透明色有効の場合、Put() と比べて、imgputt() は5倍遅い。PutEx() は2倍遅い。
  • 水平垂直反転、かつ、透明色有効の場合、Put() と比べて、imgputt() は5倍遅い。PutEX() は135倍遅い。

imgputt() は、大体5倍ぐらい遅い。どの反転描画も似たような処理をするので、処理速度は安定している。

ライン単位で Put() を呼んでいく PutEx() はかなり遅いのではないかと思ってたけど、意外とそうでもなかった。imgputt() は5倍遅いけど、PutEx() の水平反転は6倍ちょっと程度。そんなに悪くない。垂直反転に至っては Put() の2倍程度で処理できてるので、5倍遅い imgputt() よりも処理が速かった。これは意外だった。

ただ、PutEx() で水平垂直反転をすると、最悪な結果になる。135倍遅いのは、さすがに…。おそらく、Put() を1回呼ぶたびに、画面をオーバーしてないか等を調べていくのだろうけど、それを1ドットずつやってたら話にならないよなと…。

Put()のソースを眺めてみた :

それにしても、標準描画機能の Put() は異様に速い。どういう処理をしているのだろう。github にC言語で書かれたソースがあったので眺めてみた。

_fbc/src/gfxlib2/gfx_put_trans.c at master - freebasic/fbc

fb_hPutTrans1C()、fb_hPutTrans2C()、fb_hPutTrans4C() があるけれど、それぞれ、色深度8bitモード(パレットモード)、16bitモード(RRRRRGGGGGGBBBB bit)、32bitモード(AARRGGBB byte)なのだろう。

やってることは、imgputt() とさほど変わらない印象。y と x でループを回して、1ドットずつ見ていって、値をコピーするかしないかを決めて、ポインタをしかるべき値で進める。まあ、そうなるよなあ…。

もしかして、+= ではなくて、++ をループ内で使ってるあたりが効いてるのだろうか?

以上です。

過去ログ表示

Prev - 2024/02 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project