WTLIPicture Viewer: An Update to the WTL BmpView Sample Application






4.64/5 (5 votes)
An updated version of the WTL BmpView sample application using an OLE Picture object to handle multiple image types
- Download WTLIPicture Viewer project (includes source) - 40 KB
- Download WTLIPicture.h source code only - 7.7 KB

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
GetAttributes()
- returns aDWORD
containing transparency and scalability flagsGetDescription()
- returns the textual description of the image typeGetHandle()
- returns anOLE_HANDLE
to the imageGetHandle()
- takes a reference to anOLE_HANDLE
and sets the valueGetPixInformation()
- returns a structure with image information such as size, type, and the first 256 bytes of the imageGetSizeInHiMetric()
- takes aSIZE
reference and returns height and width inHiMetric
GetSizeInPixels()
- as above, but inPixels
GetType()
- returns the numeric image type, such asPICTYPE_BITMAP
Tests
These methods return a BOOL
value indicating what type of image the IPicture
contains.
IsNull()
-m_pPix
isnull
IsBitmap()
- image is a bitmap, GIF, or JPEGIsMetafile()
- image is a windows metafileIsIcon()
- image is an icon or cursorIsEnhMetafile()
- 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 < pshpack2.h >
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 < poppack.h >
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
- PNG images are not supported as
IPicture
doesn't support PNG - EMF images that are copied to the clipboard and pasted back in WMF format are misaligned
SaveToDispatch()
may cause a system crash with large images (> 5 MB)- 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.