SDIB32GL

はじめに

Win32APIには多彩な描画関数はありますが、動作が重いなどの問題があり速度重視されるアプリケーションでは敬遠されてきました。 また、アルファブレンディングや加算減算合成、アルファチャンネル付画像の転送といった高度な描画処理は本格的に使うとなるとDirect3DなどのAPIに頼らなければいけなくなります。

そこで、DIB(デバイス独立ビットマップ)を使用してこれらの高度な描画処理をソフトウェアで高速に処理してしまおうという目的で開発されたのがSDIB32GL(Super DIB 32bit Graphic Library)です。

機能・特徴

カラーキー
透過転送をWin32APIですると、BitBltを2回する必要性がありますがSDIB32GLのカラーキー転送を使えばDirectDrawのように簡単かつ高速な描画が可能です。
元画像背景画像合成後
アルファブレンディング
アルファブレンディングとは、半透明描画のことで転送元と転送先のRGBをそれぞれα値と呼ばれる0.0〜1.0の値で適切に処理したものです。 SDIB32GLでは高速化のためにα値を0〜255で表現しています。
元画像背景画像合成後
※カラーキー付のα値0.4(102)で合成
加算減算合成
加算合成は光ったものを表現する場合に使用し、減算合成は煙等の表現に使用することがあります。 合成系の中では特に高速な描画ができるのが特徴です。
元画像背景画像合成後
※加算合成
アルファチャンネル
アルファチャンネルとはRGB以外の8ビットを余分に使うこと(合計32ビット)で1ピクセル毎にα値を持ち、柔軟なアルファブレンド処理を可能としています。 α値が0か255だけのイメージを扱う場合に通常より高速に描画できるマスクイメージに特化したアルファチャンネルマスクもあります。
元画像(左:RGBデータ 右:αチャンネル)背景画像合成後
ユニバーサルトランジション
トランジションとはアドベンチャーゲームなどで、シーンとシーンの切り替えによく行うアニメーション処理のことです。 SDIB32GLでは白〜黒(α値だけのイメージ)で表現されたルール画像を使用することによって簡単にトランジションを実現できます。
元画像ルール画像背景画像
Phase=0.2Phase=0.4Phase=0.6Phase=0.8
グラフィック機能
Win32APIにはいくつかのグラフィック関数が用意されていますが、低速なうえアルファブレンディングや加算合成などの処理はできません。SDIB32GLでは全ての合成処理がサポートされています。
矩形領域楕円直線
フィルタ機能
SDIB32GLではイメージに直接フィルタ処理をすることができます。 サポートされているフィルタはネガポジ、モノクロ、セピア、ブライト、モザイクです。
ネガポジモノクロセピアブライトモザイク
ネガポジ以外は係数をリアルタイムに変更することによってアニメーションができます。
拡大縮小、回転、反転機能
Win32APIでは拡大縮小はできますが、任意の角度に回転したり反転することができません。 SDIB32GLでは拡大縮小、回転、反転転送を同時に適用しながら高速で描画できます。
横2倍に拡大45度回転横2倍に拡大
45度回転
上下反転
※ユニバーサルトランジションと特殊転送関数は回転が利用できません。
特殊転送機能
特殊転送ではアルファチャンネルだけを転送したり、カラーキーをアルファチャンネルに変換する機能があります。利用方法は様々です。
各種合成の重複が可能
アルファブレンディングしながら加算合成や、アルファチャンネルを適用しながらアルファブレンディングという転送ができます。 全て重複できるわけではなく一部の合成処理だけが可能となっています。
※拡大縮小、回転、反転と合成処理の重複は可能です。
各種画像イメージの読み込み・保存が可能
プログラマが新たに画像の読み込みコードをプログラムする必要がないように様々な画像形式に対応しています。
SDIB32GLで扱える画像フォーマットはBitmap(*.bmp)、Jpeg(*.jpg)、PNG(*.png)、TARGA(*.tga)がサポートされており、アルファチャンネルを含んだイメージも読み込み可能です。
さらに、竹村嘉人氏のSusieで利用できるSPIプラグインを使用することによって読み込める画像フォーマットを無限に拡張することができます。
ファイル以外にもメモリ、リソースからの読み込み機能も持ち合わせています。
保存にも対応していますので相互変換としての利用も可能です。
CPU依存の高速描画処理
SDIB32GLで使われている描画アルゴリズムは全てアセンブラに最適化されており、高速な描画処理が可能となっています。
Intel MMXテクノロジをサポートしているCPUならさらなる高速化が望めます。
COMインターフェイス
SDIB32GLは内部変数や関数群をCOMインターフェイスとして提供しているので様々な開発環境(Visual C++、Visual Basic、Delphi)でオブジェクト指向による開発が可能になります。
COMインターフェイスとは、簡単に言えばDLL内のプログラム(部品またはCOMオブジェクト)にアクセスするための規格です。
その規格(インターフェイス)を介してC++のクラスで実装されているSDIB32GL(COMオブジェクト)にアクセスできるので容易にコーディングが可能になるほかスピーディかつ美しいコーディングも可能となります。

