locked
Converting from bitmap file buffer to HBITMAP RRS feed

  • Question

  • Hi everyone,
      I'm working with a firewire camera driver which provides a built-in routine to convert from the proprietary raw data format into a bitmap.  However, it doesn't create this bitmap as any kind of bitmap data type, but rather as a single vector file buffer which can then be written to disk using fwrite().  Here's an example of code that would be used to write this buffer to disk:

     
    SaveImageToFile(const char* pFilename, const char* pImage, U32 imageSize)  
    {  
    size_t numBytesWritten;  
    FILE* pFile;  
    pFile = fopen(pFilename, "wb");  
    numBytesWritten = fwrite((void*)pImage, sizeof(char), imageSize, pFile);  
    fclose(pFile);  
    return ((U32)numBytesWritten == imageSize) ? SUCCESS : FAILURE;  
    }  
     
     


    However, rather than writing this buffer to disk as a bitmap file, I want to write it as the next frame in an AVI.  To do this, I'm using a routine which takes its input as an HBITMAP.  Currently, I'm writing the file buffer to disk, then loading it back in as an HBITMAP, and this is of course very slow.  I'd like to eliminate this step, and convert the file buffer to an HBITMAP in code.  How would I go about doing this?
    Thursday, July 31, 2008 5:43 PM

Answers

  •  

    If the data in memory is truly .BMP format, then it consists of

       BITMAPFILEHEADER
       BITMAPINFO
       The pixel bits

    sizeof(BITMAPFILEHEADER) will give you the offset of the BITMAPINFO struct
    BITMAPFILEHEADER.bfOffBits will give you the offset of the pixel bits.

    With those, you have all the info you need to call CreateDIBSection() to get your HBITMAP.

    After creating the DIBsection, copy the pixel bits to the pointer returned by CreateDIBSection().
    You can calculate how many bytes to copy something like this:

       LONG lStride = (((BITMAPINFO.bmiHeader.biWidth * (long)BITMAPINFO.bmiHeader.biBitCount + 31L) & (~31L)) / 8L);
       LONG numberofpixelbytestocopy = abs(BITMAPINFO.bmiHeader.biheight) * lStride;

    Mark


    Mark Salsbery Microsoft MVP - Visual C++
    • Marked as answer by Yan-Fei Wei Tuesday, August 12, 2008 2:29 AM
    • Unmarked as answer by EmoryPhys Wednesday, August 13, 2008 5:42 PM
    • Marked as answer by EmoryPhys Thursday, August 21, 2008 3:25 PM
    Monday, August 11, 2008 9:57 PM

All replies

  • What format is the data that can be written to a file?  .BMP?

    Mark
    Saturday, August 2, 2008 7:24 PM
  • Yeah, the data is intended to be written to a bitmap.  So basically I need a way to turn this bitmap file stream into an HBITMAP.
    Saturday, August 2, 2008 9:06 PM
  • CreateDIBSection().
    • Marked as answer by Yan-Fei Wei Wednesday, August 6, 2008 3:28 AM
    • Unmarked as answer by EmoryPhys Monday, August 11, 2008 4:29 PM
    Monday, August 4, 2008 2:04 AM
  • Why Now you Simply use CImage here.Load the stream from file by CImage .They will give you HBITMAP handle after loading.Have a look in MSDN for CImage everthing is there.

    Thanx

    Rupesh Shukla
    • Marked as answer by Yan-Fei Wei Wednesday, August 6, 2008 3:28 AM
    • Unmarked as answer by EmoryPhys Monday, August 11, 2008 4:29 PM
    • Unmarked as answer by EmoryPhys Monday, August 11, 2008 4:30 PM
    • Unmarked as answer by EmoryPhys Monday, August 11, 2008 4:30 PM
    • Unmarked as answer by EmoryPhys Monday, August 11, 2008 4:30 PM
    Monday, August 4, 2008 7:11 AM
  • Pintu Shukla said:

    Why Now you Simply use CImage here.Load the stream from file by CImage .They will give you HBITMAP handle after loading.Have a look in MSDN for CImage everthing is there.


    The stream isn't being loaded from a file - it is being created by a firewire camera's device driver.  The example code given with the camera SDK only shows how to use the code I included to write the data to a file, and doesn't show how to convert that char* stream into something usable by the standard windows bitmap routines.

    I'm still clueless on this one, so if anyone can help me out it'd be much appreciated.
    Monday, August 11, 2008 7:45 PM
  •  

    If the data in memory is truly .BMP format, then it consists of

       BITMAPFILEHEADER
       BITMAPINFO
       The pixel bits

    sizeof(BITMAPFILEHEADER) will give you the offset of the BITMAPINFO struct
    BITMAPFILEHEADER.bfOffBits will give you the offset of the pixel bits.

    With those, you have all the info you need to call CreateDIBSection() to get your HBITMAP.

    After creating the DIBsection, copy the pixel bits to the pointer returned by CreateDIBSection().
    You can calculate how many bytes to copy something like this:

       LONG lStride = (((BITMAPINFO.bmiHeader.biWidth * (long)BITMAPINFO.bmiHeader.biBitCount + 31L) & (~31L)) / 8L);
       LONG numberofpixelbytestocopy = abs(BITMAPINFO.bmiHeader.biheight) * lStride;

    Mark


    Mark Salsbery Microsoft MVP - Visual C++
    • Marked as answer by Yan-Fei Wei Tuesday, August 12, 2008 2:29 AM
    • Unmarked as answer by EmoryPhys Wednesday, August 13, 2008 5:42 PM
    • Marked as answer by EmoryPhys Thursday, August 21, 2008 3:25 PM
    Monday, August 11, 2008 9:57 PM

  • Mark,
       I think you've got me pointed in the right direction.  From doing some other searching, I think I've confirmed that it's .BMP format data.  Since I was sort of unclear with my initial posts - the function returns a pointer to a char array, where the first two elements of that array are 'B' and 'M'.  Unless I'm confused again, I think that's a BMP.

    Since my data is one large character array, I assume I will have to extract BITMAPFILEHEADER and BITMAPINFO from it.  I'm kind of clueless when it comes to working with offsets, so if you know of some good example code to illustrate how to do this, I'd appreciate a link.

    I apologize if I sound clueless here, so bear with me - if I understand what you're saying right, I need to call CreateDibSection() with the following parameters:

      HDC hdc - need to create a memory Device Context to use here?  I'm not sure which create function I should be using.  would this work?

    HDC hdcCreateCompatibleDC(NULL); 



      CONST BITMAPINFO *pbmi - bitmapinfo taken from my char array.  Do I have to create a bitmapinfo variable first and copy BITMAPINFO out of my array, or can I create a pointer to the position of bitmapinfo?  I'm sorry if this is a basic question, but this whole offset thing confuses the heck out of me!


      UINT iUsage  -  Should this be DIB_RGB_COLORS?  I should have mentioned that I have a grayscale image.


      VOID **ppvBits,          - the pointer I will use to copy the pixel bits


      HANDLE hSection,      NULL


      DWORD dwOffset     ignored if hSection is NULL, can I just leave it out?




    Thanks again for all your help, it's slowly starting to make more sense!
    Wednesday, August 13, 2008 5:41 PM
  • I ended up taking a very different approach, using streams and CImage, but I appreciate the help everyone has offered.  Thanks!
    Thursday, August 21, 2008 3:25 PM
  • Hi EmoryPhys?

    I have burned my brain for about 2 months to got a solution about your issue, and nothing yet..I'm writing the file buffer to disk, then loading it back in as an HBITMAP like you was doing..so I would be very happy if you could explain your approach with a little bit of your code or put on here some link about Cimage.

    Could you do this?

    • Proposed as answer by TcheloBr Sunday, February 6, 2011 6:58 PM
    Wednesday, January 12, 2011 12:09 AM
  • I got solution to my problem and to be clear and quickly i'm pasting the brief solution to the follow scenario;

    - you have a CHAR* buffer with your entire image to be exhibited on hDC display or static Control without have to save char stream to file and reopen by LoadImage to load bmp file.

    Just do the conversion Char* to HBITMAP:

     (MY CHAR STREAM IS : "data")

    //Declarations of bitmaps Structs and DC

    static BITMAPFILEHEADER * pbmfh ;  
    static BITMAPINFO * pbmi ;
    static BYTE * pBits ;
    HBITMAP=bmp1;
    HDC hDC;

    //Just do
    pbmfh=(BITMAPFILEHEADER*)data;

    //Get DC                                                                  
    hDC = GetDC(NULL);

    //Get the bitmap info and bits image data                                                                       
    pbmi = (BITMAPINFO *) (pbmfh + 1) ;
    pBits = (BYTE *) pbmfh + pbmfh->bfOffBits ;
                                                                           
     //Convert DIB to DDB                                                                           
     bmp1 = CreateDIBitmap (hDC,(BITMAPINFOHEADER *) (pbmfh + 1),CBM_INIT, (BYTE *) pBits,(BITMAPINFO *) pbmi,DIB_RGB_COLORS) ;
                                                                            
    //Release DC
    ReleaseDC(NULL, hDC); 

     

    Sunday, February 6, 2011 7:44 PM
  • Hi EmoryPhys

    there will  need to use bitblt function to paste the image after intilizing the above code.pls clear use of bmp1??



    • Edited by ss01oct Friday, August 21, 2015 9:44 AM
    Friday, August 21, 2015 9:43 AM