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

  • Live Event Date: February 25, 2015 @ 2:00 p.m. ET / 11:00 a.m. PT Secure Shell (SSH) keys provide unmitigated access for privileged users and applications. However, managing and securing these critical privileged credentials poses a real challenge for organizations, putting sensitive data at risk. In fact, more than 50% of organizations report experiencing an SSH Key related compromise. Check out this upcoming eSeminar and join Adam Bosnian, EVP of Global Business Development at CyberArk, as he discusses the …

  • The 3rd Platform of computing, based around the four pillars of mobile computing, social media, big data and analytics, and cloud, is redefining what IT infrastructure needs to provide. Endpoint solutions must meet not only traditional data protection requirements, but also a new set of requirements driven by the explosion in mobile computing. This IDC white paper explores the customer challenges associated with safeguarding data residing on various endpoint devices, including laptops, tablets, and …

Most Popular Programming Stories

More for Developers

RSS Feeds

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