Results 1 to 8 of 8

Thread: BitMap to Bytes - An Attempt

  1. #1

    Thread Starter
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849

    Smile BitMap to Bytes - An Attempt

    Hi!

    A lot of times it has been asked, yours truly inlcuded, how a Bitmap in an app can be serialized into a byte array. Given below is an attempt modifying an example from All-API Guide. Hope this provides a start to all of you. The array is now written to disk. But can be sent directly through Winsock for network tranfer.

    VB Code:
    1. 'The Sending App, containing a PictureBox and a Command Button
    2. 'ScaleMode of the Form and the PictureBox set to Pixels
    3.  
    4. Private Const BI_RGB = 0&
    5. Private Const DIB_RGB_COLORS = 0
    6. Private Type BITMAPINFOHEADER
    7.         biSize As Long
    8.         biWidth As Long
    9.         biHeight As Long
    10.         biPlanes As Integer
    11.         biBitCount As Integer
    12.         biCompression As Long
    13.         biSizeImage As Long
    14.         biXPelsPerMeter As Long
    15.         biYPelsPerMeter As Long
    16.         biClrUsed As Long
    17.         biClrImportant As Long
    18. End Type
    19. Private Type RGBQUAD
    20.         rgbBlue As Byte
    21.         rgbGreen As Byte
    22.         rgbRed As Byte
    23.         rgbReserved As Byte
    24. End Type
    25. Private Type BITMAPINFO
    26.         bmiHeader As BITMAPINFOHEADER
    27.         bmiColors As RGBQUAD
    28. End Type
    29. Private Declare Function CreateCompatibleDC Lib "gdi32" _
    30. (ByVal hdc As Long) As Long
    31. Private Declare Function CreateDIBSection Lib "gdi32" _
    32. (ByVal hdc As Long, pBitmapInfo As BITMAPINFO, _
    33. ByVal un As Long, ByVal lplpVoid As Long, _
    34. ByVal handle As Long, ByVal dw As Long) As Long
    35. Private Declare Function GetDIBits Lib "gdi32" _
    36. (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan _
    37. As Long, ByVal nNumScans As Long, lpBits As Any, _
    38. lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
    39. Private Declare Function SelectObject Lib "gdi32" _
    40. (ByVal hdc As Long, ByVal hObject As Long) As Long
    41. Private Declare Function DeleteDC Lib "gdi32" _
    42. (ByVal hdc As Long) As Long
    43. Private Declare Function DeleteObject Lib "gdi32" _
    44. (ByVal hObject As Long) As Long
    45. Private Declare Function BitBlt Lib "gdi32" _
    46. (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, _
    47. ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC _
    48. As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
    49. ByVal dwRop As Long) As Long
    50. Private Declare Function GetDC Lib "user32" _
    51. (ByVal hwnd As Long) As Long
    52. Dim iBitmap As Long, iDC As Long
    53.  
    54. Private Sub Command1_Click()
    55.     Dim bi24BitInfo As BITMAPINFO, bBytes() As Byte
    56.     With bi24BitInfo.bmiHeader
    57.         .biBitCount = 24
    58.         .biCompression = BI_RGB
    59.         .biPlanes = 1
    60.         .biSize = Len(bi24BitInfo.bmiHeader)
    61.         .biWidth = Picture1.Width
    62.         .biHeight = Picture1.Height
    63.     End With
    64.     ReDim bBytes(1 To bi24BitInfo.bmiHeader.biWidth * _
    65.     bi24BitInfo.bmiHeader.biHeight * 3) As Byte
    66.  
    67.     iDC = CreateCompatibleDC(0)
    68.  
    69.     iBitmap = CreateDIBSection(iDC, bi24BitInfo, _
    70.     DIB_RGB_COLORS, ByVal 0&, ByVal 0&, ByVal 0&)
    71.  
    72.     SelectObject iDC, iBitmap
    73.  
    74.     BitBlt iDC, 0, 0, bi24BitInfo.bmiHeader.biWidth, _
    75.     bi24BitInfo.bmiHeader.biHeight, Picture1.hdc, 0, 0, _
    76.     vbSrcCopy
    77.  
    78.     GetDIBits iDC, iBitmap, 0, _
    79.     bi24BitInfo.bmiHeader.biHeight, bBytes(1), _
    80.     bi24BitInfo, DIB_RGB_COLORS
    81.  
    82.         Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    83.             Put #1, 1, CLng(Picture1.Width)
    84.             Put #1, 5, CLng(Picture1.Height)
    85.             Put #1, 9, bBytes
    86.         Close #1
    87.     DeleteDC iDC
    88.     DeleteObject iBitmap
    89.     Client.Show 'Run the client App. I used two forms in the same app
    90. End Sub
    91.  
    92. Private Sub Form_Load()
    93. Me.ScaleMode = vbPixels
    94. With Picture1
    95.     .ScaleMode = vbPixels
    96.     .AutoRedraw = True
    97.     .AutoSize = True
    98.     .Picture = LoadPicture(App.Path & "\Clouds.bmp")
    99. End With
    100. End Sub
    101.  
    102. 'The recieving App containing a pictureBox with a command button
    103. 'with the form and picturebox scalemode set to Pixels and
    104. 'autoredraw, autosize of the pictureBox set to true
    105.  
    106. Private Declare Function SetDIBitsToDevice Lib "gdi32" _
    107. (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, _
    108. ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, _
    109. ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans _
    110. As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage _
    111. As Long) As Long
    112. Private Const BI_RGB = 0&
    113. Private Const DIB_RGB_COLORS = 0
    114. Private Type BITMAPINFOHEADER
    115.         biSize As Long
    116.         biWidth As Long
    117.         biHeight As Long
    118.         biPlanes As Integer
    119.         biBitCount As Integer
    120.         biCompression As Long
    121.         biSizeImage As Long
    122.         biXPelsPerMeter As Long
    123.         biYPelsPerMeter As Long
    124.         biClrUsed As Long
    125.         biClrImportant As Long
    126. End Type
    127. Private Type RGBQUAD
    128.         rgbBlue As Byte
    129.         rgbGreen As Byte
    130.         rgbRed As Byte
    131.         rgbReserved As Byte
    132. End Type
    133. Private Type BITMAPINFO
    134.         bmiHeader As BITMAPINFOHEADER
    135.         bmiColors As RGBQUAD
    136. End Type
    137.  
    138. Private Sub Command1_Click()
    139. Dim bi24BitInfo As BITMAPINFO, bmpWidth As Long, _
    140. bmpHeight As Long
    141. Dim bbBytes() As Byte
    142. Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    143.     ReDim bbBytes(1 To (LOF(1) - 8))
    144.         Get #1, 1, bmpWidth
    145.         Get #1, 5, bmpHeight
    146.         Get #1, 9, bbBytes
    147. Close #1
    148.  
    149.     With bi24BitInfo.bmiHeader
    150.         .biBitCount = 24
    151.         .biCompression = BI_RGB
    152.         .biPlanes = 1
    153.         .biSize = Len(bi24BitInfo.bmiHeader)
    154.         .biWidth = bmpWidth
    155.         .biHeight = bmpHeight
    156.     End With
    157.         Picture1.Width = bmpWidth
    158.         Picture1.Height = bmpHeight
    159.    
    160.     SetDIBitsToDevice Picture1.hdc, 0, 0, _
    161.     bi24BitInfo.bmiHeader.biWidth, _
    162.     bi24BitInfo.bmiHeader.biHeight, 0, 0, 0, _
    163.     bi24BitInfo.bmiHeader.biHeight, bbBytes(1), _
    164.     bi24BitInfo, DIB_RGB_COLORS
    165.    
    166.     Picture1.AutoSize = True
    167.     Picture1.Refresh
    168. End Sub
    169.  
    170. Private Sub Form_Load()
    171. Me.ScaleMode = vbPixels
    172. Picture1.ScaleMode = vbPixels
    173. End Sub
    Last edited by KayJay; Oct 5th, 2002 at 05:11 AM.

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  2. #2
    Fanatic Member Geespot's Avatar
    Join Date
    Oct 2001
    Location
    Birmingham, UK
    Posts
    577
    you can convert a bitmap to a byte array with the GetBitmapBits API


    Add a picturebox with a picture in it, and a command button
    VB Code:
    1. Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
    2. Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
    3. Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    4. Private Type BITMAP
    5.     bmType As Long
    6.     bmWidth As Long
    7.     bmHeight As Long
    8.     bmWidthBytes As Long
    9.     bmPlanes As Integer
    10.     bmBitsPixel As Integer
    11.     bmBits As Long
    12.  
    13. End Type
    14.  
    15. Private Sub Command1_Click()
    16.     Dim hbm As Long
    17.     Dim bm As BITMAP
    18.     Dim status As Long
    19.     Dim bytes() As Byte
    20.     Dim i As Long
    21.     Dim j As Long
    22.     Dim wid As Long
    23.     Dim hgt As Long
    24.    
    25.     hbm = Picture1.Image
    26.    
    27.     '-- Get status of bitmap
    28.     status = GetObject(hbm, Len(bm), bm)
    29.    
    30.     '-- Get the Bits
    31.     wid = bm.bmWidthBytes
    32.     hgt = bm.bmHeight
    33.     ReDim bytes(1 To wid, 1 To hgt)
    34.    
    35.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
    36.     '-- We now have the entire bitmap in our Byte Array
    37.    
    38.    
    39.     '-- And if you want to modify the image ( makes it darker )
    40.     For i = 1 To wid
    41.         For j = 1 To hgt
    42.             bytes(i, j) = bytes(i, j) / 2
    43.         Next j
    44.     Next i
    45.    
    46.     '-- Set the Bits
    47.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
    48.    
    49.    
    50. End Sub

  3. #3

    Thread Starter
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Thanks for that

    I tried the following
    VB Code:
    1. 'First App
    2. Picture1.Picture = LoadPicture(App.Path & "\Clouds.bmp")
    3.     Dim hbm As Long
    4.     Dim bm As BITMAP
    5.     Dim status As Long
    6.     Dim bytes() As Byte
    7.     Dim i As Long
    8.     Dim j As Long
    9.     Dim wid As Long
    10.     Dim hgt As Long
    11.    
    12.     hbm = Picture1.Image
    13.    
    14.     '-- Get status of bitmap
    15.     status = GetObject(hbm, Len(bm), bm)
    16.    
    17.     '-- Get the Bits
    18.     wid = bm.bmWidthBytes
    19.     hgt = bm.bmHeight
    20.     ReDim bytes(1 To wid, 1 To hgt)
    21.    
    22.    status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
    23.     '-- We now have the entire bitmap in our Byte Array
    24.    
    25.      Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    26.             Put #1, 1, CLng(wid)
    27.             Put #1, 5, CLng(hgt)
    28.             Put #1, 9, bytes
    29.     Close #1
    30.     Client.Show
    31.    
    32. 'Second App
    33. Private Sub Command1_Click()
    34. Dim bmpWidth As Long, bmpHeight As Long
    35. Dim bbBytes() As Byte
    36. Dim hbm As Long
    37. hbm = Picture1.Image
    38. Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    39.         Get #1, 1, bmpWidth
    40.         Get #1, 5, bmpHeight
    41. Close #1
    42. Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    43.     ReDim bbBytes(1 To bmpWidth, 1 To bmpHeight)
    44.         Get #1, 9, bbBytes
    45. Close #1
    46.  
    47. status = SetBitmapBits(hbm, bmpWidth * bmpHeight, bbBytes(1, 1))
    48. Picture1.AutoSize = True
    49. Picture1.Refresh
    I get just a series of white, green and blue horizontal lines in the second form/app

    Where am I wrong?

    Thanks

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  4. #4
    Fanatic Member Geespot's Avatar
    Join Date
    Oct 2001
    Location
    Birmingham, UK
    Posts
    577
    hmmm thats interesting, the image gets badly distorted
    yet the file contents matches the byte array

    I made the byte array to a single dimensional array ( redim bytes(1 to wid*hgt) ) thinking that could be the problem, yet it still distorts

    Ive tried removing the width and height ( 8 bytes ) from the start of the file and loading it, still distorts

    Ive done a comparison between the file data and the bytes, and its exactly the same

    im stumped

  5. #5

    Thread Starter
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Will try some more and keep you posted

    Ta

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  6. #6

    Thread Starter
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    API Guide to the rescue again!
    The dimensioning of the array is like so. So says an example from the ALL API Guide.
    VB Code:
    1. BytesPerLine = (PicInfo.bmWidth * 3 + 3) And &HFFFFFFFC
    2.     ReDim PicBits(1 To BytesPerLine * PicInfo.bmHeight * 3) As Byte
    This one works ok for me.
    VB Code:
    1. 'Form One
    2. Dim PicBits() As Byte, PicInfo As BITMAP
    3. Dim BytesPerLine As Long
    4. Picture1.Picture = LoadPicture(App.Path & "\Clouds.bmp")
    5.     GetObject Picture1.Image, Len(PicInfo), PicInfo
    6.     BytesPerLine = (PicInfo.bmWidth * 3 + 3) And &HFFFFFFFC
    7.     ReDim PicBits(1 To BytesPerLine * PicInfo.bmHeight * 3) As Byte
    8.     GetBitmapBits Picture1.Image, UBound(PicBits), PicBits(1)
    9.  
    10.      Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    11.             Put #1, 1, CLng(Picture1.Width)
    12.             Put #1, 5, CLng(Picture1.Height)
    13.             Put #1, 9, PicBits
    14.     Close #1
    15.     Client.Show
    16. End Sub
    17.  
    18. 'Client Form
    19. Dim bmpWidth As Long, bmpHeight As Long, bbBytes() As Byte
    20. Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    21.         Get #1, 1, bmpWidth
    22.         Get #1, 5, bmpHeight
    23. Close #1
    24. Picture1.Width = bmpWidth
    25. Picture1.Height = bmpHeight
    26. Open App.Path & "\CloudsCopy.BMP" For Binary As #1
    27.     ReDim bbBytes(1 To LOF(1) - 8)
    28.         Get #1, 9, bbBytes
    29. Close #1
    30. SetBitmapBits Picture1.Image, UBound(bbBytes), bbBytes(1)
    31. Picture1.Refresh

    Looks all right?
    Last edited by KayJay; Oct 5th, 2002 at 08:20 AM.

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  7. #7
    Lively Member
    Join Date
    Dec 2002
    Posts
    107
    Try this:

    VB Code:
    1. ' Global Memory Flags
    2. Const GMEM_MOVEABLE = &H2
    3. Const GMEM_ZEROINIT = &H40
    4.  
    5. Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
    6.  
    7. Private Declare Function GlobalAlloc Lib "kernel32" ( _
    8.   ByVal wFlags As Long, _
    9.   ByVal dwBytes As Long) As Long
    10.  
    11. Private Declare Function GlobalSize Lib "kernel32" ( _
    12.   ByVal hMem As Long) As Long
    13.  
    14. Private Declare Function GlobalLock Lib "kernel32" ( _
    15.   ByVal hMem As Long) As Long
    16.  
    17. Private Declare Function GlobalUnlock Lib "kernel32" ( _
    18.   ByVal hMem As Long) As Long
    19.  
    20. Const PictureID = &H746C&
    21.  
    22. Private Type PictureHeader
    23.    Magic As Long
    24.    Size As Long
    25. End Type
    26.  
    27. Public Sub Picture2Array(ByVal oObj As StdPicture, aBytes() As Byte)
    28. Dim oIPS As IPersistStream
    29. Dim oStream As IStream
    30. Dim hGlobal As Long
    31. Dim lPtr As Long
    32. Dim lSize As Long
    33. Dim Hdr As PictureHeader
    34.  
    35.    ' Get the IPersistStream interface
    36.    Set oIPS = oObj
    37.    
    38.    ' Create a IStream object
    39.    ' on global memory
    40.    Set oStream = CreateStreamOnHGlobal(0, True)
    41.    
    42.    ' Save the picture in the stream
    43.    oIPS.Save oStream, True
    44.      
    45.    ' Get the global memory handle
    46.    ' from the stream
    47.    hGlobal = GetHGlobalFromStream(oStream)
    48.    
    49.    ' Get the memory size
    50.    lSize = GlobalSize(hGlobal)
    51.    
    52.    ' Get a pointer to the memory
    53.    lPtr = GlobalLock(hGlobal)
    54.    
    55.    If lPtr Then
    56.    
    57.       lSize = lSize - Len(Hdr)
    58.      
    59.       ' Redim the array
    60.       ReDim aBytes(0 To lSize - 1)
    61.    
    62.       ' Copy the data to the array
    63.       MoveMemory aBytes(0), ByVal lPtr + Len(Hdr), lSize
    64.    
    65.    End If
    66.    
    67.    ' Release the pointer
    68.    GlobalUnlock hGlobal
    69.    
    70.    ' Release the IStream object
    71.    Set oStream = Nothing
    72.  
    73. End Sub

  8. #8

    Thread Starter
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    cool

    Thanx pal. That project's now over. But this is being added to my arsenal of VBForums Code Snippets.

    Cheers and Good Luck

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width