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
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.
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)
CDIBSectionLiteCDIBSectionLite 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.
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.
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.
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);