A DIBSection wrapper for Win32

, and was sponsored by Dundas.

CDIBSectionLite is a subset of CDIBSection which is used in Dundas Software's Ultimate Paint for MFC component. CDIBSection adds in functionality for transparancy, clipboard functions and image manipulation routines.

Environment: VC 6.0, NT4, Win9x

Introduction

Device Independant Bitmaps (DIBs) offer a means to manipulate and display bitmaps in a form that is independant of the current display setting of your computer. They are also the format of the standard windows .BMP file, and so having a means to load, display and modify DIBs is very handy. DIBs, are created by allocating memory for a bitmap header and for the actual bitmap bits, then calling functions such as SetDIBits to fill in those bits. To actually display the DIB you need to use SetDIBitsToDevice or the DrawDib functions. To modify the bits in a DIB you need to access the individual bits of the bitmap yourself. There are no shortcuts.

Device Dependant Bitmaps (DDBs), on the other hand, only allow the manipulation of bitmaps that are in the same format as your current display device. DIBs can be created in many ways, including via the CBitmap class, via the functions CreateDIBitmap and Createbitmap, or through the LoadImage function. The only option in displaying and manipulating bitmaps is to use the GDI functions BitBlt etc. While DDBs are not able to maintain device independance, they do allow bitmaps to be selected into Device Contexts and manipululated using the GDI functions such as Rectangle and TextOut.

DIBSections are a combination of these two approaches. A DIBSection is created using either the CreateDIBSection function, or by calling LoadImage with the flag LR_CREATEDIBSECTION. DIBSections are DIBs, and so they can be used to manipulate bitmaps that were created for a device other than the display device, yet they can also be manipulated using the usual GDI functions becuase of their associated HBITMAP. In effect you have the independance and power of a DIB, with the ease of use of a DDB. When displaying DIBSection you can use BitBlt, SetDIBitsToDevice or the DrawDib functions.

The only problem with DIBsections, from an MFC programmers point of view, is that there is no DIBSection wrapper. Jeff Prosise, in his book Programming Windows 95 with MFC discusses DIBSections and how great they are, but states that becuase the next version of MFC will have a DIBSection wrapper class, there is no point in him supplying one in his book. Oops! Many updates to MFC have come and gone since that boook was written and still there is no sign of a DIBSection wrapper class.

With the advent of CE, DIBSections have become even more important. Since CE is an abridged version of the Windows operating system, many of the usual APIs we know and love have been left out. If you wish to use DIBs in CE, then your only option is to use DIBSections. In a subsequent article I will extend the class presented here in order to show how to use DIBsections in CE.

Using DIBSections

To create a DIBSection you simply fill in a BITMAPINFOHEADER structure and call CreateDIBSection(). The main things you need to supply are a handle to a DC, a pointer to the BITMAPINFOHEADER structure and the address of a pointer that will point to the image bits. See Zafir's articles on creating DIBs for more information on the BITMAPINFOHEADER - the basic idea is exactly the same. CreateDIBSection will then return a HBITMAP. Hang on to this - it will be very useful.

To display DIBSections you can use

  • SetDIBitsToDevice or SetDIBits. For this you will need the BITMAPINFOHEADER structure that created the image, plus the pointer to the image bits
  • BitBlt. Use the HBITMAP returned by CreateDIBSection
  • DrawDibDraw. Again using the BITMAPINFOHEADER struct and the bits pointer.

The first two options have been dealt with many times. To use the DrawDib functions you need to create a DrawDib DC and then call DrawDibDraw:


    CPalette Palette;         // palette to use
    CDC* pDC;                 // Device context on which to draw image
    CPoint ptSrc, ptDest;     // Source and destination point of image
    CSize sizeSrc, sizeDest;  // Source and Dest. sizees of the image
    BITMAPINFOHEADER* pBitmapInfoHeader;    // bitmap info header info
    LPVOID pBitmapBits;       // Pointer to bitmap bits


    HDRAWDIB hDrawDib = DrawDibOpen();

    DrawDibSetPalette( hDrawDib, (HPALETTE) Palette); 
    DrawDibRealize( hDrawDib,  pDC->GetSafeHdc(), FALSE);
        
    DrawDibDraw(hDrawDib, pDC->GetSafeHdc(), 
                ptDest.x, ptDest.y, sizeDest.cx, sizeDest.cy, 
                pBitmapInfoHeader, pBitmapBits, 
                ptSrc.x, ptSrc.y, sizeSrc.cx, sizeSrc.cy, 
                0);

    DrawDibClose(hDrawDib);
Usually you would create a HDRAWDIB at the start of your program (using DrawDibOpen), and destroy it at the end (using DrawDibClose)

CDIBSectionLite

