Click here to Skip to main content
Click here to Skip to main content
Go to top

WTLIPicture Viewer: An Update to the WTL BmpView Sample Application

, 29 Jun 2011
Rate this:
Please Sign up or sign in to vote.
An updated version of the WTL BmpView sample application using an OLE Picture object to handle multiple image types
WTLIPicture Viewer Application

Introduction

This article introduces WTLIPicture Viewer, an updated version of the WTL BmpView sample application. WTLIPicture Viewer uses a wrapper for the OLE Picture object and handles multiple image types, including bitmap, cursor, enhanced metafile, icon, gif, jpeg, and windows metafile. Image files can be opened and zoomed in or out, copied from or pasted to the clipboard, and previewed and printed.

The Picture object wrapper is contained in the source file WTLIPicture.h and provides all needed code for using a Picture object with an image viewer like the sample WTLIPicture Viewer. It contains a WTL port and extension of the CPictureHolder class from MFC and also contains classes that provide support for multiple clipboard image formats. In addition, it provides a set of semi-standardized structures, similar to BITMAPFILEHEADER and BITMAPINFOHEADER, for most of the supported image formats.

A Note About PNG

WTLIPicture Viewer does not support PNG images because IPicture predates PNG.

Picture Object

OLE Picture objects provide a language-neutral abstraction for bitmaps, icons, and metafiles. The primary interfaces are IPicture and IPictureDisp. The IPicture interface allows the caller to manage picture properties and to use the picture in graphical rendering. The IPictureDisp interface is derived from IDispatch to provide access to the picture's properties through automation.

The following subsections explain the various methods provided by the CPixT template to simplify use of a Picture Object. Member variable m_pPix is an IPicture pointer.

Create Methods

CreateEmpty() is the basic method provided by CPixT to initialize a Picture object. All other create methods call it, passing a pointer to a filled in PICTDESC structure containing information about the picture.

BOOL CreateEmpty(LPPICTDESC lpPictDesc = NULL, BOOL bOwn = FALSE)
{ // build the PICTDESC structure if not passed in
  if (lpPictDesc == NULL)
  {
    PICTDESC pdesc;
    pdesc.cbSizeofstruct = sizeof(pdesc);
    pdesc.picType = PICTYPE_NONE;
    lpPictDesc = &pdesc;
  }

  // create the IPicture object
  return SUCCEEDED(::OleCreatePictureIndirect(lpPictDesc, IID_IPicture, bOwn,
		   (LPVOID*)&m_pPix)); }

CreateFromBitmap() is a set of three methods that allow initialization of a Picture object from a bitmap resource, a CBitmap pointer, or a bitmap handle. The following code shows the version that accepts a bitmap handle, an optional palette, and a flag indicating whether or not to transfer ownership of the bitmap to the Picture object.

BOOL CreateFromBitmap(HBITMAP hbm, HPALETTE hpal, BOOL bTransferOwnership)
{ PICTDESC pdesc;
  pdesc.cbSizeofstruct = sizeof(pdesc);
  pdesc.picType = PICTYPE_BITMAP;
  pdesc.bmp.hbitmap = hbm;
  pdesc.bmp.hpal = hpal;

  return CreateEmpty(&pdesc, bTransferOwnership); }

CreateFromEnhancedMetafile() supports creation of a Picture object from an Enhanced Metafile.

CreateFromIcon() provides methods that create a Picture object from either an icon resource or an icon handle. It supports both icon and cursor images.

CreateFromMetafile() provides initialization of a Picture object from a Windows Metafile.

Load Methods

These methods provide mechanisms for loading a Picture object from various input sources such as files and streams.

LoadFromDispatch loads a Picture object from an image file and sets the IPictureDisp interface.

BOOL LoadFromDispatch(LPTSTR szFilePath)
{ // create a variant for the file name
  VARIANT varFileName;
  varFileName.vt = VT_BSTR;
  varFileName.bstrVal = CComBSTR(szFilePath);

  LPDISPATCH lpDisp = NULL;

  // load the picture object from the file
  BOOL bResult = SUCCEEDED(::OleLoadPictureFile(varFileName, &lpDisp));

  // initialize the dispatch interface
  if (bResult) lpDisp->QueryInterface(IID_IPicture, (LPVOID*)&m_pPix);

  return bResult; }

LoadFromFile() loads a Picture object from an image file using standard file i/o.

LoadFromIStream() loads from an IStream.

LoadFromISequentialStream() loads the Picture object using an ISequentialStream pointer such as those from an OLE DB provider.

LoadFromPath() loads from a file name or URL. This is the simplest method of loading an image but it is rumored to leak resources.

BOOL LoadFromPath(LPCTSTR szFilePath)
{ return SUCCEEDED(::OleLoadPicturePath(CComBSTR(szFilePath), NULL, 0, 0,
		   IID_IPicture, (LPVOID *)&m_pPix)); }

Save Methods

These methods provide mechanisms for saving a Picture object to a file.

SaveToDispatch() saves a Picture object to an image file using the IPictureDisp interface.

BOOL SaveToDispatch(LPTSTR szFilePath)
{ BOOL bResult = FALSE;
  LPPICTUREDISP pDisp = NULL;

  if (SUCCEEDED(m_pPix->QueryInterface(IID_IPictureDisp, (LPVOID*)&pDisp)))
    BOOL bResult = SUCCEEDED(::OleSavePictureFile((LPDISPATCH)pDisp,
			     CComBSTR(szFilePath)));

  return bResult; }

