>I'll repeat, the Picture object holds a BITMAP ... The Handle property ... is in fact an hBitmap.
I never contradicted that. After all, we pass Picture.Handle to Win32 GDI functions expecting an hBitmap all the time.
But both of my statements above were based on my observations.
I just tested again. I placed a 800x600 jpg in a picture box, whose file size is 56.4 KB. I used your jpg compression code in your first post above to compress the picture. After calling GdipSaveImageToStream, I used your LoadPictureFromStream2 function to convert mystream back to an StdPicture object.
Putting that picture in a property box and querying its size returned 22296 bytes (well, decrease in size from 56 KB is explained due to substantial loss of quality (25%)). If the Picture object were saved in the property bag as a BITMAP, it would have occupied 800 x 600 x 3 = 1440000 + overhead bytes instead.
See this again in the example below. This time I use PictureFromRawBits function.
___
[tt]
Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, pclsid As Any) As Long
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long
Private Declare Function OleLoadPicture Lib "olepro32" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj As Any) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Const GMEM_MOVEABLE = &H2
Function PictureFromRawBits(bytes() As Byte) As IPicture
Dim cbMem As Long, hMem As Long, IPic(15) As Byte, istm As Object
'data length
cbMem = (UBound(bytes)) - LBound(bytes) + 1
'allocate global memory block
hMem = GlobalAlloc(GMEM_MOVEABLE, cbMem)
'copy picture data to global memory block
CopyMemory ByVal GlobalLock(hMem), bytes(LBound(bytes)), cbMem
'reset lock count
GlobalUnlock hMem
'create stream object from global memory
CreateStreamOnHGlobal hMem, 1, istm
'fill the Guid of IPicture interface from its CLSID
CLSIDFromString StrPtr("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"), IPic(0)
'create picture from stream object
OleLoadPicture ByVal ObjPtr(istm), 0, 0, IPic(0), PictureFromRawBits
'free global memory
GlobalFree hMem
End Function
Private Sub Form_Load()
Dim B() As Byte, File As String
File = "C:\Users\Public\Pictures\Poster.jpg"
Open File For Binary As #1
ReDim B(LOF(1) - 1)
Get #1, , B
Close
Dim pic As StdPicture, pb As PropertyBag
Set pic = PictureFromRawBits(B)
Set pb = New PropertyBag
pb.WriteProperty "Picture", pic
Debug.Print "File name:", File
Debug.Print "Picture width:", Round(ScaleX(pic.Width, vbHimetric, vbPixels))
Debug.Print "Picture height:", Round(ScaleX(pic.Height, vbHimetric, vbPixels))
Debug.Print "File size:", UBound(B) + 1 'FileLen(File)
Debug.Print "Size of property bag:", UBound(pb.Contents) + 1
Unload Me
End Sub[/tt]
___
The picture I used in the code is same as I referenced above. Here is the debug output.
[tt]
File name: C:\Users\Public\Pictures\Poster.jpg
File size: 57842
Picture width: 800
Picture height: 600
Size of property bag: 57900
[/tt]
Once again the property bag has the same size as the jpg file. Slight difference is due to the property bag overhead. A true color bitmap of same dimensions would have occupied more than 1.37 MB.
>plus some additional bits and pieces
Well, my theory is that, somewhere in those bits and pieces, the original stream which was used to create the picture is also preserved, and same is written to the property bag instead of the whole BITMAP data. Same stream is written to .frx files when we load a jpg picture in the picture property of a form, for instance. Otherwise, loading a jpg or a bmp file would have made no difference on the size of .frx file, and same would have reflected in the size of resulting exe file.
Well, there is another interesting observation. While PictureFromRawBits (and thus OleLoadPicture) appears to preserve the original stream, LoadPicture does not.
So if we create a Picture using LoadPicture, the resulting picture always occupies the size as that would be required by the BITMAP. See below.
___
[tt]
Private Sub Form_Load()
Dim File As String
File = "C:\Users\Public\Pictures\Poster.jpg"
Dim pic As StdPicture, pb As PropertyBag
Set pic = LoadPicture(File)
Set pb = New PropertyBag
pb.WriteProperty "Picture", pic
Debug.Print "File name:", File
Debug.Print "File size:", FileLen(File)
Debug.Print "Picture width:", Round(ScaleX(pic.Width, vbHimetric, vbPixels))
Debug.Print "Picture height:", Round(ScaleX(pic.Height, vbHimetric, vbPixels))
Debug.Print "Size of property bag:", UBound(pb.Contents) + 1
Unload Me
End Sub[/tt]
___
This time the output was as below. We see that the size of the property bag has inflated to the size of the property bag.
[tt]
File name: C:\Users\Public\Pictures\Poster.jpg
File size: 57842
Picture width: 800
Picture height: 600
Size of property bag: 1440112 [/tt]