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

  • 2015 is shaping up to include some of the best innovation the mobile industry has ever experienced. There will be new discoveries, new technologies, and existing giants in the vendor space will test the limits to increase productivity while ensuring the confidentiality, integrity, and availability of data. While all of this innovation is taking place, enterprises must continue to remain vigilant as cybercriminals continue to look for weaknesses to steal company data, and intellectual property by infiltrating …

  • An organization's ability to identify, assess and resolve technical issues is critical to business success. Developer, operations and IT teams must be able to collect and analyze data in real-time if they which to resolve issues quickly without creating additional problems. This article introduces the idea of real-time analytics and demonstrates how log data from different layers of the system and application stack can enable real-time analytics and response.

Most Popular Programming Stories

More for Developers

RSS Feeds

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