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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read