SaveToFile() saves a Picture object to an image file using standard file I/O.

Render Method

Draws the image that was created or loaded into the IPicture onto a device context. You can pass in a rectangle with values less than the image size to scale down or with values greater than the image size to scale up.

void Render(CDCHandle dc, const CRect& rcRender)
{ long hmWidth;
  long hmHeight;

  m_pPix->get_Width(&hmWidth);
  m_pPix->get_Height(&hmHeight);

  m_pPix->Render(dc, rcRender.left, rcRender.top, rcRender.Width(),
		 rcRender.Height(), 0, hmHeight-1, hmWidth, -hmHeight, NULL); }

Properties

  1. GetAttributes() - returns a DWORD containing transparency and scalability flags
  2. GetDescription() - returns the textual description of the image type
  3. GetHandle() - returns an OLE_HANDLE to the image
  4. GetHandle() - takes a reference to an OLE_HANDLE and sets the value
  5. GetPixInformation() - returns a structure with image information such as size, type, and the first 256 bytes of the image
  6. GetSizeInHiMetric() - takes a SIZE reference and returns height and width in HiMetric
  7. GetSizeInPixels() - as above, but in Pixels
  8. GetType() - returns the numeric image type, such as PICTYPE_BITMAP

Tests

These methods return a BOOL value indicating what type of image the IPicture contains.

  1. IsNull() - m_pPix is null
  2. IsBitmap() - image is a bitmap, GIF, or JPEG
  3. IsMetafile() - image is a windows metafile
  4. IsIcon() - image is an icon or cursor
  5. IsEnhMetafile() - image is an enhanced metafile

Clipboard Helper Classes

WTLIPicture.h contains two classes that help when getting or setting clipboard images. CClipboardFormatDlg is a small dialog to prompt image type selection when more than one type is available on the clipboard. It supports bitmap, enhanced metafile, and windows metafile. CWTLIPictureClipboard provides the copy function for bitmap, icon (converted to bitmap), and both metafile types. It also provides the paste function for bitmap and both types of metafiles.

Semi-standard Structures

WTLIPicture.h provides a set of semi-standardized structures, similar to BITMAPFILEHEADER and BITMAPINFOHEADER. Structures are provided for cursors and icons, jpegs, and enhanced and windows metafiles. The intent of these structures is to provide access to commonly referenced values contained in image file headers. For example, here is the definition of METAFILEHEADER for windows metafiles.

//////////////////////////////////////////////////////////
/* METAFILEHEADER (22 bytes) placeable metafile header. */
/* Metafiles may also start with a METAINFOHEADER only	*/
/* or with a METAFILEPICT clipboard header (see below)	*/
//////////////////////////////////////////////////////////
#include <span class="code-keyword">< pshpack2.h >
</span>typedef struct tagMETAFILEHEADER {
  DWORD mfKey;	    // Magic number (always 0x9AC6CDD7)
  WORD mfHandle;    // Metafile HANDLE number (always 0)
  WORD mfLeft;	    // Left coordinate in metafile units (twips)
  WORD mfTop;	    // Top coordinate in metafile units
  WORD mfRight;     // Right coordinate in metafile units
  WORD mfBottom;    // Bottom coordinate in metafile units
  WORD mfInch;	    // Number of metafile units per inch.
		    // Unscaled = 1440; 720 = 2:1; 2880 = 1:2; etc.
  DWORD mfReserved; // Reserved (always 0)
  WORD mfChecksum;  // Checksum value for previous 10 WORDs
} METAFILEHEADER, FAR *LPMETAFILEHEADER;
#include <span class="code-keyword">< poppack.h ></span>

The include files pshpack2.h and poppack.h are required to byte align the structure because it does not end on a four byte boundary.

Known Issues

  1. PNG images are not supported as IPicture doesn't support PNG
  2. EMF images that are copied to the clipboard and pasted back in WMF format are misaligned
  3. SaveToDispatch() may cause a system crash with large images (> 5 MB)
  4. Slight flickering may occur when a zoomed image is scrolled

Acknowledgements

The CWTLIPictureT template class is a WTL port and extension of CPictureHolder from the Microsoft Foundation Class library. The WTLIPictureViewer application is based on the BmpView sample application distributed with the Windows Template Library.

Terms Of Use

The sample application available with this article is free but is subject to any restrictions placed on the original BmpView sample application and CPictureHolder. The source code provided in WTLIPicture.h is free to use for any purpose as long as CPOL requirements are observed.

THIS SOFTWARE IS DISTRIBUTED AS-IS, WITHOUT WARRANTIES OF ANY KIND.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ed Gadziemski
Founder KwikiVac
United States United States
Ed has over 40 years experience in computer technology and a bachelor's degree in Business Administration. He currently owns an online retail business and previously owned a software consulting firm. During his career, he has led software development departments and created software still in use in the communications and healthcare industries. Ed is a veteran of the United States Army. He lives in Arizona in the United States.
 
This material is copyright 2014 by Ed Gadziemski. Unauthorized use is strictly prohibited. All rights reserved.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberTheAlas2-Oct-12 0:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 29 Jun 2011
Article Copyright 2011 by Ed Gadziemski
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid