LoadImageで読み込んだbmpの縦、横のサイズを取得するには?

解決


立直@一発屋  2007-02-18 22:20:08  No: 135348

LoadImageで読み込んだbmpの縦、横のサイズ取得方法をご教授願います。
用途はBitBltの引数にある縦、横のサイズを指定するためです。

いろいろサンプルコードを探したのですがBitBltの引数は固定値であったりピクチャボックスのサイズであったりして、ファイル読み込みした直のbmpの縦、横のサイズを取得するコードが見つかりませんでした。(ないはずはないと思って探したのですが・・・)

環境:VB6.0,win2000

------------------------------------------------
Dim dev_contxt As Long

dev_contxt = LoadImage(0, "G:\VB\テスト\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)

'この後がわかりません。

-----------------------------------------------


てふ  2007-02-19 00:08:13  No: 135349

戻り値がBITMAPINFOのHANDLEになっているから、それをVBで定義した
BITMAPINFOHEADER構造体の変数にCopyMemoryでコピーするなりして
直接WidthとHeightの値を見ればよいのでは?

参考URL
http://msdn2.microsoft.com/ja-jp/library/z5731wbz(VS.80).aspx
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/DirectX9_c/directx/htm/bitmapinfoheaderstructure.asp


立直@一発屋  2007-02-19 06:20:50  No: 135350

すばやい回答ありがとうございます。

ご教授いただいた方法で試してみましたがCopyMemoryで正常な値が取得できません。(幅、高さにマイナスの値が入ってりしています)

読み込んでいるtest.bmpはペイントで作成しているため正常なデータのはずなのですが。

★BITMAPINFO型をもうひとつ用意し、[pnt]の代わりに設定してみたところCopyMemoryは動作しておりますので[pnt]に設定している値が怪しいと思っております。

誠に申し訳ございませんが[pnt]の設定方法、使い方に問題があるかご確認願えますでしょうか?

-----------------------------------------------------------
Type BITMAPINFOHEADER
    biSize As Long              'ヘッダーのサイズ_
    biWidth As Long             '幅(ピクセル単位)
    biHeight As Long            '高さ(ピクセル単位)
    biPlanes As Integer         '常に1
    biBitCount As Integer       '1ピクセルあたりのカラービット数
    biCompression As Long       '圧縮方法
    biSizeImage As Long         'ピクセルデータの全バイト数
    biXPelsPerMeter As Long     '0または水平解像度
    biYPelsPerMeter As Long     '0または垂直解像度
    biClrUsed As Long           '通常は0
    biClrImportant As Long      '通常は0
End Type

Type BITMAPINFO
        bmiHeader As BITMAPINFOHEADER
'        bmiColors(255) As RGBQUAD
End Type
               ・
               ・
               ・

 Dim bmp_infoh As BITMAPINFO
 Dim lngBMP As Long
 Dim pnt As Long
 Dim alloc_hnd As Long
 
 lngBMP = LoadImage(0, "G:\VB\テスト\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
 
 alloc_hnd = GlobalAlloc(0, Len(lngBMP))
 pnt = GlobalLock(alloc_hnd)
 CopyMemory bmp_infoh, pnt, Len(bmp_infoh)★
-----------------------------------------------------------


てふ  2007-02-19 07:23:57  No: 135351

下記のようになるんじゃないでしょうか。

 lngBMP = LoadImage(0, "G:\VB\テスト\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
 
' alloc_hnd = GlobalAlloc(0, Len(lngBMP))  <---これは要らないですね
' pnt = GlobalLock(alloc_hnd)
 pnt = GlobalLock(lngBMP)  'ビットマップハンドルをロックして
 CopyMemory bmp_infoh, pnt, Len(bmp_infoh)    ’BITMAPINFOHEADERの中身をコピー
'この後、GlobalUnlockで後処理


てふ  2007-02-19 07:25:43  No: 135352

訂正

CopyMemory bmp_infoh, pnt, Len(bmp_infoh)    
↓こうした方がいいかも
CopyMemory infoh,ByVal pnt, Len(bmp_infoh)


立直@一発屋  2007-02-19 08:57:11  No: 135353

' alloc_hnd = GlobalAlloc(0, Len(lngBMP))  <---これは要らないですね
' pnt = GlobalLock(alloc_hnd)

→変な処理になっていますが、GlobalAllocを間に挟まないとGlobalLockの戻り値のハンドルが取得できない(0になってしまう)ため上記のような処理を入れました。
  MSDNのヘルプやいろんなサイトを見てみるとどうもGlobalLockの引数はGlobalXXXXといった関数の戻り値を渡してあげる必要があるようです。

  追加情報です。
  CopyMemory後のbmp_infohの値をデバッグで確認すると不定値(複数回確認するとそれぞれ値が異なる)になっておりました。pntのアドレスが不正なのは間違いないようです。
  この観点でもう少し調べてみます。


立直@一発屋  2007-02-19 09:03:12  No: 135354

すいません。レス漏れがありました。

>CopyMemory bmp_infoh, pnt, Len(bmp_infoh)    
>↓こうした方がいいかも
>CopyMemory infoh,ByVal pnt, Len(bmp_infoh)

→変更しましたが特に変化なしでした。
  #第一引数はbmp_infohで確認しています。


てふ  2007-02-19 10:27:53  No: 135355

ほんとですね。
LoadImageで取得したビットマップハンドルをロックしようとすると
GlobalAllocがNULLを返していますね。
試さずに回答していました。

原因はちょっと思いつかないので他の有識者の回答をまってください。すみません。

ただ、ビットマップファイルの画像サイズを取得したいだけなら
以下のようなやり方でもできます。(ビットマップファイルを直接読む)

  Dim hBmp    As Long
  Dim stBmi   As BITMAPINFOHEADER
  Dim lPtr    As Long
  Dim bytB(13) As Byte
  Dim intF    As Integer
  
  
  intF = FreeFile
  Open "ビットマップファイル名" For Binary As #intF
  Get #intF, , bytB   'ファイルヘッダを読み飛ばす
  Get #intF, , stBmi  'BITMAPINFOHEADERを取得
  Close #intF
  'サイズをプリント
  Debug.Print stBmi.biWidth, stBmi.biHeight

参考URL
http://www.kk.iij4u.or.jp/~kondo/bmp/


Blue  2007-02-19 18:18:11  No: 135356

GetObjectで取得できないでしょうか?

Option Explicit

Private Declare Function LoadImage Lib "User32.dll" Alias "LoadImageA" _
    (ByVal hinst As Long, ByVal lpszName As String, ByVal uType As Long, _
     ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal fuLoad As Long) As Long
Private Const IMAGE_BITMAP As Long = 0&
Private Const LR_LOADFROMFILE As Long = 16&

Private Declare Function DeleteObject Lib "Gdi32.dll" (ByVal hObject As Long) As Long
    
Private Type BITMAP
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type

Private Declare Function GetObject Lib "Gdi32.dll" Alias "GetObjectA" _
    (ByVal hgdiobj As Long, ByVal cbBuffer As Long, ByRef lpvObject As BITMAP) As Long

Public Sub Test()
    Dim hBitmap As Long
    Dim bmp As BITMAP
    
    hBitmap = LoadImage(0&, "G:\VB\テスト\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
    If hBitmap <> 0 Then
        If GetObject(hBitmap, LenB(bmp), bmp) <> 0 Then
            MsgBox "高さ:" & bmp.bmHeight & vbCrLf & "横幅:" & bmp.bmWidth
        End If
        DeleteObject hBitmap
    End If
End Sub

>戻り値がBITMAPINFOのHANDLEになっているから
これはどこの情報でしょうか?


Blue  2007-02-19 20:17:14  No: 135357

ちなみに、LoadImageではなく、VBのLoadPictureを使えば、
PictureオブジェクトのWidth/HeightプロパティからHiMetric単位の値が取れます。
過去ログ:http://madia.world.coocan.jp/vb/vb_bbs/200501_05010008.html

ピクセル単位に変換するには
http://www.geocities.co.jp/SiliconValley/4334/unibon/asp/getimagesize.html
を参考にしてください。


立直@一発屋  2007-02-20 06:47:34  No: 135358

Blueさん、てふさん>
ご回答ありがとうございます。
GetObjectで取得できましたので解決とさせていただきます。

親切にご回答いただきありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加