月刊ソフト作り!
Make The Software For VisualBasic
『ビットマップビューアを作る(その1)』
2002.Apr.17
Presented by kouta_y
感想等は掲示板、苦情はメールへ。
Windows標準画像のBMP(ビットマップ)用ビューアを作ります
ビットマップとは
数多くある画像形式の1つです。
ウィンドウズでは一番標準的な画像形式ですが、インターネットでは一番使われない画像形式でもあります。
ビットマップファイルとは、簡単に言えばRGBパタンをそのまま格納しているものです。
それ以外の画像形式は大抵「圧縮」をしており、ファイルサイズをできるだけ小さくするような工夫が凝らされています。
しかし画像の圧縮というのは、ほとんど「非可逆圧縮」と呼ばれる圧縮方法で、例えばJPEG形式で圧縮率を高くして保存してしまうと画像が乱れてしまいます。
その代わりファイルサイズは極小となります。
逆にビットマップの場合、RGBパタンをそのまま保存しているので、より鮮明な画像表示が可能となります。
その代償として、ファイルサイズは大きくなります。
インターネットでは、サーバーの容量制限やダウンロードする人の為などの理由で「ファイルサイズはなるべく小さく」という心がけがされています。(例外を除き)
なのでいくら画像が綺麗だと言っても、ファイルサイズの大きいビットマップ画像はオンラインでは嫌われています。
DIBとDDB
さて、これを知らなければビットマップは語れません。
ビットマップには大きく分けて2つの形式があり、それがDIBとDDBです。
しかし今回の「その1」では、これについては深く説明しません。
「語れない」と言ってるくせに「説明しない」とはどういう事だ!
と憤慨するかもしれませんが、正直DIBとDDBを理解するのはとても大変です。
筆者も両者の違いが分かるまで数ヶ月を要しました。
1度の説明でいきなり理解は出来ません。
何度か説明を読んでみて、少しずつ理解をしていってください。
いっぺんに理解しようとすると、必ず挫折します。
すこーしずつ分かっていけば、それで十分です。
ビットマップの形式さえ理解できれば、他の画像形式も怖くはありません。
簡単に説明をします。
これ以降もDIB、DDBという言葉を使いますが、これは2度目以降に読む場合の為です。
最初はなんとなく分かってもらえれば結構です。
DIBとは
Device Independent Bitmap
の略で、「デバイスに依存しないビットマップ」という意味で「デバイス独立ビットマップ」とも呼ばれます。
デバイスとは直訳で「装置」という意味ですが、この場合「ディスプレイ」や「プリンタ」など実際に表示させる相手の事をさします。
その「装置」もしくは「対象物」に依存をしないという事です。
DIBの構造はBITMAPINFO構造体で表します。
'DIB情報ヘッダ Public Type BITMAPINFOHEADER biSize As Long ' 構造体のサイズ biWidth As Long ' 画像の横幅 biHeight As Long ' 画像の高さ biPlanes As Integer ' プレーン数 biBitCount As Integer ' ビット数 biCompression As Long ' 圧縮コード(RLE圧縮) biSizeImage As Long ' 画像のサイズ(バイト) biXPelsPerMeter As Long ' 水平解像度 biYPelsPerMeter As Long ' 垂直解像度 biClrUsed As Long ' カラーテーブルの数 biClrImportant As Long ' 重要な色の数(0~biClrImportantまで) End Type '1ピクセルの色 Public Type RGBQUAD rgbBlue As Byte ' 青 rgbGreen As Byte ' 緑 rgbRed As Byte ' 赤 rgbReserved As Byte ' リザーブ End Type 'DIB情報 Public Type BITMAPINFO bmiHeader As BITMAPINFOHEADER bmiColors() As RGBQUAD End Type |
今のウィンドウズパソコンの拡張子.bmpのファイルはこの構造、つまりDIB形式でファイルへ保存されます。
DDBとは
Device Dependent Bitmap
の略で、「デバイスに依存するビットマップ」という意味で「デバイス依存ビットマップ」とも呼ばれます。
ディスプレイなどのデバイスに依存をします。
互換があるとも言います。
「依存をする」というのは、ディスプレイなどのデバイスの色数や解像度によってビットマップを表示させるという事です。
DDBの構造はBITMAP構造体で表します。
'DDBの情報 Public Type BITMAP bmType As Long ' タイプは0 bmWidth As Long ' 画像の横幅 bmHeight As Long ' 画像の高さ bmWidthBytes As Long ' 画像の1行のバイト数 bmPlanes As Integer ' プレーン数 bmBitsPixel As Integer ' ビット数 bmBits As Long ' ビットマップパタンへのポインタ End Type |
DDBはプログラム上からビットマップを表示させる場合に使います。
BitBlt関数などはDDBを操作します。
作る
では、よく分からない説明は終わりにして早速ビットマップを表示させるものを作ってみましょう。
何を作るかと言うと、ファイルからビットマップを直接読み込みウィンドウに表示させるというものです。
つまりDIBを直接ウィンドウに描画します。
まずプロジェクトは「標準EXE」を選び、フォームのプロパティを以下の様に設定します。
プロジェクトの名前は「MyView」という名前にします。
Form1 | |
AutoRedraw | True |
BorderStyle | 1 - 固定(実線) |
MaxButton | False |
ScaleMode | 3 - ピクセル |
Public Declare Function SetDIBitsToDevice Lib "gdi32" ( _ ByVal hDC As Long, _ ByVal X As Long, _ ByVal Y As Long, _ ByVal dx As Long, _ ByVal dy As Long, _ ByVal SrcX As Long, _ ByVal SrcY As Long, _ ByVal Scan As Long, _ ByVal NumScans As Long, _ Bits As Any, _ BitsInfo As Any, _ ByVal wUsage As Long _ ) As Long |
この関数はDIBを直接デバイスに描画します。
hDC、転送先のデバイスコンテキストハンドルを指定します。
X,Y、転送先の左上隅XとYの座標。
dx,dy、転送先の横幅と高さ。
SrcX,SrcY、転送元の左上隅XとYの座標
Scan、最初の走査線を指定します。走査線とは行の事です。
NumScans、走査線の数を指定します。1度に全て描画する場合は高さを指定します。
Bits、ビットマップパタンへのポインタを指定します。
BitsInfo、DIBの情報が入ったBITMAPINFO構造体を指定します。
wUsage、カラー情報のフラグを指定します。RGBパタンならDIB_RGB_COLORSを、パレットインデックスならDIB_PAL_COLORSを指定します。
コードは
今回はイベントは一切ハンドラしません。
全てスタートアッププロージャに記述します。
表示させるビットマップファイルは引数として貰います。
ではSub Mainのコードです。
Public Sub Main() Dim BFH As BITMAPFILEHEADER Dim BIH As BITMAPINFOHEADER Dim Bit() As Byte Dim Cmd As String Dim Argv() As String Dim Argc As Long Dim NO As Integer Cmd = Command$() Argc = ArgvArgc(Cmd, Argv) If Argc <= 0 Then Exit Sub NO = FreeFile() Open Argv(0) For Binary As #NO Get #NO, , BFH If BFH.bfType <> BM Then ' ビットマップではない MsgBox "形式エラー" Close Exit Sub End If Get #NO, , BIH If BIH.biBitCount < 16 Then ' 16Bit未満 MsgBox "色数エラー" Close Exit Sub End If ' ReDim Bit(BIH.biSizeImage - 1) As Byte ReDim Bit(BIH.biHeight * BIH.biWidth * 4) As Byte Get #NO, , Bit Close Load Form1 Form1.Width = (BIH.biWidth * Screen.TwipsPerPixelX) + _ (Form1.Width - (Form1.ScaleWidth * Screen.TwipsPerPixelX)) ' Twipに変換 Form1.Height = (BIH.biHeight * Screen.TwipsPerPixelY) + _ (Form1.Height - (Form1.ScaleHeight * Screen.TwipsPerPixelY)) ' Twipに変換 Form1.Caption = Argv(0) 'DIBを転送 Call SetDIBitsToDevice(Form1.hDC, 0, 0, BIH.biWidth, BIH.biHeight, _ 0, 0, 0, BIH.biHeight, Bit(0), BIH, 0) Form1.Show End Sub |
まず受け取った引数の解析をします。
サンプルでは第一引数のみ使用します。
次に受け取ったパスを開き、BITMAPFILEHEADER構造体を取得します。
その後、BITMAPINFOHEADER構造体を取得、続けてビットパタンを取得しています。
サンプルでは16ビット未満のビットマップは表示させません。8ビット(256色)以下のビットマップの場合コードが難しくなる為、簡易化させる為です。
ファイルを読み込んだら、メインフォームをロードします。
まだ表示はされません。
次にフォームの横幅と高さを設定します。
ビットマップ画像の大きさに合わせます。
Width、Heightプロパティの単位はTwipの為、ピクセルをTwip単位に変換すると同時に、フォームのクライアント領域も計算しています。
SetDIBitsToDevice関数で、読み込んだDIBを渡してフォームに描画します。
最後にフォームを表示させます。
引数の解析
最初に呼び出しているArgvArgc関数は自作関数です。
コードはサンプルプロジェクトを見てください。
終わり
今回はDDBには一切触れていません。
DIBを直接描画しているので、デバイスによって色が変わるなどといった現象もおきません。
次回は256色なども表示できるものを作ります。
今回のサンプルプロジェクト
vb06.lzh(6.94KB)