CDIBSectionLite is a stripped down version of the CDIBSection DIBSection wrapper class used in Ultimate Paint, an image editing library by Dundas Software that replicates the functionality of MS Paint. DIBSections were chosen for this application due to their DIB nature, and becuase of the ease in which they allowed the bitmap bits to be manipulated.

This class provides a simple interface to DIBSections including loading, saving and displaying DIBsections. Full palette support is provided, as well as the options of using the DrawDib routines to provide lightning fast drawing and full dithering. Note that the DrawDib functions are only available for images with at least 8 bits per pixel.

Using CDIBSectionLite

This class is very simple to use. The bitmap can be set using either SetBitmap() (which accepts either a Device dependant or device independant bitmap, or a resource ID) or by using Load(), which allows an image to be loaded from disk. To display the bitmap simply use Draw or Stretch.

eg.

      CDIBSectionLite dibsection;
      dibsection.Load(_T("image.bmp"));
      dibsection.Draw(pDC, CPoint(0,0));  // pDC is of type CDC*
or
      CDIBSectionLite dibsection;
      dibsection.SetBitmap(IDB_BITMAP); 
      dibsection.Draw(pDC, CPoint(0,0));  // pDC is of type CDC*
Note that CDIBsectionLite::Draw() takes an optional third parameter that allows you to specify background drawing. This is useful in a palettized environment when you application is not in the foreground, as it selects the current palette in background, leaving the foreground app looking normal, and you app looking somewhat more respectable than otherwise. See OnQueryNewPalette and OnPaletteChanged functions for more info on foreground and background palette handling.

CDIBsectionLite API

The CDIBsectionLite API includes methods for loading and displaying images, methods to extract information about the image, as well as palette options for getting and setting the current palette. or later.


    void DeleteObject()                           // Deletes the image and frees all memory

    HBITMAP      GetSafeHandle() const            // Gets a HBITMAP handle to the image
    CSize        GetSize() const                  // Gets the size of the image in pixels
    int          GetHeight() const                // Gets the height of the image in pixels
    int          GetWidth() const                 // Gets the width of the image in pixels
    int          GetPlanes() const                // Gets the number of colour planes in the image 
    int          GetBitCount() const              // Gets the bits per pixel for the image 
    LPVOID       GetDIBits()                      // Returns a pointer to the image bits
    LPBITMAPINFO GetBitmapInfo()                  // Returns a pointer a BITMAPINFO structure for the image
    DWORD        GetImageSize() const             // Returns the size of the image (in bytes)
    LPBITMAPINFOHEADER GetBitmapInfoHeader()      // Returns a pointer to a BITMAPINFOHEADER structure
    
    BOOL SetBitmap(UINT nIDResource);             // Loads an image into the object.
    BOOL SetBitmap(LPCTSTR lpszResourceName);     //    nIDResource   - Bitmap resource ID 
    BOOL SetBitmap(HBITMAP hBitmap,               //    lpszResourceName  - Bitmap resource ID
                   CPalette* pPalette = NULL);    //    hBitmap       - existing image handle
    BOOL SetBitmap(LPBITMAPINFO lpBitmapInfo,     //    palette       - palette to be used for image construction
                   LPVOID lpBits);                //    lpBitmapInfo  - pointer to BITMAPINFO structure
                                                  //    lpBits        - pointer to image bits

    CPalette *GetPalette()                        // Return current palette
    BOOL SetPalette(CPalette* pPalette)           // Set current palette
    BOOL SetLogPalette(LOGPALETTE* pLogPalette)   // Set current palette

    BOOL SetDither(BOOL bDither);                 // Use DrawDib to dither?
    BOOL GetDither();                             // Is DrawDib being used to dither?

    BOOL Load(LPCTSTR lpszFileName);              // Load form disk
    BOOL Save(LPCTSTR lpszFileName);              // Save to disk

    BOOL Draw(CDC* pDC, CPoint ptDest,                  // Draw image
              BOOL bForceBackground = FALSE);
    BOOL Stretch(CDC* pDC, CPoint ptDest, CSize size,   // Stretch draw image
                 BOOL bForceBackground = FALSE);          

Download demo project - 56 Kb

Download source - 9.5 Kb



