To save the picture, use GetDIBits to get the bitmap's pixel information in DIB (device-independent bitmap) format. Save the pixel data and the image's BITMAPINFOHEADER information using AppendChunk.
Note that you could write the pixel information in blocks using multiple calls to AppendChunk if that were more efficient for some reason. In this case, we need to store all of the pixel information in an array at the same time anyway so we won't save memory doing this in chunks as we would if we were copying a file's contents into the database in chunks.
To reload the image, use GetChunk to retrieve the BITMAPINFOHEADER and pixel information. Then use SetDIBits to display the result.
|
' Save the picture into the database as a DIB.
Private Sub SaveDibToDb(rs As ADODB.Recordset)
Dim bytes_per_scanLine As Integer
Dim wid As Long
Dim hgt As Long
Dim bitmap_info As BITMAPINFO
Dim pixels() As Byte
Dim buffer() As Byte
' Prepare the bitmap description.
wid = picPerson.ScaleWidth
hgt = picPerson.ScaleHeight
With bitmap_info.bmiHeader
.biSize = 40
.biWidth = wid
' Use negative height to scan top-down.
.biHeight = -hgt
.biPlanes = 1
.biBitCount = 32
.biCompression = BI_RGB
bytes_per_scanLine = ((((.biWidth * .biBitCount) + _
31) \ 32) * 4)
.biSizeImage = bytes_per_scanLine * hgt
End With
' Load the bitmap's data.
ReDim pixels(1 To 4, 1 To wid, 1 To hgt)
GetDIBits picPerson.hdc, picPerson.Image, _
0, hgt, pixels(1, 1, 1), _
bitmap_info, DIB_RGB_COLORS
' Save the BITMAPINFO.
ReDim buffer(0 To Len(bitmap_info.bmiHeader) - 1)
CopyMemory buffer(0), bitmap_info.bmiHeader, _
Len(bitmap_info.bmiHeader)
rs!Picture.AppendChunk buffer
' Save the pixels.
ReDim buffer(0 To 4 * wid * hgt - 1)
CopyMemory buffer(0), pixels(1, 1, 1), 4 * wid * hgt
rs!Picture.AppendChunk buffer
End Sub
' Load the DIB from the database.
Private Sub LoadDibFromDb(rs As ADODB.Recordset)
Dim bytes_per_scanLine As Integer
Dim wid As Long
Dim hgt As Long
Dim bitmap_info As BITMAPINFO
Dim pixels() As Byte
Dim buffer() As Byte
' Get the BITMAPINFO.
buffer = rs!Picture.GetChunk(Len(bitmap_info.bmiHeader))
CopyMemory bitmap_info.bmiHeader, buffer(0), _
Len(bitmap_info.bmiHeader)
' Get the pixels.
wid = bitmap_info.bmiHeader.biWidth
hgt = Abs(bitmap_info.bmiHeader.biHeight)
buffer = rs!Picture.GetChunk(4 * wid * hgt)
ReDim pixels(1 To 4, 1 To wid, 1 To hgt)
CopyMemory pixels(1, 1, 1), buffer(0), 4 * wid * hgt
' Size the PictureBox.
picPerson.Move picPerson.Left, picPerson.Top, wid, hgt
' Display the results.
SetDIBits picPerson.hdc, picPerson.Image, _
0, hgt, pixels(1, 1, 1), _
bitmap_info, DIB_RGB_COLORS
picPerson.Picture = picPerson.Image
End Sub
|
One disadvantage to this method is that DIBs store picture information using 4 bytes per pixel (plus 40 bytes of header information). That's essentially a bitmap version of a 32-bit color image and it takes up a lot of space. For example, a 400 by 300 pixel image takes 480,000 bytes or 468 KB. Saved as a JPEG file, this picture might take far less space. In one quick test, a photographic image took only 15 KB saved as a JPEG.
To save space, you might want compress the data going into the database and decompress it when you retrieve it using Zlib or some other compression library. Click here for an example that usees Zlib.
See my book Visual Basic Graphics Programming for more information on graphics programming in Visual Basic.
|