|
|
//
// loadimag.cpp
//
// implementation of loading a file from disk via an installed graphic filter
//
#include "stdafx.h"
#include "pbrush.h"
#include "imgwnd.h"
#include "imgsuprt.h"
#include "loadimag.h"
#include "bmpstrm.h"
#include "imaging.h"
#include <atlbase.h>
// must define one of the following:
//#define _USE_FLT_API
#ifdef _X86_
#define _USE_IFL_API
#endif
#ifdef _USE_FLT_API
#include "filtapi.h"
#endif
#ifdef _USE_IFL_API
#include "image.h"
#include "interlac.h"
#define MAX_PAL_SIZE 256
#ifdef PNG_SUPPORT // for Portable Network Graphics. As of 12/10/1996 the support was broken
//----------------------------------------------------------------------------
// Places a line of image data from an ADAM 7 interlaced file (i.e., currently
// a PNG file) into its correct position in a memory buffer: this memory
// buffer is essentially an array of pointers to the rows of the image in
// which the pixel data is to be set.
//----------------------------------------------------------------------------
IFLERROR ReadADAM7InterlacedImage(LPBYTE apbImageBuffer[], IFLHANDLE pfpbFROM, int ImageHeight, int ImageWidth, int cbPixelSize, IFLCLASS ImageClass) {
int cRasterLines = iflGetRasterLineCount(pfpbFROM);
ADAM7_STRUCT stAdam7; stAdam7.iImageHeight = ImageHeight; stAdam7.iImageWidth = ImageWidth; stAdam7.Class = ImageClass; stAdam7.cbPixelSize = iflGetBitsPerPixel (pfpbFROM)/8;//cbPixelSize;
stAdam7.iPassLine = 0; LPBYTE pbScanLine = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, ImageWidth * stAdam7.cbPixelSize); wsprintf (buf, TEXT("Pixel size: %d, Size of a scan line: %d\n"), stAdam7.cbPixelSize, ImageWidth*stAdam7.cbPixelSize);
if (pbScanLine == NULL) return IFLERR_MEMORY;
int cTotalScanLines = iADAM7CalculateNumberOfScanLines(&stAdam7);
int iLine; IFLERROR idErr; BOOL fEmptyLine;
for (iLine = 0, idErr = IFLERR_NONE, fEmptyLine = FALSE; idErr == IFLERR_NONE && iLine < (int)cRasterLines; iLine++) { if (!fEmptyLine) idErr = iflRead(pfpbFROM, pbScanLine, 1);
stAdam7.iScanLine = iLine; fEmptyLine = ADAM7AddRowToImageBuffer(apbImageBuffer, pbScanLine, &stAdam7); }
HeapFree(GetProcessHeap(), 0, pbScanLine); return idErr; }
//----------------------------------------------------------------------------
// Deallocates the image space allocated in the function AllocateImageSpace()
//----------------------------------------------------------------------------
LPBYTE *FreeImageSpace(HANDLE hHeap, LPBYTE ppImageSpace[], int height) { if (ppImageSpace != NULL) { for (int i = 0; i < height; i++) { if (ppImageSpace[i] != NULL) { HeapFree(hHeap, 0, ppImageSpace[i]); ppImageSpace[i] = NULL; } }
HeapFree(hHeap, 0, ppImageSpace); ppImageSpace = NULL; }
return ppImageSpace; }
//----------------------------------------------------------------------------
// Allocate some image space: this function will create a dynamic array
// of "height" pointers which each point to an allocated row of bytes of
// size "width".
//----------------------------------------------------------------------------
LPBYTE *AllocateImageSpace(HANDLE hHeap, int height, int width, int cbSize) { LPBYTE *ppImageSpace = (LPBYTE *)HeapAlloc(hHeap, 0, height * sizeof(void *)); TCHAR buf[200]; wsprintf (buf, TEXT("Size of image line: %d\n"), width*cbSize);
if (ppImageSpace != NULL) { // Init the pointers to NULL: this makes error recovery easier
for (int i = 0; i < height; i++) ppImageSpace[i] = NULL;
// NOW allocate the pointer space for the image
for (i = 0; i < height; i++) { ppImageSpace[i] = (LPBYTE)HeapAlloc(hHeap, 0, width * cbSize); if (ppImageSpace[i] == NULL) break; }
if (i < height) // We weren't able to allocate the required space
ppImageSpace = FreeImageSpace(hHeap, ppImageSpace, height); }
return ppImageSpace; } #endif // PNG_SUPPORT
#endif // _USE_IFL_API
// returns a pointer to the extension of a file.
//
// in:
// qualified or unqualfied file name
//
// returns:
// pointer to the extension of this file. if there is no extension
// as in "foo" we return a pointer to the NULL at the end
// of the file
//
// foo.txt ==> ".txt"
// foo ==> ""
// foo. ==> "."
//
LPCTSTR FindExtension(LPCTSTR pszPath) { for (LPCTSTR pszDot = NULL; *pszPath; pszPath = CharNext(pszPath)) { switch (*pszPath) { case TEXT('.'): pszDot = pszPath; // remember the last dot
break; case TEXT('\\'): case TEXT(' '): // extensions can't have spaces
pszDot = NULL; // forget last dot, it was in a directory
break; } }
// if we found the extension, return ptr to the dot, else
// ptr to end of the string (NULL extension)
return pszDot ? pszDot : pszPath; }
//
// GetFilterInfo
//
// 32-bit import filters are listed in the registry...
//
// HKLM\SOFTWARE\Microsoft\Shared Tools\Graphics Filters\Import\XXX
// Path = filename
// Name = friendly name
// Extenstions = file extenstion list
//
#pragma data_seg(".text")
static const TCHAR c_szImpHandlerKey[] = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Import"); static const TCHAR c_szExpHandlerKey[] = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Export"); static const TCHAR c_szName[] = TEXT("Name"); static const TCHAR c_szPath[] = TEXT("Path"); static const TCHAR c_szExts[] = TEXT("Extensions"); static const TCHAR c_szImageAPI[] = TEXT("Image API Enabled Filters"); #pragma data_seg()
BOOL GetInstalledFilters(BOOL bOpenFileDialog, int i, LPTSTR szName, UINT cbName, LPTSTR szExt, UINT cbExt, LPTSTR szHandler, UINT cbHandler, BOOL& bImageAPI) { HKEY hkey; HKEY hkeyT; TCHAR ach[80]; BOOL rc = FALSE; // return code
bImageAPI = FALSE;
if (RegOpenKey(HKEY_LOCAL_MACHINE, bOpenFileDialog ? c_szImpHandlerKey : c_szExpHandlerKey, &hkey) == 0) { if (RegEnumKey(hkey, i, ach, sizeof(ach)/sizeof(ach[0]))==0) { if (RegOpenKey(hkey, ach, &hkeyT) == 0) { if (szName) { szName[0] = 0; RegQueryValueEx(hkeyT, c_szName, NULL, NULL, (LPBYTE)szName, (LPDWORD)&cbName); } if (szExt) { szExt[0] = 0; RegQueryValueEx(hkeyT, c_szExts, NULL, NULL, (LPBYTE)szExt, (LPDWORD)&cbExt); } if (szHandler) { szHandler[0] = 0; RegQueryValueEx(hkeyT, c_szPath, NULL, NULL, (LPBYTE)szHandler, (LPDWORD)&cbHandler); }
RegCloseKey(hkeyT); rc = TRUE; }
TCHAR szEnabledFilters[1024]; DWORD dwEnabledFiltersSize = sizeof(szEnabledFilters);
// Does the filter support Image Library Files API ?
if (RegQueryValueEx(hkey, c_szImageAPI, NULL, NULL, (LPBYTE)szEnabledFilters, &dwEnabledFiltersSize) == 0) { for ( LPCTSTR pExt = _tcstok(szEnabledFilters, _T(" ")); pExt != NULL && bImageAPI != TRUE; pExt = _tcstok(NULL, _T(" "))) { if (_tcsicmp(pExt, ach) == 0) { bImageAPI = TRUE; } } } } RegCloseKey(hkey); }
return rc; }
#ifdef _USE_FLT_API
//
// GetHandlerForFile
//
// find an import/export filter for the given file.
//
BOOL GetHandlerForFile(BOOL bImport, LPCTSTR szFile, LPTSTR szHandler, UINT cb) { TCHAR buf[40]; BOOL rc = FALSE; // return code
*szHandler = 0;
if (szFile == NULL) return FALSE;
// find the extension
LPCTSTR ext = FindExtension(szFile);
BOOL bImageAPI;
for (int i = 0; GetInstalledFilters(bImport, i, NULL, 0, buf, sizeof(buf), szHandler, cb, bImageAPI); i++) { if (lstrcmpi(ext+1, buf) == 0) break; else *szHandler = 0; }
// make sure the handler file does exist
if (*szHandler && GetFileAttributes(szHandler) != -1) rc = TRUE;
return rc; }
//
// FindBitmapInfo
//
// find the DIB bitmap in a memory meta file...
//
LPBITMAPINFOHEADER FindBitmapInfo(LPMETAHEADER pmh) { for (LPMETARECORD pmr = (LPMETARECORD)((LPBYTE)pmh + pmh->mtHeaderSize*2); pmr < (LPMETARECORD)((LPBYTE)pmh + pmh->mtSize*2); pmr = (LPMETARECORD)((LPBYTE)pmr + pmr->rdSize*2)) { switch (pmr->rdFunction) { case META_DIBBITBLT: return (LPBITMAPINFOHEADER)&(pmr->rdParm[8]);
case META_DIBSTRETCHBLT: return (LPBITMAPINFOHEADER)&(pmr->rdParm[10]);
case META_STRETCHDIB: return (LPBITMAPINFOHEADER)&(pmr->rdParm[11]);
case META_SETDIBTODEV: return (LPBITMAPINFOHEADER)&(pmr->rdParm[9]); } }
return NULL; }
#endif // _USE_FLT_API
#ifdef _USE_IFL_API
IFLERROR ReadGIFInterlacedImage(BYTE *ppbImageBuffer, IFLHANDLE pfpbFROM, int ImageHeight, DWORD dwWidthInBytes) { int iLine, iPass, iIntLine, iTempLine; IFLERROR idErr;
WORD InterlaceMultiplier[] = { 8, 8, 4, 2 }; WORD InterlaceOffset[] = { 0, 4, 2, 1 };
idErr = IFLERR_NONE;
iPass = 0; iIntLine = InterlaceOffset[iPass]; iLine = 0; while (idErr == IFLERR_NONE && iLine < ImageHeight) { iTempLine = InterlaceMultiplier[iPass] * iIntLine + InterlaceOffset[iPass]; if (iTempLine >= ImageHeight) { iPass++; iIntLine = 0; iTempLine = InterlaceOffset[iPass]; }
if (iTempLine < ImageHeight) { idErr = iflRead(pfpbFROM, (LPBYTE)ppbImageBuffer+((ImageHeight-iTempLine-1)*dwWidthInBytes), 1); iLine++; } iIntLine++; }
return idErr; } #endif // _USE_IFL_API
//
// LoadDIBFromFile
//
// load a image file using a image import filter. The filters use ANSI strings.
//
HGLOBAL LoadDIBFromFileA(LPCSTR szFileName, GUID *pguidFltTypeUsed) { #ifdef _USE_IFL_API
IFLTYPE iflType;
iflImageType((LPSTR)szFileName, &iflType);
// make sure the image is of a type we know how to import
if (iflType == IFLT_PNG) { return NULL; }
IFLHANDLE iflHandle = iflCreateReadHandle(iflType); if (!iflHandle) { //
// No filter installed for this type
//
return NULL; }
LPBYTE lpStart = 0;
__try {
IFLERROR iflErr = iflOpen(iflHandle, (LPSTR)szFileName, IFLM_READ); if (iflErr != IFLERR_NONE) { iflFreeHandle(iflHandle); return NULL; }
ASSERT(pguidFltTypeUsed);
switch (iflType) { case IFLT_GIF: *pguidFltTypeUsed = WiaImgFmt_GIF; break; case IFLT_BMP: *pguidFltTypeUsed = WiaImgFmt_BMP; break; case IFLT_JPEG: *pguidFltTypeUsed = WiaImgFmt_JPEG; break; case IFLT_TIFF: *pguidFltTypeUsed = WiaImgFmt_TIFF; break; case IFLT_PNG: *pguidFltTypeUsed = WiaImgFmt_PNG; break; case IFLT_PCD: *pguidFltTypeUsed = WiaImgFmt_PHOTOCD; break; default: *pguidFltTypeUsed = WiaImgFmt_UNDEFINED; break; }
IFLCLASS iflClass = iflGetClass(iflHandle); IFLSEQUENCE iflSequence = iflGetSequence(iflHandle); IFLCOMPRESSION iflCompression = iflGetCompression(iflHandle); WORD iBPS = (WORD) iflGetBitsPerChannel(iflHandle);
if (iflClass != IFLCL_RGB && iflClass != IFLCL_PALETTE && iflClass != IFLCL_GRAY && iflClass != IFLCL_BILEVEL) { #ifdef _DEBUG
TRACE(TEXT("LoadDIBFromFile: Not a RGB/PALETTE/GRAY/BW image.\n")); MessageBox (NULL, TEXT("Not a RGB/PALETTE/GRAY/BW image."), TEXT("Loadimag.cpp"), MB_OK); #endif
iflClose(iflHandle); iflFreeHandle(iflHandle); return NULL; }
// get the transparent color
if (iflClass == IFLCL_RGB) { IFLCOLOR iflTransColor; g_bUseTrans = (IFLERR_NONE == iflControl(iflHandle, IFLCMD_TRANS_RGB, 0, 0, &iflTransColor)); if (g_bUseTrans) crTrans = RGB(iflTransColor.wRed, iflTransColor.wGreen, iflTransColor.wBlue); } else // must be IFLCL_PALETTE or IFLCL_GRAY or IFLCL_BILEVEL
{ BYTE byTransIdx; g_bUseTrans = (IFLERR_NONE == iflControl(iflHandle, IFLCMD_TRANS_IDX, 0, 0, &byTransIdx)); if (g_bUseTrans) crTrans = byTransIdx; // need to convert to COLORREF below
}
BITMAPINFOHEADER bi; memset(&bi, 0, sizeof(BITMAPINFOHEADER));
bi.biSize = sizeof(BITMAPINFOHEADER); // should be 0x28 or 40 decimal
bi.biWidth = iflGetWidth(iflHandle); bi.biHeight = iflGetHeight(iflHandle); bi.biPlanes = 1;
if (iflClass == IFLCL_RGB) { #ifdef PNG_SUPPORT
if (iflType == IFLT_PNG) { bi.biBitCount = iBPS*3; } else #endif // PNG_SUPPORT
{ bi.biBitCount = (WORD) iflGetBitsPerPixel (iflHandle); } } else // must be IFLCL_PALETTE or IFLCL_GRAY or IFLCL_BILEVEL
{ bi.biBitCount = 8; }
bi.biCompression = 0; // convert width in pixels to bytes after rounding it up first
DWORD dwWidthInBytes = ((bi.biWidth * bi.biBitCount + 31) & ~31)/8; bi.biSizeImage = abs(bi.biHeight) * dwWidthInBytes; // bi.biXPelsPerMeter = 0;
// bi.biYPelsPerMeter = 0;
if (iflClass == IFLCL_PALETTE || iflClass == IFLCL_GRAY || iflClass == IFLCL_BILEVEL) bi.biClrUsed = MAX_PAL_SIZE; // bi.biClrImportant = 0;
LPBYTE lpBMP;
if ((lpBMP = lpStart = (LPBYTE) GlobalAlloc(GMEM_FIXED, bi.biSize + bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage)) == NULL) goto exit;
memcpy(lpBMP, &bi, bi.biSize); lpBMP += bi.biSize;
BYTE byTemp; int i, j;
switch (iflSequence) { case IFLSEQ_TOPDOWN: switch (iflClass) { case IFLCL_RGB:
lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage - dwWidthInBytes; for (i = 0; i < abs(bi.biHeight); lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1); // need to swap RED with BLUE for internal DIB display
for (j = 0; j < bi.biWidth*3; j+=3) { byTemp = *(lpBMP+j); *(lpBMP+j) = *(lpBMP+j+2); *(lpBMP+j+2) = byTemp; } } break;
case IFLCL_PALETTE:
// get palette info first...
RGBTRIPLE Pal3[MAX_PAL_SIZE]; RGBQUAD Pal4[MAX_PAL_SIZE]; ZeroMemory (Pal3, MAX_PAL_SIZE*(sizeof(RGBTRIPLE))); iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
for (i = 0; i < MAX_PAL_SIZE; i++) { Pal4[i].rgbBlue = Pal3[i].rgbtRed; Pal4[i].rgbGreen = Pal3[i].rgbtGreen; Pal4[i].rgbRed = Pal3[i].rgbtBlue; Pal4[i].rgbReserved = 0; } memcpy(lpBMP, Pal4, sizeof(Pal4));
if (g_bUseTrans) // convert the transparent color index to COLORREF
crTrans = RGB(Pal4[crTrans].rgbRed,Pal4[crTrans].rgbGreen, Pal4[crTrans].rgbBlue);
lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1); }
break;
case IFLCL_GRAY:
// get palette info first...
//BYTE PalGray[MAX_PAL_SIZE];
//iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &PalGray);
for (i = 0; i < MAX_PAL_SIZE; i++) { Pal4[i].rgbBlue = (BYTE) i;//PalGray[i];
Pal4[i].rgbGreen = (BYTE) i;//PalGray[i];
Pal4[i].rgbRed = (BYTE) i;//PalGray[i];
Pal4[i].rgbReserved = 0; } memcpy(lpBMP, Pal4, sizeof(Pal4));
if (g_bUseTrans) // convert the transparent color index to COLORREF
crTrans = RGB(Pal4[crTrans].rgbRed, Pal4[crTrans].rgbGreen, Pal4[crTrans].rgbBlue);
lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1); }
break;
case IFLCL_BILEVEL:
// set color Black
Pal4[0].rgbBlue = 0; Pal4[0].rgbGreen = 0; Pal4[0].rgbRed = 0; Pal4[0].rgbReserved = 0;
// set color White
Pal4[1].rgbBlue = 255; Pal4[1].rgbGreen = 255; Pal4[1].rgbRed = 255; Pal4[1].rgbReserved = 0;
memcpy(lpBMP, Pal4, sizeof(Pal4));
if (g_bUseTrans) // convert the transparent color index to COLORREF
crTrans = RGB(Pal4[crTrans].rgbRed, Pal4[crTrans].rgbGreen, Pal4[crTrans].rgbBlue);
lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1); } break;
default: // currently not supported
break; } break;
case IFLSEQ_BOTTOMUP:
lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage - dwWidthInBytes;
for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1);
// need to swap RED with BLUE for internal DIB display
for (j = 0; j < bi.biWidth*3; j+=3) { byTemp = *(lpBMP+j); *(lpBMP+j) = *(lpBMP+j+2); *(lpBMP+j+2) = byTemp; } } break;
case IFLSEQ_GIF_INTERLACED: {
// get color palette info first...
RGBTRIPLE Pal3[MAX_PAL_SIZE]; RGBQUAD Pal4[MAX_PAL_SIZE]; iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
for (i = 0; i < MAX_PAL_SIZE; i++) { Pal4[i].rgbBlue = Pal3[i].rgbtRed; Pal4[i].rgbGreen = Pal3[i].rgbtGreen; Pal4[i].rgbRed = Pal3[i].rgbtBlue; Pal4[i].rgbReserved = 0; } memcpy(lpBMP, Pal4, sizeof(Pal4));
if (g_bUseTrans) // convert the transparent color index to COLORREF
crTrans = RGB(Pal4[crTrans].rgbRed,Pal4[crTrans].rgbGreen, Pal4[crTrans].rgbBlue);
LPBYTE lpTemp = lpBMP + sizeof(Pal4); ReadGIFInterlacedImage (lpTemp, iflHandle, bi.biHeight, dwWidthInBytes);
} break; /* case 1010101:
{
int IM[] = { 8, 8, 4, 2 }; // interlace multiplier
//int IO[] = { 1, 5, 3 ,2 }; // interface offset
int IO[] = { 0, 4, 2,1 };
for (j = 0; j < 4; j++) { lpBMP = lpTemp + bi.biSizeImage - dwWidthInBytes*IO[j]; for (i = 0; i < abs(bi.biHeight) && lpBMP >= lpTemp; lpBMP-=dwWidthInBytes*IM[j], i+=8) { // read in one line at a time
iflRead(iflHandle, (LPBYTE)lpBMP, 1); } }
break; }*/ #ifdef PNG_SUPPORT
case IFLSEQ_ADAM7_INTERLACED: {
// get color palette info first...
RGBTRIPLE Pal3[MAX_PAL_SIZE]; RGBQUAD Pal4[MAX_PAL_SIZE]; iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
for (i = 0; i < MAX_PAL_SIZE; i++) { Pal4[i].rgbBlue = Pal3[i].rgbtRed; Pal4[i].rgbGreen = Pal3[i].rgbtGreen; Pal4[i].rgbRed = Pal3[i].rgbtBlue; Pal4[i].rgbReserved = 0; } memcpy(lpBMP, Pal4, sizeof(Pal4));
if (g_bUseTrans) // convert the transparent color index to COLORREF
crTrans = RGB(Pal4[crTrans].rgbRed, Pal4[crTrans].rgbGreen, Pal4[crTrans].rgbBlue); /////////////////////////////
HANDLE hHeap = GetProcessHeap(); LPBYTE *ppbRGBRowPtrs =(LPBYTE *)AllocateImageSpace(hHeap, bi.biHeight, dwWidthInBytes, /*bi.biWidth, */sizeof(BYTE));
if (ppbRGBRowPtrs != NULL) { // First get the image. This function will de-interlace the image
// AND any alpha channel information: it will also resize the alpha
// channel data structure to the image height from the number of
// raster lines, if necessary.
iflErr = ReadADAM7InterlacedImage(ppbRGBRowPtrs, iflHandle, bi.biHeight, bi.biWidth, sizeof(BYTE)*3, iflClass); /////////////////////////////
if (iflErr == IFLERR_NONE) { lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage - dwWidthInBytes; for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++) { // read in one line at a time
memcpy((LPBYTE)lpBMP, ppbRGBRowPtrs[i], dwWidthInBytes);
// need to swap RED with BLUE for internal DIB display
for (j = 0; j < bi.biWidth*3; j+=3) { byTemp = *(lpBMP+j); *(lpBMP+j) = *(lpBMP+j+2); *(lpBMP+j+2) = byTemp; } } }
ppbRGBRowPtrs = (LPBYTE *)FreeImageSpace(hHeap, ppbRGBRowPtrs, bi.biHeight); } break;
} #endif // PNG_SUPPORT
default: break; }
} __except(EXCEPTION_EXECUTE_HANDLER) { }
exit: iflClose(iflHandle); iflFreeHandle(iflHandle);
return (HGLOBAL)lpStart;
#endif // _USE_IFL_API
//////////////////////////////////////////////////////////////////////////////
#ifdef _USE_FLT_API
HINSTANCE hLib = NULL; FILESPEC fileSpec; // file to load
GRPI pict; UINT rc; // return code
HANDLE hPrefMem = NULL; // filter-supplied preferences
UINT wFilterType; // 2 = graphics filter
char szHandler[128]; HGLOBAL hDib = NULL;
PFNGetFilterInfo lpfnGetFilterInfo; PFNImportGr lpfnImportGr;
if (!GetHandlerForFile(TRUE, szFileName, szHandler, sizeof(szHandler))) return FALSE;
if (szHandler[0] == 0) return FALSE;
if ((hLib = LoadLibrary(szHandler)) == NULL) goto exit;
// get a pointer to the ImportGR function
lpfnGetFilterInfo = (PFNGetFilterInfo)GetProcAddress(hLib, "GetFilterInfo"); lpfnImportGr = (PFNImportGr)GetProcAddress(hLib, "ImportGr");
if (lpfnGetFilterInfo == NULL) lpfnGetFilterInfo = (PFNGetFilterInfo)GetProcAddress(hLib, "GetFilterInfo@16");
if (lpfnImportGr == NULL) lpfnImportGr = (PFNImportGr)GetProcAddress(hLib, "ImportGr@16");
if (lpfnImportGr == NULL) goto exit;
if (lpfnGetFilterInfo != NULL) { wFilterType = (*lpfnGetFilterInfo) ((short) 2, // interface version no.
(char *)NULL, // unused
(HANDLE *) &hPrefMem, // fill in: preferences
(DWORD) 0x00020000); // unused in Windows
// the return value is the type of filter: 0=error,
// 1=text-filter, 2=graphics-filter
if (wFilterType != 2) goto exit; }
fileSpec.slippery = FALSE; // TRUE if file may disappear
fileSpec.write = FALSE; // TRUE if open for write
fileSpec.unnamed = FALSE; // TRUE if unnamed
fileSpec.linked = FALSE; // Linked to an FS FCB
fileSpec.mark = FALSE; // Generic mark bit
fileSpec.dcbFile = 0L; //the converters need a pathname without spaces...
GetShortPathName(szFileName, fileSpec.szName, sizeof(fileSpec.szName));
pict.hmf = NULL;
rc = (*lpfnImportGr) (NULL, // "the target DC" (printer?)
(FILESPEC *) &fileSpec, // file to read
(GRPI *) &pict, // fill in: result metafile
(HANDLE) hPrefMem); // preferences memory
if (pict.hmf != NULL) { if (rc == 0) { // find the BITMAPINFO in the returned metafile
LPMETAHEADER lpMetaHeader = (LPMETAHEADER) GlobalLock(pict.hmf);
LPBITMAPINFOHEADER lpbi = FindBitmapInfo(lpMetaHeader);
if (lpbi != NULL) { // copy the DIB
SIZE_T nSize = FindDibSize(lpbi);
hDib = GlobalAlloc(GMEM_FIXED, nSize);
CopyMemory(hDib, lpbi, nSize); }
GlobalUnlock(pict.hmf); }
GlobalFree(pict.hmf); }
exit: if (hPrefMem != NULL) GlobalFree(hPrefMem);
if (hLib) FreeLibrary(hLib);
return hDib;
#endif // _USE_FLT_API
return NULL; }
CGdiplusInit::CGdiplusInit( Gdiplus::DebugEventProc debugEventCallback /*= 0*/, BOOL suppressBackgroundThread /*= FALSE*/, BOOL suppressExternalCodecs /*= FALSE*/ ) { Gdiplus::GdiplusStartupInput StartupInput( debugEventCallback, suppressBackgroundThread, suppressExternalCodecs );
StartupStatus = GdiplusSafeStartup(&Token, &StartupInput, this); }
CGdiplusInit::~CGdiplusInit() { if (StartupStatus == Gdiplus::Ok) { Gdiplus::GdiplusShutdown(Token); } }
Gdiplus::Status CGdiplusInit::GdiplusSafeStartup( ULONG_PTR *token, const Gdiplus::GdiplusStartupInput *input, Gdiplus::GdiplusStartupOutput *output ) { __try { return Gdiplus::GdiplusStartup(token, input, output); } __except(EXCEPTION_EXECUTE_HANDLER) { return Gdiplus::GdiplusNotInitialized; } }
BOOL GetGdiplusDecoders(UINT *pnCodecs, Gdiplus::ImageCodecInfo **ppCodecs) { ASSERT(pnCodecs); ASSERT(ppCodecs);
*ppCodecs = 0; *pnCodecs = 0;
if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok) { __try { UINT cbCodecs;
if (Gdiplus::GetImageDecodersSize(pnCodecs, &cbCodecs) == Gdiplus::Ok) { if (*pnCodecs > 0) { *ppCodecs = (Gdiplus::ImageCodecInfo *) LocalAlloc(LMEM_FIXED, cbCodecs);
if (*ppCodecs != 0) { if (Gdiplus::GetImageDecoders(*pnCodecs, cbCodecs, *ppCodecs) == Gdiplus::Ok) { return TRUE; } } } } } __except(EXCEPTION_EXECUTE_HANDLER) { }
LocalFree(*ppCodecs);
*ppCodecs = 0; *pnCodecs = 0; }
return FALSE; }
BOOL GetGdiplusEncoders(UINT *pnCodecs, Gdiplus::ImageCodecInfo **ppCodecs) { ASSERT(pnCodecs); ASSERT(ppCodecs);
*ppCodecs = 0; *pnCodecs = 0;
if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok) { __try { UINT cbCodecs;
if (Gdiplus::GetImageEncodersSize(pnCodecs, &cbCodecs) == Gdiplus::Ok) { if (*pnCodecs > 0) { *ppCodecs = (Gdiplus::ImageCodecInfo *) LocalAlloc(LMEM_FIXED, cbCodecs);
if (*ppCodecs != 0) { if (Gdiplus::GetImageEncoders(*pnCodecs, cbCodecs, *ppCodecs) == Gdiplus::Ok) { return TRUE; } } } } } __except(EXCEPTION_EXECUTE_HANDLER) { }
LocalFree(*ppCodecs);
*ppCodecs = 0; *pnCodecs = 0; }
return FALSE; }
BOOL GetClsidOfEncoder(REFGUID guidFormatID, CLSID *pClsid) { Gdiplus::ImageCodecInfo *pCodecs = 0; UINT nCodecs = 0;
GetGdiplusEncoders(&nCodecs, &pCodecs);
for (UINT i = 0; i < nCodecs; ++i) { if (pCodecs[i].FormatID == guidFormatID) { if (pClsid) { *pClsid = pCodecs[i].Clsid; }
LocalFree(pCodecs);
return TRUE; } }
LocalFree(pCodecs);
return FALSE; }
HGLOBAL LoadDIBGdiplus(LPCTSTR szFileName, GUID *pguidFltTypeUsed) { // check that the BMP encoder exists
CLSID ClsidBmpEncoder;
if (GetClsidOfEncoder(WiaImgFmt_BMP, &ClsidBmpEncoder)) { // let GDI+ import the file
USES_CONVERSION;
Gdiplus::Bitmap image(T2CW(szFileName));
if (image.GetLastStatus() == Gdiplus::Ok) { // read the image type
ASSERT(pguidFltTypeUsed);
image.GetRawFormat(pguidFltTypeUsed);
// create a stream that emulates a bmp file
CComPtr<CBmpStream> pStream; if (CBmpStream::Create(&pStream) == S_OK) { // convert the image into a BMP
if (image.Save(pStream, &ClsidBmpEncoder, 0) == Gdiplus::Ok) { return pStream->GetBuffer(); }
pStream->FreeBuffer(); } } }
return 0; }
HGLOBAL LoadDIBFromFile(LPCTSTR szFileName, GUID *pguidFltTypeUsed) { // Try GDI+ filters first. If it fails to convert the image or
// if it's not available, try the old method
HGLOBAL hResult = 0;
if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok) { __try { hResult = LoadDIBGdiplus(szFileName, pguidFltTypeUsed); } __except(EXCEPTION_EXECUTE_HANDLER) { } }
if (!hResult) { USES_CONVERSION;
hResult = LoadDIBFromFileA(T2CA(szFileName), pguidFltTypeUsed); }
return hResult; }
|