// // 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 // 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 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; }