※C/C++から利用する場合に限り、静的リンクを使用してSDIB32GLのCOMオブジェクトに直接アクセスできます。

対応開発環境

OSMicrosoft Windows 98/Me/2000/XP
CPUIntel x86 シリーズ互換プロセッサ、MMX搭載プロセッサ
開発ツール Microsoft Visual C++ 6.0
Microsoft Visual C++ .NET (※1)
Microsoft Visual C++ 2005 (※1)
Microsoft Visual Basic 6.0
Microsoft Visual Basic .NET (※1)
Microsoft Visual Basic 2005 (※1)
Borland Delphi 6
言語 C/C++
Visual Basic (※2)
Delphi (※2)
リンク方式 静的リンク、動的リンク (※3)

※1 未確認です。
※2 β版(95b、96b)は対応していません。
※3 C/C++で使用する場合は静的リンク(非COM)のみでも可能。

※十分な動作速度を得るにはIntel Pentium 4 1.5GHz以上のCPUと512MB以上のメモリを推奨します。

ダウンロード

最新バージョン
  • 本体(ランタイム+SDK+ソースコード)
    • SDIB32GL100.zip (6,649,440byte)

      ※Vectorからもダウンロードできます。

      →リファレンスファイルについて
旧バージョン
※ファイルは圧縮されていますのでダウンロード後、別途解凍ソフト等で解凍して下さい。
※ソースコードは修正BSDライセンスです。
※ソースコードをビルドするには最新のPlatform SDK(VC++6.0の場合はMicrosoft Platform SDK February 2003)とIJGのlibjpeglibpngzlibが別途必要です。
(注) 1.00以上と1.00未満(0.96、0.95)は互換性がありませんので実際の開発には使用しないで下さい。

更新履歴

ver 1.00 - 2004.04.17
  • Component Object Model(COM)に正式対応しました。 (これに伴い、引数、型、戻り値等の変更があります。)
  • Visual Basic、Delphiに対応しました。
  • メモリ、リソースからの読み込み機能を追加。
  • その他修正、機能の強化。
ver 0.96b - 2004.02.26
  • 読み込みフォーマットにPNGを追加し、TARGAを8ビット、8ビット+αチャンネルにも対応。
  • SPIプラグインに対応。
  • ユニバーサルトランジション機能を追加。
  • αチャンネルマスク機能追加。
  • その他バグ修正。
ver 0.95b - 2004.02.07
  • サンプルにDirectDrawを追加しました。
ver 0.95b - 2004.01.26
  • SDIB32GLとしてDLLに移行。
  • 回転拡大縮小描画機能追加。
  • フィルタ機能追加。
ver 試作2 - 2003.12.27
  • 直線、楕円機能追加。
  • 拡大縮小機能追加。
  • αチャンネル機能追加。
