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

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


Comments

  • There are no comments yet. Be the first to comment!

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

Top White Papers and Webcasts

  • Although much publicity around computer security points to hackers and other outside attacks, insider threats can be particularly insidious and dangerous, whether caused by malice or employee negligence. In this report, you learn the eight most significant cybersecurity threats that could impact your organization (at any time), Forbes cited internal threats as No. 3, noting that internal attacks can be "the most devastating" due to the amount of damage privileged users can inflict and the type of data they can …

  • Migrating away from Windows Server 2003 is an investment in your organization's future, and there has never been a better time to begin the migration process. Take the next step to transform your datacenter by upgrading your server platform with leading edge Windows Operating Systems and SanDisk flash solutions.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date