Discussion:
LoadImage & LR_CREATEDIBSECTION
(too old to reply)
R.Wieser
2004-04-10 19:17:16 UTC
Permalink
Hello All,

I'm trying to make sense of a few GDI-functions, but I'm not having much
luck with it ...

The endpoint of what I'm trying to do is to load a BMP, cot some part out of
it, and save that part to another file. This all while retaining the
origional image's color-depth & colors.

I've found an exmple that let's me make a snapshot from the screen, store it
into a DIB, and let's me save the DIB to a file. It works o.k.

Now I thought I could try to load an image, and save that image to another
file. I took the "LoadImage" function, and provided it (among others) the
LR_CREATEDIBSECTION -flag. With it I was/am thinking that the result is a
DIB that I can, with a previously written routine, directly save to file.

Nothing is less true .... And I have no idea why (none of the provided info
on the Web sheds any light on it).

Has anyone an idea what's going on / what I should do ?

Any help is appriciated.

Regards,
Rudy Wieser
Mike D Sutton
2004-04-10 23:47:05 UTC
Permalink
Post by R.Wieser
I'm trying to make sense of a few GDI-functions, but I'm not having much
luck with it ...
The endpoint of what I'm trying to do is to load a BMP, cot some part out of
it, and save that part to another file. This all while retaining the
origional image's color-depth & colors.
I've found an exmple that let's me make a snapshot from the screen, store it
into a DIB, and let's me save the DIB to a file. It works o.k.
Now I thought I could try to load an image, and save that image to another
file. I took the "LoadImage" function, and provided it (among others) the
LR_CREATEDIBSECTION -flag. With it I was/am thinking that the result is a
DIB that I can, with a previously written routine, directly save to file.
Nothing is less true .... And I have no idea why (none of the provided info
on the Web sheds any light on it).
Has anyone an idea what's going on / what I should do ?
First off, make sure you're also specifying the LR_LOADFROMFILE flag as the flags and IMAGE_BITMAP for the type (obviously also make
sure that the file name you're giving it is also valid .BMP file.)
At this point you should have a valid DIBSection GDI object which you can extract the data from and write to disk as you require, if
you want to check that the handle you have is a valid object then use the GetObject() API call on it:

'***
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" ( _
ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long

Private Type Bitmap ' 24 bytes
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type

...

Dim hBMP As Long
Dim BMInf As Bitmap

hBMP = LoadImage( ... )
If (GetObject(hBMP, Len(BMInf), BMInf)) Then
With BMInf
Debug.Print "Size: " & .bmWidth & " * " & .bmHeight & " * " & .bmBitsPixel
Debug.Print "Valid plane count: " & CBool(.bmPlanes = 1)
Debug.Print "Type: " & IIf(.bmBits = 0, "DDB", "DIBSection")
End With
End If
'***

If this all checks out ok and you still can't save the image out to disk then it sounds to me like you've got a bad Bitmap I/O
routine. My guess would be you've got a palette which it's not taking into account perhaps? Is the Bitmap compressed
(RLE/Bit-fields?)
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-11 10:21:56 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@tk2msftngp13.phx.gbl...

Hello Mike,

[Snip]
Post by Mike D Sutton
Post by R.Wieser
Now I thought I could try to load an image, and save that
image to another file. I took the "LoadImage" function,
and provided it (among others) the
LR_CREATEDIBSECTION -flag. With it I was/am
thinking that the result is a DIB that I can, with a previously
written routine, directly save to file.
First off, make sure you're also specifying the
LR_LOADFROMFILE flag as the flags and
IMAGE_BITMAP for the type (obviously also make sure
that the file name you're giving it is also valid .BMP file.)
All done :-)
Post by Mike D Sutton
At this point you should have a valid DIBSection GDI
object which you can extract the data from and write to
disk as you require, if you want to check that the handle
you have is a valid object then use the GetObject() API
[Snip code-example]

Your code-example showed a GetObject() -call. It did make me realize that
the DIB-section result from the LoadImage could well be non-directly
accessible (aka : a Handle), and has to be "copied" into an allocated block
of memory before being able to save it to file ...

I'm quite sure that that is where I went wrong ...
Post by Mike D Sutton
Hope this helps,
It does, it does !

Thanks for your help :-)

Regards,
Rudy Wieser
Mike D Sutton
2004-04-11 10:57:56 UTC
Permalink
Post by R.Wieser
Your code-example showed a GetObject() -call. It did make me realize that
the DIB-section result from the LoadImage could well be non-directly
accessible (aka : a Handle), and has to be "copied" into an allocated block
of memory before being able to save it to file ...
There shouldn't really be any reason why you wouldn't be able to access the returned DIBSection object exclusively however it may
have something to do with the way your Bitmap I/O routine is operating. Generally a few calls to GetDIBits() and a file header is
all that's required to write a .BMP file from a DIBSection since they're such similar structures.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-11 15:45:32 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
#***@TK2MSFTNGP12.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
Your code-example showed a GetObject() -call.
It did make me realize that the DIB-section result
from the LoadImage could well be non-directly
accessible (aka : a Handle), and has to be "copied"
into an allocated block of memory before being
able to save it to file ...
There shouldn't really be any reason why you wouldn't
be able to access the returned DIBSection object
exclusively however it may have something to do with
the way your Bitmap I/O routine is operating.
Generally a few calls to GetDIBits() and a file header
is all that's required to write a .BMP file from a
DIBSection since they're such similar structures.
Actually, I'm going quite gaga here ... :-(

All I'm (currently) trying to do is to :
1) Load an image from file in such a way that I can draw on it (using
standard API-functions)
2) Draw on it (have not even reached this stage yet :-\ )
3) Save the (altered) image to a file

I'm quite sure that I can load & save an image, but only for specific
circumstances. Maybe my problem is that I would like to have my routines
generic, so I can save *any* image (mostly loaded into a DC) to file.

Just to name something I'm bumping against : I've loaded an image from a
file as normal, and as a DIB-section. For some reason I can get a palette
from the DC if it's contents are loaded as a DIB-section, but not when
loaded as a bitmap. Why ? A bitmap (<= 8 bpc) needs a palette too,
otherwise it's colors go AWOL ...

And something I do not understand about DIB-sections : If a DIB contains a
BITMAPINFOHEADER (including a palette if relevant), why does a DIB-Section
have this information too ? Why does a DIB-Section have a BITMAPHEADER
when all of it's info is allso stored into the BITMAPINFOHEADER just below
the BITMAPHEADER ? In the light of this, what justifies it's existense ?
It just does not make sense ...
Post by Mike D Sutton
Hope this helps,
Your help sure does, but I currently do not seem to be able to understand
the fine points of GDI-programming, and it is frustrating. Even something
simple as loading-and-saving an image goes beyond me :-\