ver 試作1 - 2003.05.21
  • 初期バージョン完成。

今後の開発予定・既知の不具合

致命的な不具合は今のところ無いと思います。もしあれば御連絡下さいませ。
今後の開発予定についてですがまだ予定しておりません。もし、このDLLを使って下さる方が多ければ考えます。

これは不具合ではないですが、SDIB32GLFreeBSTR関数が実は必要のないものだったという事です。
とりあえず、あってもなくても害はなさそうなのでそのままにしておきます。
必要無い理由についてですが、ISDIB32GLインターフェイスにはGetFileNameというメソッドがあります。
これは、読んで時の如くファイル名を取得するメソッドで第1引数にBSTR型のポインタ(BSTR* lpbstrFileName)を指定します。
このメソッドを実行すると内部では::SysAllocStringがコールされBSTR型のメモリが確保されます。
通常DLL内で確保したメモリは、DLL内で解放するという規則があるのですが、BSTR型にはサイズプレフィクスと呼ばれる文字列のバイト数を確保した領域が設けられているので上記の”DLL内で確保したメモリは、DLL内で解放する”という規則にはあてはまりません。故に、呼び出し側でメモリの解放(::SysFreeString)が可能という事になります。
そのような理由からSDIB32GLFreeBSTRは必要無かったと判断しました。

