Using Placeable Metafiles: Save and Convert to HBITMAP and Raster Formats

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Environment: VC

In same circumstances, developers need to write applications with graphics file export of its own drawings. A common case of graphical export is the Windows metafile (wmf), bitmap, and few other standard raster formats, such as tiff, jpeg, and png. You also need to include the possibility to choose the resolution and color depth for raster formats.

Drawing a Metafile

To draw a metafile, you need to create the metafile device context (DC) and close it after drawing. The metafile DC supports a limited set of GDI functions (See Windows-Format Metafiles in Platform SDK). To illustrate the drawing, see the next example:


// Prepare metafile DC
HDC metafileDC = CreateMetaFile(0);
SIZE &extents = m_sizeExtent;
int savedState = SaveDC(metafileDC);
SetMapMode(metafileDC, MM_ANISOTROPIC);
SetWindowOrgEx(metafileDC, 0, 0, 0);
SetWindowExtEx(metafileDC, extents.cx, extents.cy, 0);
RECT rect = {0 ,0, extents.cx, extents.cy};
RECT *prcBounds = &rectl;
RECT *prcWBounds = &rectl;

// Draw in metafile using GDI API.
Rectangle(metafileDC, prcBounds->left, prcBounds->top,
prcBounds->right, prcBounds->bottom);
// Custom drawing.
// void Draw(HDC hdc, RECT *prcBounds, RECT *prcWBounds = 0)

Draw(metafileDC, prcBounds, prcWBounds);

// Restore initial state.
RestoreDC(metafileDC, savedState);
// Extract HMETAFILE.
HMETAFILE metafile = CloseMetaFile(metafileDC);
// Use this HMETAFILE later. Do not forget to delete it:
// DeleteMetaFile(metafile);

Saving a Metafile

The Windows GDI API provides a way to save and load metafiles on disk. This is the CreateMetafile(LPCTSTR filePath) function. But, using it for these purposes not a good idea. This way, a created metafile doesn’t work with all versions of MS Word and Picture object (IPicture). To avoid these restrictions, you need to save the metafile in a placeable format. In this case, metafile bits are prefixed with a metafile header structure. This structure contains the metafile dimensions and an indication of the placeable metafile. Its size is 22 bytes. The structure is not defined in standard header files; thus, you need to define it explicitly. The next lines of code show how to use the WMFile class to save a placeable metafile. This part of the code can be used in conjunction with the previous one.


WMFile wmfFile(metafile, extents.cx, extents.cy, FALSE);
LPCTSTR filename = _T(“test.wmf”);
wmfFile.save(fileName);

Converting a Metafile to a Bitmap

Converting a metafile to a 24-bit color bitmap is simple. Just follow these steps:

  1. Create the memory DC.
  2. Create the device-independent bitmap.
  3. Select the bitmap to the created memory DC.
  4. Draw in this DC.
  5. Select the old bitmap to DC.

But what about resolution, non-24-bit color depth, and scaling a metafile to a whole bitmap? All of these are implemented in the WMFile class as a getBitmap function. This function takes the required resolution and color depth as arguments and produces a new HBITMAP as its return value.


WMFile wmfFile(metafile, extents.cx, extents.cy, FALSE);
int resolution = 300;
WORD colorDepth = 24;
HBITMAP hBitmap = wmfFile.getBitmap(resolution, colorDepth);

// Manipulate with hBitmap.

DeleteObject(hBitmap);

Now it handles 24, 8, and 4 bits of color depth. To extend it for 16- and 32-bit support, use BITMAPINFOHEADER::biCompression=BI_BITFIELDS and specify the appropriate color mask.

Using Graphics Libraries

There are many graphics libraries that support conversions between various graphical formats. These are GDI+, PaintLib, CxImage, LibTiff, LibJpeg, LibPng, and so forth.
In my work, I use the CxImage library. This is a set of C++ classes, containing encapsulated low-level libraries (such as LibTiff, LibJpeg, LibPng, and so forth.). But, in addition, it provides many features.

Sample Program

The WMFile_demo application was created to show how the WMFile class works. This is a console application. To make WMFile_demo work, you need to specify the output file name as an argument:

     WMFile_demo.exe “c:test.wmf”

As a result, the following path will be created for the Windows metafile and bitmap files; its name will be appended with “.bmp” (“c:test.wmf.bmp”). Use the Draw function in WMFile_demo.cpp to provide your custom drawing.

Downloads


Download demo project – 12 Kb


Download source – 6 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read