Regards,
Rudy Wieser
Mike D Sutton
2004-04-11 19:17:47 UTC
Permalink
Post by R.Wieser
Actually, I'm going quite gaga here ... :-(
1) Load an image from file in such a way that I can draw on it (using
standard API-functions)
2) Draw on it (have not even reached this stage yet :-\ )
3) Save the (altered) image to a file
I'm quite sure that I can load & save an image, but only for specific
circumstances. Maybe my problem is that I would like to have my routines
generic, so I can save *any* image (mostly loaded into a DC) to file.
Just to name something I'm bumping against : I've loaded an image from a
file as normal, and as a DIB-section. For some reason I can get a palette
from the DC if it's contents are loaded as a DIB-section, but not when
loaded as a bitmap. Why ? A bitmap (<= 8 bpc) needs a palette too,
otherwise it's colors go AWOL ...
A DIB/DIBSection is device independent and stores it's custom palette as part of it's header structure, a DDB is device dependant
and is assumed to use the system palette. If it has it's own palette then a separate GDI palette object must be created, filled and
selected into the same DC as the DDB for it to be used - LoadImage() does not do this for you so if you want to load a paletted
image and keep the palette intact then use the LR_CREATEDIBSECTION flag.
Post by R.Wieser
And something I do not understand about DIB-sections : If a DIB contains a
BITMAPINFOHEADER (including a palette if relevant), why does a DIB-Section
have this information too ? Why does a DIB-Section have a BITMAPHEADER
when all of it's info is allso stored into the BITMAPINFOHEADER just below
the BITMAPHEADER ? In the light of this, what justifies it's existense ?
It just does not make sense ...
A DIB is really a rarely used creature since it is nothing more than a chunk of memory containing a header followed by the bitmap
data, often when people (including myself at times) write DIB they actually mean DIBSection.
A DIBSection is an encapsulation of a DIB into a GDI object which can be used with the rest of the GDI infrastructure allowing
drawing to be performed in a device independent manor. The BITMAPINFO structure is always present with a DIB or DIBSection but
since it has a dynamic array for the palette, non-paletted images (excluding for the moment bit-fields compressed images) are not
required to store this and so often to save space developers just reference the BITMAPINFOHEADER structure directly rather than
through the BITMAPINFO (the system doesn't care, it's only a pointer to some memory at the end of the day.)
Post by R.Wieser
Your help sure does, but I currently do not seem to be able to understand
the fine points of GDI-programming, and it is frustrating. Even something
simple as loading-and-saving an image goes beyond me :-\
Try this:

'***
Private Declare Function LoadImage Lib "User32.dll" Alias "LoadImageA" ( _
ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, _
ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
Private Declare Function GetObject Lib "GDI32.dll" Alias "GetObjectA" ( _
ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long
Private Declare Function DeleteObject Lib "GDI32.dll" ( _
ByVal hObject As Long) As Long
Private Declare Function GetDIBits Lib "GDI32.dll" (ByVal aHDC As Long, _
ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, _
ByRef lpBits As Any, ByRef lpBI As BitmapInfo8, ByVal wUsage As Long) As Long
Private Declare Function GetDC Lib "User32.dll" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "User32.dll" ( _
ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Declare Function CreateCompatibleDC Lib "GDI32.dll" ( _
ByVal hDC As Long) As Long
Private Declare Function SelectObject Lib "GDI32.dll" ( _
ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "GDI32.dll" ( _
ByVal hDC As Long) As Long

Private Type Bitmap ' 24 bytes
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type

Private Type BitmapFileHeader ' 14 bytes
bfType As Integer
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type

Private Type BitmapInfoHeader ' 40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type

Private Type BitmapInfo8 ' 1064 bytes
bmiHeader As BitmapInfoHeader
bmiColors(255) As Long
End Type

Private Const IMAGE_BITMAP As Long = &H0
Private Const LR_LOADFROMFILE As Long = &H10
Private Const LR_CREATEDIBSECTION As Long = &H2000
Private Const BI_BITFIELDS As Long = &H3

Private Sub Form_Load()
Dim hBMP As Long, hOldBMP As Long
Dim hDC As Long

SET FILE PATH'S HERE THEN REMOVE THIS LINE
Const ImgPath As String = "X:\Path\SrcFile.bmp"
Const SavePath As String = "X:\Path\DestFile.bmp"

' Attempt to load this file from disk
hBMP = LoadImage(App.hInstance, ImgPath, IMAGE_BITMAP, 0, 0, _
LR_LOADFROMFILE Or LR_CREATEDIBSECTION)

If (hBMP) Then ' Loaded ok, create a DC stick the Bitmap into it
hDC = CreateCompatibleDC(0)
hOldBMP = SelectObject(hDC, hBMP)

' Perform any drawing to hDC now

Call SelectObject(hDC, hOldBMP)
Call DeleteDC(hDC)

' Attempt to save Bitmap back out to disk
If (Not SaveDIB(hBMP, SavePath)) Then
Debug.Print "Error saving """ & SavePath & """"
End If

' Clean up
Call DeleteObject(hBMP)
Else ' Something went wrong during loading
Debug.Print "Error loading """ & ImgPath & """"
End If
End Sub

Private Function SaveDIB(ByVal inDIB As Long, ByRef inPath As String) As Boolean
Dim BMinf As Bitmap
Dim DIBHead As BitmapInfo8
Dim NumCols As Long
Dim DeskDC As Long
Dim BMData() As Long, DataLen As Long
Dim FileHead As BitmapFileHeader
Dim FNum As Integer
Dim WritePal As Long
Dim FileSize As Long

If (GetObject(inDIB, Len(BMinf), BMinf) = 0) Then Exit Function
If (BMinf.bmBits = 0) Then Exit Function ' Only working with DIBSection's

' Get a reference DC to work with
DeskDC = GetDC(0)

' Set Bitmap info header size
DIBHead.bmiHeader.biSize = Len(DIBHead.bmiHeader)

' Attempt to read DIBSection header
If (GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)) Then
If (DIBHead.bmiHeader.biBitCount <= 8) Then
NumCols = DIBHead.bmiHeader.biClrUsed ' Read palette
If (NumCols = 0) Then NumCols = 2 ^ DIBHead.bmiHeader.biBitCount
Call GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)
ElseIf (DIBHead.bmiHeader.biCompression) Then
If (DIBHead.bmiHeader.biCompression = BI_BITFIELDS) Then
NumCols = 3
Else ' Don't support RLE compressed images
Call ReleaseDC(0, DeskDC)
Exit Function
End If
End If

' Create image data buffer
DataLen = DIBHead.bmiHeader.biSizeImage \ 4
ReDim BMData(DataLen - 1) As Long

' Read image data
Call GetDIBits(DeskDC, inDIB, 0, _
DIBHead.bmiHeader.biHeight, BMData(0), DIBHead, 0)
DIBHead.bmiHeader.biClrUsed = NumCols

With FileHead
.bfType = &H4D42 ' Bitmap magic cookie; ASCII "BM"
.bfOffBits = Len(FileHead) + Len(DIBHead.bmiHeader) + (NumCols * 4)
.bfSize = DIBHead.bmiHeader.biSizeImage + .bfOffBits
End With

On Error Resume Next ' Check to see if the file already exists
FileSize = CBool(FileLen(inPath) + 1)
On Error GoTo 0

' If so, kill it
If (FileSize) Then Call Kill(inPath)

FNum = FreeFile() ' Get a free file handle
Open inPath For Binary Access Write Lock Read Write As #FNum
Put #FNum, , FileHead ' Write file header
Put #FNum, , DIBHead.bmiHeader ' Write Bitmap info header

If (NumCols) Then ' Write palette
For WritePal = 0 To NumCols - 1
Put #FNum, , DIBHead.bmiColors(WritePal)
Next WritePal
End If

Put #FNum, , BMData() ' Write image data
Close #FNum

' Return true
SaveDIB = True
End If

Call ReleaseDC(0, DeskDC)
End Function
'***

I've tested this with 1, 4, 8, 15 (Bit-fields), 16, 24 and 32-bit images and it seems to work ok here.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
Mike D Sutton
2004-04-11 20:17:03 UTC
Permalink
[Re-post; the first one didn't seem to go through]
Post by R.Wieser
Actually, I'm going quite gaga here ... :-(
1) Load an image from file in such a way that I can draw on it (using
standard API-functions)
2) Draw on it (have not even reached this stage yet :-\ )
3) Save the (altered) image to a file
I'm quite sure that I can load & save an image, but only for specific
circumstances. Maybe my problem is that I would like to have my routines
generic, so I can save *any* image (mostly loaded into a DC) to file.
Just to name something I'm bumping against : I've loaded an image from a
file as normal, and as a DIB-section. For some reason I can get a palette
from the DC if it's contents are loaded as a DIB-section, but not when
loaded as a bitmap. Why ? A bitmap (<= 8 bpc) needs a palette too,
otherwise it's colors go AWOL ...
A DIB/DIBSection is device independent and stores it's custom palette as part of it's header structure, a DDB is device dependant
and is assumed to use the system palette. If it has it's own palette then a separate GDI palette object must be created, filled and
selected into the same DC as the DDB for it to be used - LoadImage() does not do this for you so if you want to load a paletted
image and keep the palette intact then use the LR_CREATEDIBSECTION flag.
Post by R.Wieser
And something I do not understand about DIB-sections : If a DIB contains a
BITMAPINFOHEADER (including a palette if relevant), why does a DIB-Section
have this information too ? Why does a DIB-Section have a BITMAPHEADER
when all of it's info is allso stored into the BITMAPINFOHEADER just below
the BITMAPHEADER ? In the light of this, what justifies it's existense ?
It just does not make sense ...
A DIB is really a rarely used creature since it is nothing more than a chunk of memory containing a header followed by the bitmap
data, often when people (including myself at times) write DIB they actually mean DIBSection.
A DIBSection is an encapsulation of a DIB into a GDI object which can be used with the rest of the GDI infrastructure allowing
drawing to be performed in a device independent manor. The BITMAPINFO structure is always present with a DIB or DIBSection but
since it has a dynamic array for the palette, non-paletted images (excluding for the moment bit-fields compressed images) are not
required to store this and so often to save space developers just reference the BITMAPINFOHEADER structure directly rather than
through the BITMAPINFO (the system doesn't care, it's only a pointer to some memory at the end of the day.)
Post by R.Wieser
Your help sure does, but I currently do not seem to be able to understand
the fine points of GDI-programming, and it is frustrating. Even something
simple as loading-and-saving an image goes beyond me :-\
Try this:

'***
Private Declare Function LoadImage Lib "User32.dll" Alias "LoadImageA" ( _
ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, _
ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
Private Declare Function GetObject Lib "GDI32.dll" Alias "GetObjectA" ( _
ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long
Private Declare Function DeleteObject Lib "GDI32.dll" ( _
ByVal hObject As Long) As Long
Private Declare Function GetDIBits Lib "GDI32.dll" (ByVal aHDC As Long, _
ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, _
ByRef lpBits As Any, ByRef lpBI As BitmapInfo8, ByVal wUsage As Long) As Long
Private Declare Function GetDC Lib "User32.dll" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "User32.dll" ( _
ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Declare Function CreateCompatibleDC Lib "GDI32.dll" ( _
ByVal hDC As Long) As Long
Private Declare Function SelectObject Lib "GDI32.dll" ( _
ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "GDI32.dll" ( _
ByVal hDC As Long) As Long

Private Type Bitmap ' 24 bytes
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type

Private Type BitmapFileHeader ' 14 bytes
bfType As Integer
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type

Private Type BitmapInfoHeader ' 40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type

Private Type BitmapInfo8 ' 1064 bytes
bmiHeader As BitmapInfoHeader
bmiColors(255) As Long
End Type

Private Const IMAGE_BITMAP As Long = &H0
Private Const LR_LOADFROMFILE As Long = &H10
Private Const LR_CREATEDIBSECTION As Long = &H2000
Private Const BI_BITFIELDS As Long = &H3

Private Sub Form_Load()
Dim hBMP As Long, hOldBMP As Long
Dim hDC As Long

SET FILE PATH'S HERE THEN REMOVE THIS LINE
Const ImgPath As String = "X:\Path\SrcFile.bmp"
Const SavePath As String = "X:\Path\DestFile.bmp"

' Attempt to load this file from disk
hBMP = LoadImage(App.hInstance, ImgPath, IMAGE_BITMAP, 0, 0, _
LR_LOADFROMFILE Or LR_CREATEDIBSECTION)

If (hBMP) Then ' Loaded ok, create a DC stick the Bitmap into it
hDC = CreateCompatibleDC(0)
hOldBMP = SelectObject(hDC, hBMP)

' Perform any drawing to hDC now

Call SelectObject(hDC, hOldBMP)
Call DeleteDC(hDC)

' Attempt to save Bitmap back out to disk
If (Not SaveDIB(hBMP, SavePath)) Then
Debug.Print "Error saving """ & SavePath & """"
End If

' Clean up
Call DeleteObject(hBMP)
Else ' Something went wrong during loading
Debug.Print "Error loading """ & ImgPath & """"
End If
End Sub

Private Function SaveDIB(ByVal inDIB As Long, ByRef inPath As String) As Boolean
Dim BMinf As Bitmap
Dim DIBHead As BitmapInfo8
Dim NumCols As Long
Dim DeskDC As Long
Dim BMData() As Long, DataLen As Long
Dim FileHead As BitmapFileHeader
Dim FNum As Integer
Dim WritePal As Long
Dim FileSize As Long

If (GetObject(inDIB, Len(BMinf), BMinf) = 0) Then Exit Function
If (BMinf.bmBits = 0) Then Exit Function ' Only working with DIBSection's

' Get a reference DC to work with
DeskDC = GetDC(0)

' Set Bitmap info header size
DIBHead.bmiHeader.biSize = Len(DIBHead.bmiHeader)

' Attempt to read DIBSection header
If (GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)) Then
If (DIBHead.bmiHeader.biBitCount <= 8) Then
NumCols = DIBHead.bmiHeader.biClrUsed ' Read palette
If (NumCols = 0) Then NumCols = 2 ^ DIBHead.bmiHeader.biBitCount
Call GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)
ElseIf (DIBHead.bmiHeader.biCompression) Then
If (DIBHead.bmiHeader.biCompression = BI_BITFIELDS) Then
NumCols = 3
Else ' Don't support RLE compressed images
Call ReleaseDC(0, DeskDC)
Exit Function
End If
End If

' Create image data buffer
DataLen = DIBHead.bmiHeader.biSizeImage \ 4
ReDim BMData(DataLen - 1) As Long

' Read image data
Call GetDIBits(DeskDC, inDIB, 0, _
DIBHead.bmiHeader.biHeight, BMData(0), DIBHead, 0)
DIBHead.bmiHeader.biClrUsed = NumCols

With FileHead
.bfType = &H4D42 ' Bitmap magic cookie; ASCII "BM"
.bfOffBits = Len(FileHead) + Len(DIBHead.bmiHeader) + (NumCols * 4)
.bfSize = DIBHead.bmiHeader.biSizeImage + .bfOffBits
End With

On Error Resume Next ' Check to see if the file already exists
FileSize = CBool(FileLen(inPath) + 1)
On Error GoTo 0

' If so, kill it
If (FileSize) Then Call Kill(inPath)

FNum = FreeFile() ' Get a free file handle
Open inPath For Binary Access Write Lock Read Write As #FNum
Put #FNum, , FileHead ' Write file header
Put #FNum, , DIBHead.bmiHeader ' Write Bitmap info header

If (NumCols) Then ' Write palette
For WritePal = 0 To NumCols - 1
Put #FNum, , DIBHead.bmiColors(WritePal)
Next WritePal
End If

Put #FNum, , BMData() ' Write image data
Close #FNum

' Return true
SaveDIB = True
End If

Call ReleaseDC(0, DeskDC)
End Function
'***

I've tested this with 1, 4, 8, 15 (Bit-fields), 16, 24 and 32-bit images and it seems to work ok here.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-12 10:56:14 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP10.phx.gbl...

Hello Mike,

[Snip]
Post by Mike D Sutton
A DIB/DIBSection is device independent and stores it's custom
palette as part of it's header structure, a DDB is device dependant
and is assumed to use the system palette.
This is what I understood :-) I've even found a nice description of how to
transform a DDB into a DIB (by adding a selected DC's palette to it). The
only problem was/is that it stores this DIB into allocated memory (easy to
be stored into a file) , and therefore is not usable for drawing anymore.
Post by Mike D Sutton
If it has it's own palette then a separate GDI palette object
must be created, filled and selected into the same DC as the
DDB for it to be used - LoadImage() does not do this for
you so if you want to load a paletted image and keep the
palette intact then use the LR_CREATEDIBSECTION flag.
[Snip]
Post by Mike D Sutton
A DIB is really a rarely used creature since it is nothing more
than a chunk of memory containing a header followed by the
bitmap data,
If that "chunk of memory" contains all relevant data (such like with,
height, colordepth, colors and the bitmap), what is supposed to be wrong
with that ?

In other words : What does DIB-section have over a DIB ?
Post by Mike D Sutton
often when people (including myself at times) write DIB they
actually mean DIBSection.
A DIBSection is an encapsulation of a DIB into a GDI object
which can be used with the rest of the GDI infrastructure
allowing drawing to be performed in a device independent
manor. The BITMAPINFO structure is always present with
a DIB or DIBSection but since it has a dynamic array for the
palette, non-paletted images excluding for the moment bit-fields
compressed images) are not required to store this and so often
to save space developers just eference the
BITMAPINFOHEADER structure directly rather than through
the BITMAPINFO (the system doesn't care, it's only a pointer
to some memory at the end of the day.)
Hmmm ... It looks like I still have to do a lot of reading. Not in the
least about the relation between DC's and DIB/DIB-sections :-)
Post by Mike D Sutton
Post by R.Wieser
Your help sure does, but I currently do not seem to be able
to understand the fine points of GDI-programming, and it is
frustrating. Even something simple as loading-and-saving
an image goes beyond me :-\
'***
[Snip code]
Post by Mike D Sutton
'***
I've tested this with 1, 4, 8, 15 (Bit-fields), 16, 24 and
32-bit images and it seems to work ok here.
Thanks ! I just yesterday dropped my Assembly-language approach (oops !
didn't I mention that I used Windows-assembly for my experiments ? :-), and
tried to write an image-loader in VB. With some trial-and-error I even got
it to work :-)

I allso realized that using DIB or DIB-section for handling/transferring
color-independant bitmaps would probably be the best. Now all I need/want
to do is to create a routine that will store a snapshot of a window into a
DIB/DIB-section (not sure at the moment which is better suited ...).
Post by Mike D Sutton
Hope this helps,
Again, it surely does. Especially the part that shows how to save a
DIB-section to file helps a lot, as I would have needed to build one myself
thru exhaustive trial-and-error :-)

Regards,
Rudy Wieser
Mike D Sutton
2004-04-12 14:45:01 UTC
Permalink
Post by R.Wieser
This is what I understood :-) I've even found a nice description of how to
transform a DDB into a DIB (by adding a selected DC's palette to it). The
only problem was/is that it stores this DIB into allocated memory (easy to
be stored into a file) , and therefore is not usable for drawing anymore.
Presuming you mean DIBSection rather than DIB in the paragraph above, there is really very little difference in the way you use them
with GDI - it's all taken care of for you behind the scenes.
Post by R.Wieser
If that "chunk of memory" contains all relevant data (such like with,
height, colordepth, colors and the bitmap), what is supposed to be wrong
with that ?
In other words : What does DIB-section have over a DIB ?
A DIB cannot be used with the GDI infrastructure, a DIBSection on the other hand is a GDI object which can be selected into a DC and
drawn to in the same way as a DDB.
Post by R.Wieser
Hmmm ... It looks like I still have to do a lot of reading. Not in the
least about the relation between DC's and DIB/DIB-sections :-)
Yes, it sounds like you're getting confused with DIBSections and DIBs - In your case forget about DIBs entirely since you'll only
need to use DIBSections which are just as friendly as DDBs. Here's a very quick overview of DCs and Bitmap types:

A DC is a container object for other GDI objects such as Bitmaps, Pens, Brushes etc and is used to take these objects and make them
work with a specific physical device such as a printer or monitor.

A DDB is a GDI Bitmap object which is generally bound to the resolution of the display device it's DC references (see above) but in
rare cases can have an arbitrary depth (but these are a pain to work with since GDI doesn't like them.) Since this is a GDI object
it can be selected into a DC and drawing operations can be performed on it with the standard drawing methods, the bitmap data itself
is managed by the system and to get access to it we must use the Get/SetBitmapBits() or Get/SetDIBits() API calls.

A DIBSection is a close relative to the DDB but it's key difference is that it is designed to have a bit-depth other than that of
the display device to allow for device independent drawing in Windows. Like a DDB it is accessible via a GDI object handle which
also means it's compatible with the rest of the GDI infrastructure and is an encapsulation of a memory DIB (see below.) It's bitmap
data is directly accessible which makes it very fast to perform image manipulation on (although slightly tricky in VB since we don't
have very good pointer support) but we can also manipulate the data with Get/SetDIBits(). Since this is often at a different depth
than the system and often uses a palette, the palette data is stored as part of the image rather than in a separate GDI palette
object as with a DDB making DIBSections nice and portable.

A DIB is never used as part of the GDI infrastructure and is effectively nothing more than a .BMP file in memory but without the
file header (actually a .BMP file is a DIB with an additional header rather than the other way round..) DIBs are generally only
used in rare situations where an image needs to be passed around in memory but without the overhead and restrictions of GDI, a
couple of examples would be with the video API's and when working with the CF_DIB clipboard format - have a look at this thread for
an example:
http://groups.google.co.uk/groups?th=28f79a3a1cf84811
Post by R.Wieser
I allso realized that using DIB or DIB-section for handling/transferring
color-independant bitmaps would probably be the best. Now all I need/want
to do is to create a routine that will store a snapshot of a window into a
DIB/DIB-section (not sure at the moment which is better suited ...).
A DIBSection would be far better suited, hopefully the above definitions clarified this further though.
Post by R.Wieser
Again, it surely does. Especially the part that shows how to save a
DIB-section to file helps a lot, as I would have needed to build one myself
thru exhaustive trial-and-error :-)
It's one for the archives - Lots of people ask for a Bitmap writer so now there's one online.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-12 18:44:53 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP11.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
This is what I understood :-) I've even found a nice description of
how to transform a DDB into a DIB (by adding a selected DC's
palette to it). The only problem was/is that it stores this DIB into
allocated memory (easy to be stored into a file) , and therefore is
not usable for drawing anymore.
Presuming you mean DIBSection rather than DIB in the paragraph
above, there is really very little difference in the way you use them
with GDI - it's all taken care of for you behind the scenes.
Actually, I would not really know. I'm not a bit sure about what both
should look like. But I get the idea that the DDB2DIB routine does just
that : creating a (memory-stored) DIB.
Post by Mike D Sutton
Post by R.Wieser
If that "chunk of memory" contains all relevant data (such like with,
height, colordepth, colors and the bitmap), what is supposed to be
wrong with that ?
In other words : What does DIB-section have over a DIB ?
A DIB cannot be used with the GDI infrastructure, a DIBSection
on the other hand is a GDI object which can be selected into a
DC and drawn to in the same way as a DDB.
I'm afraid I don't understand. As far as I know A DIB contains all
information that defines an image : the size, colordepth & colors and the
bitmap itself. That should be enough. But for some reason it's not ...
Post by Mike D Sutton
Post by R.Wieser
Hmmm ... It looks like I still have to do a lot of reading. Not in the
least about the relation between DC's and DIB/DIB-sections :-)
Yes, it sounds like you're getting confused with DIBSections and DIBs -
You can say that again :-)
Post by Mike D Sutton
In your case forget about DIBs entirely since you'll only need
to use DIBSections which are just as friendly as DDBs.
Currently I'm trying to create a DIB-class (my second attempt at creating a
Class-object :-) to enable me to edit DIB-sections/BMP's of any color-depth,
incoorporating your save-a-DIB -routine. It looks like it works. Now I
only have to add some drawing-functions to it (like a normal
picture-controll would have)

[Snip]

Thanks for the quick explanation.

Regards,
Rudy Wieser
Mike D Sutton
2004-04-12 19:00:17 UTC
Permalink
Post by R.Wieser
I'm afraid I don't understand. As far as I know A DIB contains all
information that defines an image : the size, colordepth & colors and the
bitmap itself. That should be enough. But for some reason it's not ...
Correct, and then a DIBSection (as created by LoadImage() and written by the SaveDIB() method) wraps that into a GDI object that you
can select as any other HBITMAP object.
Post by R.Wieser
Currently I'm trying to create a DIB-class (my second attempt at creating a
Class-object :-) to enable me to edit DIB-sections/BMP's of any color-depth,
incoorporating your save-a-DIB -routine. It looks like it works. Now I
only have to add some drawing-functions to it (like a normal
picture-controll would have)
Just select the DIBSection into a DC and you can draw to it all you wish - see the post with the SaveDIB() method in for an example.
In hindsight it really should have been called SaveDIBSection(), I hope this wasn't the source of your confusion on the subject..
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-12 20:11:40 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
#***@tk2msftngp13.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
I'm afraid I don't understand. As far as I know A DIB contains
all information that defines an image : the size, colordepth &
colors and the bitmap itself. That should be enough. But for
some reason it's not ...
Correct, and then a DIBSection (as created by LoadImage() and
written by the SaveDIB() method) wraps that into a GDI object
that you can select as any other HBITMAP object.
Post by R.Wieser
Currently I'm trying to create a DIB-class (my second attempt at
creating a Class-object :-) to enable me to edit DIB-sections/
BMP's of any color-depth, incoorporating your save-a-DIB
-routine. It looks like it works. Now I only have to add some
drawing-functions to it (like a normal picture-controll would have)
Just select the DIBSection into a DC and you can draw to it all you
wish - see the post with the SaveDIB() method in for an example.
Yes, but that would mean that anyone that want's to use it would need to get
aquainted with GDI-function calling (and it quirks). My idea of creating a
Class-module is to let it look, from the outside, like it's just another
Picturebox or Image-control object : standard graphic-commands like VB uses
them should apply, and they should be equally named :-)
Post by Mike D Sutton
In hindsight it really should have been called SaveDIBSection(),
I hope this wasn't the source of your confusion on the subject..
No, not really. I understood that the LoadImage function that was supplied
the LR_CREATEDIBSECTION returned a DIB-*section* , and not a DIB. From
there I allready concluded that your save-function actually took a
DIBSection. Further comments (to the first two IF's in the save-routine)
strengthened that conclusion.

Regards,
Rudy Wieser
Mike D Sutton
2004-04-12 20:32:14 UTC
Permalink
Post by R.Wieser
Yes, but that would mean that anyone that want's to use it would need to get
aquainted with GDI-function calling (and it quirks). My idea of creating a
Class-module is to let it look, from the outside, like it's just another
Picturebox or Image-control object : standard graphic-commands like VB uses
them should apply, and they should be equally named :-)
Simply select the DIBSection into a DC (which you can create at the same time as the DIBSection), expose it via a property and it
will behave exactly the same way as a picture box's .hDC property. If you wish to further encapsulate the drawing calls to emulate
VB's .Line()() and .Circe() methods etc then you can use the MoveToEx() and LineTo(), and Ellipse() API calls respectively on the
internal DC. You may find the APIDraw library on my site to be useful at this stage since it wraps up the pen and brush object
creation that would otherwise be required.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-13 09:32:22 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@tk2msftngp13.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
Yes, but that would mean that anyone that want's to use it would
need to get aquainted with GDI-function calling (and it quirks).
My idea of creating a Class-module is to let it look, from the
standard graphic-commands like VB uses them should apply, and
they should be equally named :-)
Simply select the DIBSection into a DC (which you can create at
the same time as the DIBSection),
Which is what I did. Otherwise drawing on the DIBSection would pose
somewhat of a problem :-)
Post by Mike D Sutton
expose it via a property and it will behave exactly the same way
as a picture box's .hDC property. If you wish to further encapsulate
the drawing calls to emulate VB's . Line()() and .Circe() methods
etc then you can use the MoveToEx() and LineTo(), and Ellipse()
API calls respectively on the internal DC.
Jup. I've got the simple line to work, but am struggeling with the 'B' and
'BF' modes of it. Currently I'm using PolyLine and Polygon to emulate those
modes, but I'm not quite content ...
Post by Mike D Sutton
You may find the APIDraw library on my site to be useful at this
stage since it wraps up the pen and brush object creation that
would otherwise be required.
Thanks for the suggestion. I think I will take a peek, if only to know how
other people have solved it :-)

Regards,
Rudy Wieser
Mike D Sutton @ Work
2004-04-13 13:26:20 UTC
Permalink
Post by R.Wieser
Jup. I've got the simple line to work, but am struggeling with the 'B' and
'BF' modes of it. Currently I'm using PolyLine and Polygon to emulate those
modes, but I'm not quite content ...
You can use the Rectangle() API for both; just have a null brush selected for 'B' mode.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-13 14:56:32 UTC
Permalink
Mike D Sutton @ Work <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP11.phx.gbl...

Hello Mike,
Post by Mike D Sutton @ Work
Post by R.Wieser
Jup. I've got the simple line to work, but am struggeling with the 'B' and
'BF' modes of it. Currently I'm using PolyLine and Polygon to emulate those
modes, but I'm not quite content ...
You can use the Rectangle() API for both; just have a null brush selected for 'B' mode.
I did visit your site, and saw you using that very function. And, it was
exactly what I was searching for (I knew it was/should be there, just did
not know the function's name) :-)

My line-function now seems to be behaving just like it's picturebox
counterpart. Next stop : PaintPicture (using DC's)

Regards,
Rudy Wieser
Mike D Sutton @ Work
2004-04-13 16:07:20 UTC
Permalink
Post by R.Wieser
I did visit your site, and saw you using that very function. And, it was
exactly what I was searching for (I knew it was/should be there, just did
not know the function's name) :-)
My line-function now seems to be behaving just like it's picturebox
counterpart. Next stop : PaintPicture (using DC's)
BitBlt() / StretchBlt()
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-13 18:11:59 UTC
Permalink
Mike D Sutton @ Work <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP11.phx.gbl...

Hello Mike,
Post by Mike D Sutton @ Work
Post by R.Wieser
Next stop : PaintPicture (using DC's)
BitBlt() / StretchBlt()
Jup for the latter one.

Now if I only could think of a method to obtain the height & width of an
image selected into an DC (if no width or height is provided in the
PaintPicture call, the height and width of the source-image is taken) ...

Another thing is that PaintPicture ignores any data *outside* the
source-image (if it's instructed to copy data from there), while a Blit
happily copies that garbage in/onto the target-image. :-\

Just some things yet to solve :-)
Post by Mike D Sutton @ Work
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
WWW: Http://www.mvps.org/EDais/
Mike D Sutton
2004-04-13 21:41:49 UTC
Permalink
Post by R.Wieser
Now if I only could think of a method to obtain the height & width of an
image selected into an DC (if no width or height is provided in the
PaintPicture call, the height and width of the source-image is taken) ...
Call GetObject() on the DIBSection handle as I used in the SaveDIB() method and it will fill a BITMAP structure with information
about that Bitmap including it's size and bit-depth. If for some reason you don't know the DIBSection handle then you can sue the
GetCurrentObject() API call with the OBJ_BITMAP flag on the DC handle.
Post by R.Wieser
Another thing is that PaintPicture ignores any data *outside* the
source-image (if it's instructed to copy data from there), while a Blit
happily copies that garbage in/onto the target-image. :-\
Validate the input coordinates and only draw the section you require, since you're wrapping the call you can do whatever you want
with the input parameters. You can find the area that two rectangles overlay with the IntersectRect() API call if you require it.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-13 23:11:03 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP11.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
Now if I only could think of a method to obtain the height &
width of an image selected into an DC (if no width or height
is provided in the PaintPicture call, the height and width of
the source-image is taken) ...
Call GetObject() on the DIBSection handle as I used in the
SaveDIB() method and it will fill a BITMAP structure with
information about that Bitmap including it's size and bit-depth.
But that will probably not work on a PictureBox or Image object as defined
within VB (both will probably use DDB's)
Post by Mike D Sutton
If for some reason you don't know the DIBSection handle
then you can sue the GetCurrentObject() API call with the
OBJ_BITMAP flag on the DC handle.
Bingo ! That was/is the type of call I was looking for :-) Thanks.
Post by Mike D Sutton
Post by R.Wieser
Another thing is that PaintPicture ignores any data *outside*
the source-image (if it's instructed to copy data from there),
while a Blit happily copies that garbage in/onto the target-
image. :-\
Validate the input coordinates and only draw the section you
require, since you're wrapping the call you can do whatever
you want with the input parameters.
I can't just change the input-parameters, as they are also gouverning the
stretching/squishing of the image (I'm using StretchBlt for the actual
copying, just like PaintPicture seems to do). I probably would need to copy
the source into an intermediate bitmap, mask-off the parts I do not need,
and than copy that result on/into the target DC.

Now I think of it ... Maybe if I would change the target-parameters over a
same amount (percentage-wise) as the source-parameters it would probably
work ...
Post by Mike D Sutton
You can find the area that two rectangles overlay with the
IntersectRect() API call if you require it.
Hmmm ... I'l have to look into that one ...

Regards,
Rudy Wieser
Mike D Sutton @ Work
2004-04-14 10:09:29 UTC
Permalink
Post by R.Wieser
But that will probably not work on a PictureBox or Image object as defined
within VB (both will probably use DDB's)
Sure it will, it's just an HBITMAP the same as the DIBSection - remember a DIBSection and DDB are very closely related, generally
what work's for one will also work for the other in terms of operating on their handles at least.
Post by R.Wieser
I can't just change the input-parameters, as they are also gouverning the
stretching/squishing of the image (I'm using StretchBlt for the actual
copying, just like PaintPicture seems to do). I probably would need to copy
the source into an intermediate bitmap, mask-off the parts I do not need,
and than copy that result on/into the target DC.
Now I think of it ... Maybe if I would change the target-parameters over a
same amount (percentage-wise) as the source-parameters it would probably
work ...
As long as you took into account working to and from a clipped rectangle there should be no problem, both BitBlt() and StretchBlt()
take source rectangles to blit from, and StretchBlt() also takes a destination rectangle (obviously!) With a little bit of trial
and error/testing it shouldn't be too tricky to work something up that takes into account the 4 or so different possibilities
(clipping one, the other, both or neither.)
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-14 21:36:22 UTC
Permalink
Mike D Sutton @ Work <***@mvps.org> schreef in berichtnieuws
***@tk2msftngp13.phx.gbl...

Hello Mike,
Post by Mike D Sutton @ Work
But that will probably not work on a PictureBox or Image
object as defined within VB (both will probably use DDB's)
Sure it will, it's just an HBITMAP the same as the DIBSection -
remember a DIBSection and DDB are very closely related, generally
what work's for one will also work for the other in terms of operating
on their handles at least.
Well, I just spend some time to find a way to get my DIBSection accepted by
VB's PaintPicture method. The only thing I got outof it where
program-crashes. :-\ :-)

That's nonwithstanding the fact the GetObjectType GDI-call classifies both
as OBJ_BITMAP ...

Any idea's ? :-)
Post by Mike D Sutton @ Work
I can't just change the input-parameters, as they are also
gouverning the stretching/squishing of the image (I'm using
StretchBlt for the actual copying, just like PaintPicture
seems to do). I probably would need to copy the source
into an intermediate bitmap, mask-off the parts I do not
need, and than copy that result on/into the target DC.
Now I think of it ... Maybe if I would change the target-
parameters over a same amount (percentage-wise) as the
source-parameters it would probably work ...
As long as you took into account working to and from a
clipped rectangle there should be no problem, both BitBlt()
and StretchBlt() take source rectangles to blit from, and
StretchBlt() also takes a destination rectangle (obviously!)
With a little bit of trial and error/testing it shouldn't be too
tricky to work something up that takes into account the 4
or so different possibilities (clipping one, the other, both
or neither.)
Which should not be too difficult. Now the only question remains as what I
should do if the target-width & height are not multiples of the source width
& height .... For some reason 0.5 or 0.3 pixel does not seem to exist :-)

By the way : I tried to apply a clipping-region (CreateRectRgn equal in size
of my DIBSection) to my source-DC, but for some reason it was ignored ....

Seems like I have to read-up on Regions too :-)

Regards,
Rudy Wieser
Mike D Sutton @ Work
2004-04-15 11:13:48 UTC
Permalink
Post by R.Wieser
Well, I just spend some time to find a way to get my DIBSection accepted by
VB's PaintPicture method. The only thing I got outof it where
program-crashes. :-\ :-)
PaintPicture() is working at the OLE level so you need to wrap your DIBSection in a StdPicture object, if you must use it then have
a look at this old post for an example:
http://groups.google.co.uk/groups?selm=eC%24lb53yCHA.2232%40TK2MSFTNGP09
Post by R.Wieser
That's nonwithstanding the fact the GetObjectType GDI-call classifies both
as OBJ_BITMAP ...
Sorry, you've lost me - what's the problem? If you just need to get the size of the Bitmap then surely the fact that both are
classified in the same way is a benefit to you? If you particularly need to differentiate between the two then as mentioned before
the GetObject() call will only fill in the .bmBits member of the BITMAP structure for a DIBSection.
Also AFAIK VB's objects use a DIBSections wrapped by StdPicture objects, it's quite rare that you'll get a DDB wrapped as a
StdPicture since it's not as portable (DIBs use a shared memory pool where as DDBs are defined in local process specific memory.)
If you need to save a DDB using the SaveDIB() method, then it _should_ work as-is however you'll need to put in some tests for
paletted images and perhaps add a palette handle as an optional parameter if you want to be really thorough.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-15 15:08:47 UTC
Permalink
Mike D Sutton @ Work <***@mvps.org> schreef in berichtnieuws
#***@tk2msftngp13.phx.gbl...

Hello Mike,
Post by Mike D Sutton @ Work
Post by R.Wieser
Well, I just spend some time to find a way to get my DIBSection
accepted by VB's PaintPicture method. The only thing I got
outof it where program-crashes. :-\ :-)
PaintPicture() is working at the OLE level so you need to wrap
your DIBSection in a StdPicture object, if you must use it then have
http://groups.google.co.uk/groups?selm=eC%24lb53yCHA.2232%40TK2MSFTNGP09
Thanks !
Post by Mike D Sutton @ Work
Post by R.Wieser
That's nonwithstanding the fact the GetObjectType GDI-call
classifies both as OBJ_BITMAP ...
Sorry, you've lost me - what's the problem? If you just need to
get the size of the Bitmap then surely the fact that both are
classified in the same way is a benefit to you?
Not really. I actually confuses me. I can retrieve certain aspects of the
bitmap, but I can't use the"bitmaps" interchangably (have to "type-cast" a
DIB-section to a StdPicture to be able to use it in VB).

Although I have some info about GDI-functions (about the same the MS-site
offers when you look for a function), a lot remains untold :-\
Post by Mike D Sutton @ Work
If you particularly need to differentiate between the two then as
mentioned before the GetObject() call will only fill in the .bmBits
member of the BITMAP structure for a DIBSection.
??? Are you sure ? I've succesfully extracted (among onthers) the width &
height from such a structure returned from my DIBSection.
Post by Mike D Sutton @ Work
Also AFAIK VB's objects use a DIBSections wrapped by
StdPicture objects, it's quite rare that you'll get a DDB wrapped
as a StdPicture since it's not as portable (DIBs use a shared
memory pool where as DDBs are defined in local process specific
memory.)
If you need to save a DDB using the SaveDIB() method, then it
_should_ work as-is however you'll need to put in some tests for
paletted images and perhaps add a palette handle as an optional
parameter if you want to be really thorough.
Hope this helps,
Your info still helps me, bit by bit, to understand more about
Image-handling :-)

Regards,
Rudy Wieser
Mike D Sutton @ Work
2004-04-15 15:19:38 UTC
Permalink
Post by R.Wieser
Not really. I actually confuses me. I can retrieve certain aspects of the
bitmap, but I can't use the"bitmaps" interchangably (have to "type-cast" a
DIB-section to a StdPicture to be able to use it in VB).
It's a little more than a type cast, it's basically wrapping it in another layer for another entire library - The GDI objects till
sit behind all this though and can be used directly within VB without having to use the OLE side of things at all.
Post by R.Wieser
Although I have some info about GDI-functions (about the same the MS-site
offers when you look for a function), a lot remains untold :-\
I guess a lot of it will just come with practice, there's probably not a lot more I can tell you about the methods.
Post by R.Wieser
??? Are you sure ? I've succesfully extracted (among onthers) the width &
height from such a structure returned from my DIBSection.
The rest of the structure is filled for either structure, but the .bmBits member is only filled for a DIBSection - try it on a
handle returned from CreateDIBSection() and CreateCompatibleBitmap() for example.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/

R.Wieser
2004-04-12 14:02:37 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP10.phx.gbl...

Hello Mike,

Just a question :

[Snip]
Post by Mike D Sutton
' Attempt to read DIBSection header
If (GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)) Then
If (DIBHead.bmiHeader.biBitCount <= 8) Then
NumCols = DIBHead.bmiHeader.biClrUsed ' Read palette
If (NumCols = 0) Then NumCols = 2 ^
DIBHead.bmiHeader.biBitCount
Post by Mike D Sutton
Call GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)
What's the reason to re-load DIBHead here (in the last line of the above) ?
As far as I can see, you have not changed anything that could have an impact
on it.

Regards,
Rudy Wieser
Mike D Sutton
2004-04-12 14:22:14 UTC
Permalink
Post by Mike D Sutton
Post by Mike D Sutton
' Attempt to read DIBSection header
If (GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)) Then
If (DIBHead.bmiHeader.biBitCount <= 8) Then
NumCols = DIBHead.bmiHeader.biClrUsed ' Read palette
If (NumCols = 0) Then NumCols = 2 ^
DIBHead.bmiHeader.biBitCount
Post by Mike D Sutton
Call GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)
What's the reason to re-load DIBHead here (in the last line of the above) ?
As far as I can see, you have not changed anything that could have an impact
on it.
The first GetDIBits() call fills the main header structure and allows us to see whether the DIBSection has a palette or not
(biBitCount <= 8.) If so a second call to GetDIBits() is required to fill the palette array (for some reason the first call does
not fill it, put a break point after the first call and see for yourself.) The reason NumCols is being assigned is that the second
call to GetDIBits() for some reason knocks out the .biClrUsed and .biClrImportant members of the BITMAPINFOHEADER structure so it
must be re-set after the call, also I've taken into account the odd situation where this is not assigned at all and assigned the
default palette entry count for that bit-depth (2 ^ DIBHead.bmiHeader.biBitCount.)
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-12 18:22:38 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@tk2msftngp13.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by Mike D Sutton
Post by Mike D Sutton
' Attempt to read DIBSection header
If (GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)) Then
If (DIBHead.bmiHeader.biBitCount <= 8) Then
NumCols = DIBHead.bmiHeader.biClrUsed ' Read palette
If (NumCols = 0) Then NumCols = 2 ^
DIBHead.bmiHeader.biBitCount
Post by Mike D Sutton
Call GetDIBits(DeskDC, inDIB, 0, 0, ByVal 0&, DIBHead, 0)
What's the reason to re-load DIBHead here (in the last line of the above) ?
As far as I can see, you have not changed anything that could have an impact
on it.
The first GetDIBits() call fills the main header structure and
allows us to see whether the DIBSection has a palette or not
(biBitCount <= 8.) If so a second call to GetDIBits() is
required to fill the palette array (for some reason the first call
does not fill it, put a break point after the first call and see for
yourself.) The reason NumCols is being assigned is that the
second call to GetDIBits() for some reason knocks out the
.biClrUsed and .biClrImportant members of the
BITMAPINFOHEADER structure so it must be re-set after
the call, also I've taken into account the odd situation where
this is not assigned at all and assigned the default palette entry
count for that bit-depth (2 ^ DIBHead.bmiHeader.biBitCount.)
Hmm ... Strange. The first call loads the structure partially, and the
second one fill's-in more of the same structure, while erasing other parts
...

I'm sure it's driven by some kind of logic, just one I do not see at the
moment :-)

Thanks for your answer.

Regards,
Rudy Wieser
Post by Mike D Sutton
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
WWW: Http://www.mvps.org/EDais/
Mike D Sutton
2004-04-12 19:03:49 UTC
Permalink
Post by R.Wieser
Hmm ... Strange. The first call loads the structure partially, and the
second one fill's-in more of the same structure, while erasing other parts
I'm sure it's driven by some kind of logic, just one I do not see at the
moment :-)
In many cases just filling the header structure alone is all that's required, my guess would be that once the biClrUsed field (and
perhaps the biBitCount field also?) is populated then the palette is written into the structure but I've not done any tests on it.
As to why it wipes the used and important colours fields, your guess is as good as mine but I would guess it's a bug.
Cheers,

Mike


- Microsoft Visual Basic MVP -
E-Mail: ***@mvps.org
WWW: Http://www.mvps.org/EDais/
R.Wieser
2004-04-12 20:16:42 UTC
Permalink
Mike D Sutton <***@mvps.org> schreef in berichtnieuws
***@TK2MSFTNGP09.phx.gbl...

Hello Mike,
Post by Mike D Sutton
Post by R.Wieser
Hmm ... Strange. The first call loads the structure partially,
and the second one fill's-in more of the same structure,
while erasing other parts
I'm sure it's driven by some kind of logic, just one I do not
see at the moment :-)
In many cases just filling the header structure alone is all that's
required, my guess would be that once the biClrUsed field
(and perhaps the biBitCount field also?) is populated then the
palette is written into the structure but I've not done any tests
on it.
As to why it wipes the used and important colours fields, your
guess is as good as mine but I would guess it's a bug.
It would be my guess allso, but I've experienced too many 'bugs' that had
some reason to live, once the reason of what was happening was explained to
me :-\ So, I've become a bit carefull with declaring something a bug. :-)

Regards,
Rudy Wieser
Loading...