FAQ for C/C++

  • リファレンスはないんですか?
  • ゴメンナサイ・・・とりあえず今はサンプルソースを参考にしてください。古いリファレンスも少しは使えると思います。
  • 『 error LNK2001: 外部シンボル "_IID_ISDib32GL" は未解決です 』等のコンパイルエラーが出ます。
  • これはSDIB32GLのGUIDが定義されていないためにでるエラーです。
    この場合次の2つのうちどちらかの方法でGUIDを定義して下さい。
    A. SDIB32GL.Hをインクルードした1つのソースファイルの上に#include<initguid.h>と記述して下さい。
    B. SD32GLGUID.LIBをプロジェクトにインポートするだけです。
  • 32ビットDIBしか扱えないのでしょうか?
  • アルゴリズムの問題から32ビットしか扱えません。
  • バージョンアップしたらリビルドしなければならないのでしょうか?
  • その必要はありません。DLLをインストールし直す(差し替える)だけです。
  • TARGAファイルの読み込みでエラーが出ます。
  • そのTARGAは圧縮されていませんか?TARGAの圧縮ファイルはサポートされていません。
  • 描画がものすごく重いのですが?
  • SDIB32GLはメモリとCPUの性能に依存します。あまり古いCPU、メモリですと重いかもしれません。
  • DLLでエラーがでます。
  • 実行した関数とその方法を添えて、お手数ですがご報告お願いします。
  • MMX用とX86用インターフェイスの混在は可能でしょうか?
  • それぞれ別のオブジェクトですのでMMXならMMXのオブジェクトにX86ならX86のオブジェクトに転送しないと描画されません。
  • 描画時の拡大縮小が荒い、回転の精度が悪いですがなんとかなりませんか?
  • なんともなりません。ゲーム開発を目的としている以上この辺は仕方ないです。
  • 回転描画時の角度がおかしいのですが?
  • 角度はラジアンではなく0〜512度の角度です。
  • 描画後にαチャンネルがおかしくなるのですが?
  • αチャンネルについてフィルタ機能以外は描画後に不定となります。 これは処理速度を向上させるためαチャンネル領域を計算部分に使用しているからです。 これを回避するには予め描画するバッファのαチャンネルだけをを別のバッファに転送しておき描画後αチャンネルだけを転送することで解決します。 しかし、2回余分に描画することになるので処理速度面では重くなりますがこのような状況は稀ですので処理対象として省かせて頂きました。 フィルタ機能は主に元の画像に適用するものなのでαチャンネルは壊さない設計となっています。
  • 描画できません。
  • サンプルも描画できないようでしたら他に問題があるのかもしれません。
  • 拡大縮小ってどうやるんですか?
  • 拡大なら転送先のサイズを転送元サイズより大きくします。 縮小なら転送先のサイズを転送元サイズより小さくします。
    例)元画像を2倍に拡大して転送します。
    SIZE sizeSrc = { 64, 64 }; SIZE sizeDest = { 128, 128 };
    pBack->Blt( pHoge, 0, 0, sizeDest, 0, sizeSrc );
  • 上下左右反転ってどうやるんですか?
  • 反転は転送先サイズの値を負にするだけです。 例)左右反転して転送します。
    SIZE sizeSrc = { 64 ,64 }; SIZE sizeDest = { -64, 64 };
    pBack->Blt( pHoge, 0, 0, sizeDest, 0, sizeSrc );
  • 転送できるサイズに制限はありますか?
  • 65535を超えるサイズは転送できません。しかしこれは実際の描画時のサイズであって描画して欲しいサイズではありません。通常はクリッピング処理され適切にサイズが変更されます。例えばバッファのサイズ(クリッピング領域)が640×480で、10000×10000のサイズを転送する場合640×480にクリッピングされます。
  • Sepiaメソッドを使用しましたがセピアに変換できません。
  • 第6引数のColorにセピアカラーを指定しないとセピアに変換できません。 セピアカラーはマクロSDIB32GL_SEPIAとして定義されています。
  • DirectDrawを利用する利点は?
  • 結果を見る限りでは「ない」…と思います。あえていうならばフルスクリーンで動作できること…ですがWin32APIだけでもフルスクリーン化は可能なのでやはり意味はないです(汗
  • トランジションできません。
  • ルール画像の大きさが転送先と同じ大きさになっているか確認して下さい。
  • AlphaChannelMask系の関数とAlphaChannel系の関数の違いを詳しく教えて下さい。
  • 通常の方はαチャンネルが0、255の時もそのままα計算をしていますが、Maskのほうはαチャンネルが0の時、255の時に単純に描画するかしないかで描画を高速化しています。 キャラクターなどでαチャンネルが0、255が多いものはMask関数を推奨します。 Mask関数を使用しても高速に描画できない場合もあります。
  • Line系メソッドの太さは変更できないのですか?
  • できません。太さを変更したいのでしたら自前でラインの本数を増やして描画するなどで対応して下さい。
  • Ellipse系メソッドは枠だけの描画には対応していないのですか?
  • 今のところ塗りつぶししかできません。
  • Mosaicメソッドのブロックがサイズが大きくなるにつれてずれて表示されていきます。
  • 高速化のため、ブロックの左上座標の色を使用して塗りつぶしているためです。
  • 自前で凄い描画をしてみたいです。
  • GetScanLineメソッドなどで直接メモリにアクセスして凄い描画をして下さい。
  • ATLのCComPtr(スマートポインタ)は使えますか?
  • はい、使えます。
  • COMスマートポインタはクールに使えますか?
  • はい、クールに使えます。
  • そもそもスマートポインタって何さ?何がスマートなの?痩せてるの?もやしなの?おいしいの?
  • いや、そのスマートじゃなくて・・・、簡単に説明するとメモリの確保と解放を自動でやってくれるスマート(賢い)なポインタとだけ言っておきましょう。
  • SDIB32GLを使用するのにCOMの知識は必要ですか?
  • 深い知識は必要ありません。基本的な流れはDirextXのCOMの使い方とほぼ同じです。
  • DirectXのインターフェイスに似ているのはなぜですか?
  • DirectXっぽくしてみたかったからです。というか、COMだから似るのあたり前です。
  • 何か参考にしたソースコードなどはありますか?
  • buin2gou様開発のDelphi用グラフィックライブラリ、TABitmapのソースコードを参考に開発をさせていただきました。
  • ソースコードを改造したいのですが?
  • ソースコードに同封のlicense.txtを隅から隅まで読んで下さい。
  • もっと最適化できます!
  • 切実に教えて下さい。