|
■No85458 (魔界の仮面弁士 さん) に返信
サンプルコードをありがとうございます。
とりあえず、コンパイルエラーをとるために、以下のように手直しして動かしてみました。
'---宣言
'BITMAPINFO構造体
Private Structure BITMAPINFO
Dim bmiHeader As BITMAPINFOHEADER
Dim bmiColors() As RGBQUAD
End Structure
'---本体
Private Sub Viewdds(ByVal temp_dds_name As String)
Dim ret As Integer
Dim BitMapMemoryHandle As Long
Dim BitMapInf As Long
Dim LocalMemoryBMP As Long
Dim LocalMemoryInf As Long
Dim BitMapHeader As BITMAPINFOHEADER
Dim bpi As BITMAPINFO
Dim info As PICTUREINFO
ret = GetPictureInfo(temp_dds_name, temp_dds_name.Length, 0, info) '画像の展開
ret = GetPicture(temp_dds_name, 0, 0, BitMapInf, BitMapMemoryHandle, 0, 0) '画像の展開
LocalMemoryBMP = LocalLock(BitMapMemoryHandle) 'メモリのロック
LocalMemoryInf = LocalLock(BitMapInf)
MoveMemory(BitMapHeader, LocalMemoryInf, Len(BitMapHeader)) 'メモリ移動
Dim bmp As Bitmap = Nothing
Dim dataSize As Integer = info.width * info.height
Select Case info.colorDepth
Case 32
bmp = New Bitmap(info.width, info.height, PixelFormat.Format32bppArgb)
dataSize *= 4
Case 24
bmp = New Bitmap(info.width, info.height, PixelFormat.Format24bppRgb)
dataSize *= 3
Case 16
bmp = New Bitmap(info.width, info.height, PixelFormat.Format16bppRgb565)
dataSize *= 3
Case 8
bmp = New Bitmap(info.width, info.height, PixelFormat.Format8bppIndexed)
'dataSize *= 1
Case 4
bmp = New Bitmap(info.width, info.height, PixelFormat.Format4bppIndexed)
dataSize \= 2
Case Else
bmp = New Bitmap(info.width, info.height, PixelFormat.Format1bppIndexed)
dataSize \= 8
End Select
'カラーパレットを持つ PixelFormat 形式の場合は、
'RGBQUAD(パレット情報)も転写しておく
If (info.colorDepth = 1) Or (info.colorDepth = 4) Or (info.colorDepth = 8) Then
ReDim bpi.bmiColors(255)
MoveMemory(bpi, LocalMemoryInf, Len(bpi)) 'メモリ移動
Dim cp As System.Drawing.Imaging.ColorPalette
cp = bmp.Palette
Dim i As Long
For i = 0 To cp.Entries.Length - 1
'※bpi は、getPicture API で得た BITMAPINFO 構造体
cp.Entries(i) = Color.FromArgb(bpi.bmiColors(i).rgbRed, bpi.bmiColors(i).rgbGreen, bpi.bmiColors(i).rgbBlue)
Next
bmp.Palette = cp
End If
'※bmpData は getPicture で得たビットマップデータ
Dim data(Math.Max(0, dataSize - 1)) As Byte
Marshal.Copy(Marshal.ReadIntPtr(LocalMemoryBMP), data, 0, data.Length)
'Bitmap 本体を表す配列のデータを Scan0 に転送
Dim bitmapdata As BitmapData = bmp.LockBits(New Rectangle(New Point(), bmp.Size), ImageLockMode.ReadWrite, bmp.PixelFormat)
Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length)
bmp.UnlockBits(bitmapdata)
LocalUnlock(BitMapMemoryHandle) 'メモリロック解除
LocalUnlock(BitMapInf)
LocalFree(BitMapMemoryHandle) 'メモリ開放
LocalFree(BitMapInf)
'出力イメージを上下反転
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
'作成した画像を表示する
Picture1.Image = bmp
End Sub
「Marshal.Copy(Marshal.ReadIntPtr(LocalMemoryBMP), data, 0, data.Length)」
ここで「保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」エラーとなってしまいました。
data.Lengthの値は「&H100000」でした。
> nuget で "dds" を検索すると、CSharpImageLibrary などが
> ヒットしましたが、それも駄目なんですね。
> (とはいえ、spi も DLL なのでは…)
うう、そうなんですが、いろいろ事情が・・・
> その点に関しては、当初の SetDIBits 案でも同じだと思います。
先に書いたSetDIBitsでは動作せず「CInt(CObj(Picture1.Image))」が問題ありそうと、いろいろ教えていただいたものの、どう修正していいものやら分からなかったもので。面目ありません。
一応、下記のようにつくってはみたのですが、結局ダメでした。
Using gp As Graphics = Picture1.CreateGraphics 'フォームのGraphicsを作成
Dim hDC As IntPtr = gp.GetHdc() 'そのデバイスコンテキストを取得
Dim bmp As New Bitmap(BitMapHeader.biWidth, BitMapHeader.biHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
Dim _bmp As System.IntPtr
_bmp = bmp.GetHbitmap
ret = SetDIBits(hDC, _bmp, 0, Picture1.Height, LocalMemoryBMP, LocalMemoryInf, 0) 'ビットマップ表示
Picture1.Image = Image.FromHbitmap(_bmp)
Picture1.Refresh() 'ピクチャーボックス更新
gp.ReleaseHdc()
End Using
|