Comments

  • memory leaking problem when using CreateDibSection

    Posted by Legacy on 03/27/2003 12:00am

    Originally posted by: test

    do you have the same problem like this situation?

    it seems that inner implementation within CreateDibSection are some problem to release the memory allcated. so resource be occupied after repeat CreatDIBSection several times. what can i do?

    Reply
  • I have questions so

    Posted by Legacy on 02/08/2003 12:00am

    Originally posted by: Payam Govahi

    Thanks for ur very intresting program ,
    
    I m working on a program for knitting carpets
    I hade may prolems with vc and device contexts
    and I decided to write the program in vb
    but your program give many hopes to me

    I have written the program toobacarpet
    and put it in my simple payamtooba homepage:
    www.geocities.com/payamtooba
    or www.payamsoft.com
    I red other comments,and I have any questions like others and I ll be glad if I could see your answers to their questions

    regards

    Reply
  • Printing the DIB?

    Posted by Legacy on 01/19/2003 12:00am

    Originally posted by: Kyle Brown

    Hi there, I am using your code, and it works great. I have a slight problem, when I use the stretch function in my print function, it seems to work differently on different printers? Do you know if there is something special I have to do to get a consistent print? Thanks.

    Kyle.

    Reply
  • How to use it ?

    Posted by Legacy on 10/16/2002 12:00am

    Originally posted by: Alex Chung

    I am just a VC++ beginner. But I have to work on an imaging project. Could anyone tell me how to make use of the DIBsectionLite functions to read an Bitmap file? I look fwd to receiving your valuable advice. Thanks very much !

    Reply
  • drawdibdraw virus

    Posted by Legacy on 08/27/2002 12:00am

    Originally posted by: Simon

    My computer is displaying a window saying 'DrawDibDraw refused to cooperate' which will not delete, I assume its a virus. Any ideas how to get rid of it?

    Reply
  • great stuff

    Posted by Legacy on 03/13/2002 12:00am

    Originally posted by: philip cunningham

    downloaded the code, linked it to my project and about 3 weeks worth of old work went out of the window. The code is exactly what I was looking for. Thanks for helping out
    

    Reply
  • great stuff

    Posted by Legacy on 03/13/2002 12:00am

    Originally posted by: philip cunningham

    downloaded the code, linked it to my project and about 3 weeks worth of old work went out of the window. The code is exactly what I was looking for. Thanks for helping out
    

    Reply
  • How can I print out a screenshot?

    Posted by Legacy on 10/30/2001 12:00am

    Originally posted by: Karsten Brinkmann

    I want to make a screenshot and print it out.
    I use the following code:

    void CPrintScreenDlg::OnButtonDrucken()
    {
    HWND hWnd = ::GetDesktopWindow();
    CWnd* pWnd = new CWnd;
    pWnd->Attach(hWnd);

    CClientDC dc(pWnd);

    CDC memDC;
    CRect rect;

    memDC.CreateCompatibleDC(&dc);

    pWnd->GetWindowRect(rect);

    m_bitmap.CreateCompatibleBitmap( &dc, rect.Width(), rect.Height() );

    CBitmap* pOldBitmap = memDC.SelectObject(&m_bitmap);

    memDC.BitBlt(0, 0, rect.Width(),rect.Height(), &dc, 0, 0, SRCCOPY);

    m_dibSection.SetBitmap( (HBITMAP) m_bitmap.GetSafeHandle() );

    Drucken();

    memDC.SelectObject(pOldBitmap);
    m_bitmap.Detach();

    pWnd->Detach();

    delete pWnd;

    }

    void CPrintScreenDlg::Drucken()
    {
    DOCINFO DocInfo; // DOCINFO
    CDC dc; // Device Context

    // Druckereinstellung ermitteln
    CPrintDialog PrintDlg( true, PD_RETURNDC );

    // PrintDlg anzeigen ja / nein
    if( PrintDlg.DoModal() != IDOK )
    return;

    DocInfo.cbSize = sizeof(DocInfo);
    DocInfo.lpszDocName = _T("Screenshot");
    DocInfo.lpszOutput = NULL;

    // Drucker DC holen
    dc.Attach( PrintDlg.GetPrinterDC() );
    //dc.ResetDC( mod );

    // nicht ben�tigte Resourcen freigeben
    if( PrintDlg.m_pd.hDevMode )
    ::GlobalFree( PrintDlg.m_pd.hDevMode );
    if( PrintDlg.m_pd.hDevNames )
    ::GlobalFree( PrintDlg.m_pd.hDevNames );

    // Dokumentanfang
    dc.StartDoc( &DocInfo );

    m_dibSection.Draw( &dc, CPoint(0,0) );

    // Dokumentende
    dc.EndPage();
    dc.EndDoc();

    }
    But the printer allways prints a BLACK box.
    What do I wrong?

    thank you

    Reply
  • Serializing CDIBsectionLite

    Posted by Legacy on 08/27/1999 12:00am

    Originally posted by: Rupert

    Thanks for this code, it is really useful. Just a couple of questions; what would I need to do to support serialization in CDIBsectionLite (any code appreciated). Is there a way to get CDIBsection without buying the entire Ultimate paint application ($899 seems a bit much for one class).
    Rupert

    Reply
  • Small "LoadImage" bug fixed

    Posted by Legacy on 06/04/1999 12:00am

    Originally posted by: Chris Maunder

    There was a small "LoadImage" bug that has been fixed as of 4 june 1999.
    Sorry for any inconvenience! This was causing bitmaps with less than 256 colours to appear black (they were not getting loaded properly)

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds