Results 1 to 19 of 19

Thread: Saving a BITMAP from memory to disk

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Hi,
    I want to save a bitmap that I have created in memory to a file. I don't want to use any picture boxes (so I can't use the Save functionality of them) because this is for a usercontrol and I'm trying to keep the number of device contexts to a minimum (I'm drawing directly onto the control). I'm presuming that somewhere there's a way of saving a bitmap but am I going to have to create a file and write a bitmap header then copy the memory into the file ?

    cheers

    Andy

  2. #2
    Hyperactive Member
    Join Date
    Jun 1999
    Posts
    308

    Post

    UserControl interface is, still, a form meaning that if you draw over the control

    savepicture UserControl.Picture
    help you, I believe.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Hi,
    Thanks for the help. However, the usercontrol is only displaying a portion of a bitmap that I have in memory and it's the whole memory bitmap that I need to save.

    cheers

    Andy

  4. #4
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926

    Post

    Do you want to save the bitmap in full color, or as 4 or 8 bit bitmap?
    Do you have the bitmap in a DC?

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Hi,
    I've got the handle to the bitmap in memory. When I want to display a portion of it, I select it into a DC and stretch blit it to the usercontrol.hDC. And I need to save the bitmap as either 24bit colour (huge) or monochrome, but to be able to save as 16 or 256 colour would also be useful.

    cheers

    Andy

    [This message has been edited by andymac (edited 02-14-2000).]

  6. #6
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926

    Post

    Code:
    Option Explicit
    Private Type BITMAP
            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 BITMAPINFOHEADER
            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 RGBQUAD
            rgbBlue As Byte
            rgbGreen As Byte
            rgbRed As Byte
            rgbReserved As Byte
    End Type
    Private Type BITMAPINFO
            bmiHeader As BITMAPINFOHEADER
            ' 24 bits bitmap has no color table
            'bmiColors(255) As RGBQUAD   '256 colors
    End Type
    Private Type BITMAPFILEHEADER
            bfType(1) As Byte
            bfSize As Long
            bfReserved1 As Integer
            bfReserved2 As Integer
            bfOffBits As Long
    End Type
    
    Private Const BI_RGB = 0&
    Private Const GMEM_MOVEABLE = &H2
    Private Const DIB_RGB_COLORS = 0
    
    Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
    Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
    Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
    Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage 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 Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
    Private Declare Function lwrite Lib "kernel32" Alias "_lwrite" (ByVal hFile As Long, lpBuffer As Any, ByVal wBytes As Long) As Long
    Private Declare Function lclose Lib "kernel32" Alias "_lclose" (ByVal hFile As Long) As Long
    Private Declare Function lcreat Lib "kernel32" Alias "_lcreat" (ByVal lpPathName As String, ByVal iAttribute As Long) As Long
    
    Public Sub Save24bitPicture(hBitmap As Long, Dest As String)
    Dim tempDC As Long
    Dim bm As BITMAP
    Dim bi As BITMAPINFO
    Dim retVal As Long
    Dim bufSize As Long
    Dim ghnd As Long
    Dim gptr As Long
    Dim bmfh As BITMAPFILEHEADER
    Dim hFile As Long
    Dim Cntr As Integer
    
        ' Create a temporary memory DC, I made it compatible with the first form in the forms collection
        tempDC = CreateCompatibleDC(Forms(0).hdc)
        ' Get the size of the picture bitmap
        retVal = GetObjectAPI(hBitmap, Len(bm), bm)
        ' Fill the BITMAPINFO for the desired DIB
        bi.bmiHeader.biSize = Len(bi.bmiHeader)
        bi.bmiHeader.biWidth = bm.bmWidth
        bi.bmiHeader.biHeight = bm.bmHeight
        bi.bmiHeader.biPlanes = 1
        ' Set to 8 here to create a 8 bit DIB
        ' Set to 4 here to create an 4 bit DIB
        bi.bmiHeader.biBitCount = 24
        bi.bmiHeader.biCompression = BI_RGB
        ' Now calculate the data buffer size needed
        bufSize = bi.bmiHeader.biWidth
    
        ' Figure out the number of bytes based on the
        ' number of pixels in each byte. In this case we
        ' really don't need all this code because this example
        ' always uses a 24 bits DIB, but the code is shown
        ' here for your future reference
        Select Case bi.bmiHeader.biBitCount
            Case 1
                bufSize = (bufSize + 7) / 8
            Case 4
                bufSize = (bufSize + 1) / 2
            Case 24
                bufSize = bufSize * 3
        End Select
        ' And make sure it aligns on a long boundary
        bufSize = ((bufSize + 3) / 4) * 4
        ' And multiply by the # of scan lines
        bufSize = bufSize * bi.bmiHeader.biHeight
        
        ' Now allocate a buffer to hold the data
        ' We use the global memory pool because this buffer
        ' could easily be above 64k bytes.
        ghnd = GlobalAlloc(GMEM_MOVEABLE, bufSize)
        gptr = GlobalLock(ghnd)
        
        ' now copy the DDB to the DIB
        retVal = GetDIBits(tempDC, hBitmap, 0, bm.bmHeight, ByVal gptr, bi, DIB_RGB_COLORS)
        ' write the bitmapfileheader
        With bmfh
            .bfType(0) = &H42
            .bfType(1) = &H4D   ' the string "BM", I have split the integer into two bytes because the bytes got swapped
            .bfSize = Len(bmfh) + Len(bi) + bufSize
            .bfReserved1 = 0
            .bfReserved2 = 0
            .bfOffBits = Len(bi) + 14
        End With
        
        ' create the file, I've chosen the api way because
        ' it's an easy way to copy the data block
        hFile = lcreat(Dest, 0)
        ' write the bitmapfileheader to the file,
        ' for some strange reasons the structure can't be copied at once
        retVal = lwrite(hFile, bmfh.bfType(0), 1)
        retVal = lwrite(hFile, bmfh.bfType(1), 1)
        retVal = lwrite(hFile, bmfh.bfSize, 4)
        retVal = lwrite(hFile, bmfh.bfReserved1, 2)
        retVal = lwrite(hFile, bmfh.bfReserved2, 2)
        retVal = lwrite(hFile, bmfh.bfOffBits, 4)
        ' write the bitmapinfo to the file
        retVal = lwrite(hFile, bi, Len(bi))
        ' write the data to the file
        retVal = lwrite(hFile, ByVal gptr, bufSize)
        ' and close the file
        retVal = lclose(hFile)
        ' Dump the global memory block
        retVal = GlobalUnlock(ghnd)
        retVal = GlobalFree(ghnd)
        retVal = DeleteDC(tempDC)
        ' and were done
    End Sub

    [This message has been edited by Frans C (edited 02-14-2000).]

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Ta very much, I'll give it a go.

    thanks

    Andy

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Yep that all works. I had a few problems with the data structure being wrong, but I'm now happily saving in 4bit or 8bit colour (which is alot smaller).

    Thanks very much

    cheers

    Andy

  9. #9
    Guest

    Post

    If your bitmap is in memory as a string (I have done that), just Open a file with the extension .bmp and

    Open MyBMP for Binary as #1
    Put #1,,YourString
    Close #1

    Let me know if you want the bitmap file structure as a word document; I learned from it.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Jan 2000
    Location
    North Yorkshire
    Posts
    102

    Post

    Hi Yaz,
    The bitmap is in memory as however a bitmap is held with a pointer / handle to the memory. From the example above, you can't just write the memory in because there is no header information and the bitmap is not device independant (hence the DIB stuff in the middle). However, the method of writing a string from memory as you've shown is a good idea. Not tried it myself, but it certainly looks quick and simple.

    cheers

    Andy

  11. #11
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: Saving a BITMAP from memory to disk

    This looks like something that I can use. However I am using VB.NET and there is no hdc property of a form anymore. Any idea on how I can make this work?

    Thanks.

  12. #12
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Saving a BITMAP from memory to disk

    Are you talking about this line:
    tempDC = CreateCompatibleDC(Forms(0).hdc)

    If so, you don't need to create a DC for the code in post #6 above. You can simply reference one instead. So you can change
    Code:
    ' change from: tempDC = CreateCompatibleDC(Forms(0).hdc), to
    tempDC = GetDC(0&)
    
    ' then, instead of: retVal = DeleteDC(tempDC), use this
    retVal = ReleaseDC(0&, tempDC)
    Since you are using .Net, I'd bet you can find examples in the .Net portion of the forums.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  13. #13
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: Saving a BITMAP from memory to disk

    I searched but found nothing, although I did find questions similar to mine that went unanswered. I don't think I can use this routine anyway. After making that change I get an error from GetObjectAPI "Type 'System.Drawing.Bitmap' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."
    Thanks anyway.

  14. #14
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Saving a BITMAP from memory to disk

    Maybe you should try the .Net forum again. Searching, I found some good examples that allow you to save binary data using .Net's StreamWriter, converting image to jpg using a statement like: "PictureBox1.Image.Save(wfStream, System.Drawing.Imaging.ImageFormat.Jpeg)" (post #30 in that link)

    Here are the terms I used when I searched that forum: Bitmap Stream File
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #15
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Saving a BITMAP from memory to disk

    Just in case you did not notice, this thread is 10 years old! Back then there was no .NET...

  16. #16
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Saving a BITMAP from memory to disk

    Quote Originally Posted by CVMichael View Post
    Just in case you did not notice, this thread is 10 years old! Back then there was no .NET...
    I didn't even notice
    I only noticed today's post by MarMan and didn't look at the dates of the previous postings.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  17. #17
    Addicted Member
    Join Date
    Jul 2006
    Posts
    159

    Re: Saving a BITMAP from memory to disk

    Love the idea of saving the bitmap as a string but how do I get the data from .hdc into a string?

  18. #18
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Saving a BITMAP from memory to disk

    John, you are replying to a 15 year-old thread (started in 2000)
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  19. #19
    Addicted Member
    Join Date
    Jul 2006
    Posts
    159

    Re: Saving a BITMAP from memory to disk

    I know - It's still relevant!

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