Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1124 lines
35 KiB

  1. //
  2. // loadimag.cpp
  3. //
  4. // implementation of loading a file from disk via an installed graphic filter
  5. //
  6. #include "stdafx.h"
  7. #include "pbrush.h"
  8. #include "imgwnd.h"
  9. #include "imgsuprt.h"
  10. #include "loadimag.h"
  11. #include "bmpstrm.h"
  12. #include "imaging.h"
  13. #include <atlbase.h>
  14. // must define one of the following:
  15. //#define _USE_FLT_API
  16. #ifdef _X86_
  17. #define _USE_IFL_API
  18. #endif
  19. #ifdef _USE_FLT_API
  20. #include "filtapi.h"
  21. #endif
  22. #ifdef _USE_IFL_API
  23. #include "image.h"
  24. #include "interlac.h"
  25. #define MAX_PAL_SIZE 256
  26. #ifdef PNG_SUPPORT // for Portable Network Graphics. As of 12/10/1996 the support was broken
  27. //----------------------------------------------------------------------------
  28. // Places a line of image data from an ADAM 7 interlaced file (i.e., currently
  29. // a PNG file) into its correct position in a memory buffer: this memory
  30. // buffer is essentially an array of pointers to the rows of the image in
  31. // which the pixel data is to be set.
  32. //----------------------------------------------------------------------------
  33. IFLERROR ReadADAM7InterlacedImage(LPBYTE apbImageBuffer[], IFLHANDLE pfpbFROM,
  34. int ImageHeight, int ImageWidth, int cbPixelSize,
  35. IFLCLASS ImageClass)
  36. {
  37. int cRasterLines = iflGetRasterLineCount(pfpbFROM);
  38. ADAM7_STRUCT stAdam7;
  39. stAdam7.iImageHeight = ImageHeight;
  40. stAdam7.iImageWidth = ImageWidth;
  41. stAdam7.Class = ImageClass;
  42. stAdam7.cbPixelSize = iflGetBitsPerPixel (pfpbFROM)/8;//cbPixelSize;
  43. stAdam7.iPassLine = 0;
  44. LPBYTE pbScanLine = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, ImageWidth * stAdam7.cbPixelSize);
  45. wsprintf (buf, TEXT("Pixel size: %d, Size of a scan line: %d\n"), stAdam7.cbPixelSize,
  46. ImageWidth*stAdam7.cbPixelSize);
  47. if (pbScanLine == NULL)
  48. return IFLERR_MEMORY;
  49. int cTotalScanLines = iADAM7CalculateNumberOfScanLines(&stAdam7);
  50. int iLine;
  51. IFLERROR idErr;
  52. BOOL fEmptyLine;
  53. for (iLine = 0, idErr = IFLERR_NONE, fEmptyLine = FALSE;
  54. idErr == IFLERR_NONE && iLine < (int)cRasterLines;
  55. iLine++)
  56. {
  57. if (!fEmptyLine)
  58. idErr = iflRead(pfpbFROM, pbScanLine, 1);
  59. stAdam7.iScanLine = iLine;
  60. fEmptyLine = ADAM7AddRowToImageBuffer(apbImageBuffer, pbScanLine, &stAdam7);
  61. }
  62. HeapFree(GetProcessHeap(), 0, pbScanLine);
  63. return idErr;
  64. }
  65. //----------------------------------------------------------------------------
  66. // Deallocates the image space allocated in the function AllocateImageSpace()
  67. //----------------------------------------------------------------------------
  68. LPBYTE *FreeImageSpace(HANDLE hHeap, LPBYTE ppImageSpace[], int height)
  69. {
  70. if (ppImageSpace != NULL)
  71. {
  72. for (int i = 0; i < height; i++)
  73. {
  74. if (ppImageSpace[i] != NULL)
  75. {
  76. HeapFree(hHeap, 0, ppImageSpace[i]);
  77. ppImageSpace[i] = NULL;
  78. }
  79. }
  80. HeapFree(hHeap, 0, ppImageSpace);
  81. ppImageSpace = NULL;
  82. }
  83. return ppImageSpace;
  84. }
  85. //----------------------------------------------------------------------------
  86. // Allocate some image space: this function will create a dynamic array
  87. // of "height" pointers which each point to an allocated row of bytes of
  88. // size "width".
  89. //----------------------------------------------------------------------------
  90. LPBYTE *AllocateImageSpace(HANDLE hHeap, int height, int width, int cbSize)
  91. {
  92. LPBYTE *ppImageSpace = (LPBYTE *)HeapAlloc(hHeap, 0, height * sizeof(void *));
  93. TCHAR buf[200];
  94. wsprintf (buf, TEXT("Size of image line: %d\n"), width*cbSize);
  95. if (ppImageSpace != NULL)
  96. {
  97. // Init the pointers to NULL: this makes error recovery easier
  98. for (int i = 0; i < height; i++)
  99. ppImageSpace[i] = NULL;
  100. // NOW allocate the pointer space for the image
  101. for (i = 0; i < height; i++)
  102. {
  103. ppImageSpace[i] = (LPBYTE)HeapAlloc(hHeap, 0, width * cbSize);
  104. if (ppImageSpace[i] == NULL)
  105. break;
  106. }
  107. if (i < height) // We weren't able to allocate the required space
  108. ppImageSpace = FreeImageSpace(hHeap, ppImageSpace, height);
  109. }
  110. return ppImageSpace;
  111. }
  112. #endif // PNG_SUPPORT
  113. #endif // _USE_IFL_API
  114. // returns a pointer to the extension of a file.
  115. //
  116. // in:
  117. // qualified or unqualfied file name
  118. //
  119. // returns:
  120. // pointer to the extension of this file. if there is no extension
  121. // as in "foo" we return a pointer to the NULL at the end
  122. // of the file
  123. //
  124. // foo.txt ==> ".txt"
  125. // foo ==> ""
  126. // foo. ==> "."
  127. //
  128. LPCTSTR FindExtension(LPCTSTR pszPath)
  129. {
  130. for (LPCTSTR pszDot = NULL; *pszPath; pszPath = CharNext(pszPath))
  131. {
  132. switch (*pszPath)
  133. {
  134. case TEXT('.'):
  135. pszDot = pszPath; // remember the last dot
  136. break;
  137. case TEXT('\\'):
  138. case TEXT(' '): // extensions can't have spaces
  139. pszDot = NULL; // forget last dot, it was in a directory
  140. break;
  141. }
  142. }
  143. // if we found the extension, return ptr to the dot, else
  144. // ptr to end of the string (NULL extension)
  145. return pszDot ? pszDot : pszPath;
  146. }
  147. //
  148. // GetFilterInfo
  149. //
  150. // 32-bit import filters are listed in the registry...
  151. //
  152. // HKLM\SOFTWARE\Microsoft\Shared Tools\Graphics Filters\Import\XXX
  153. // Path = filename
  154. // Name = friendly name
  155. // Extenstions = file extenstion list
  156. //
  157. #pragma data_seg(".text")
  158. static const TCHAR c_szImpHandlerKey[] = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Import");
  159. static const TCHAR c_szExpHandlerKey[] = TEXT("SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Export");
  160. static const TCHAR c_szName[] = TEXT("Name");
  161. static const TCHAR c_szPath[] = TEXT("Path");
  162. static const TCHAR c_szExts[] = TEXT("Extensions");
  163. static const TCHAR c_szImageAPI[] = TEXT("Image API Enabled Filters");
  164. #pragma data_seg()
  165. BOOL GetInstalledFilters(BOOL bOpenFileDialog, int i, LPTSTR szName, UINT cbName,
  166. LPTSTR szExt, UINT cbExt, LPTSTR szHandler, UINT cbHandler, BOOL& bImageAPI)
  167. {
  168. HKEY hkey;
  169. HKEY hkeyT;
  170. TCHAR ach[80];
  171. BOOL rc = FALSE; // return code
  172. bImageAPI = FALSE;
  173. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  174. bOpenFileDialog ? c_szImpHandlerKey : c_szExpHandlerKey, &hkey) == 0)
  175. {
  176. if (RegEnumKey(hkey, i, ach, sizeof(ach)/sizeof(ach[0]))==0)
  177. {
  178. if (RegOpenKey(hkey, ach, &hkeyT) == 0)
  179. {
  180. if (szName)
  181. {
  182. szName[0] = 0;
  183. RegQueryValueEx(hkeyT, c_szName, NULL, NULL,
  184. (LPBYTE)szName, (LPDWORD)&cbName);
  185. }
  186. if (szExt)
  187. {
  188. szExt[0] = 0;
  189. RegQueryValueEx(hkeyT, c_szExts, NULL, NULL,
  190. (LPBYTE)szExt, (LPDWORD)&cbExt);
  191. }
  192. if (szHandler)
  193. {
  194. szHandler[0] = 0;
  195. RegQueryValueEx(hkeyT, c_szPath, NULL, NULL,
  196. (LPBYTE)szHandler, (LPDWORD)&cbHandler);
  197. }
  198. RegCloseKey(hkeyT);
  199. rc = TRUE;
  200. }
  201. TCHAR szEnabledFilters[1024];
  202. DWORD dwEnabledFiltersSize = sizeof(szEnabledFilters);
  203. // Does the filter support Image Library Files API ?
  204. if (RegQueryValueEx(hkey, c_szImageAPI, NULL, NULL,
  205. (LPBYTE)szEnabledFilters, &dwEnabledFiltersSize) == 0)
  206. {
  207. for (
  208. LPCTSTR pExt = _tcstok(szEnabledFilters, _T(" "));
  209. pExt != NULL && bImageAPI != TRUE;
  210. pExt = _tcstok(NULL, _T(" ")))
  211. {
  212. if (_tcsicmp(pExt, ach) == 0)
  213. {
  214. bImageAPI = TRUE;
  215. }
  216. }
  217. }
  218. }
  219. RegCloseKey(hkey);
  220. }
  221. return rc;
  222. }
  223. #ifdef _USE_FLT_API
  224. //
  225. // GetHandlerForFile
  226. //
  227. // find an import/export filter for the given file.
  228. //
  229. BOOL GetHandlerForFile(BOOL bImport, LPCTSTR szFile, LPTSTR szHandler, UINT cb)
  230. {
  231. TCHAR buf[40];
  232. BOOL rc = FALSE; // return code
  233. *szHandler = 0;
  234. if (szFile == NULL)
  235. return FALSE;
  236. // find the extension
  237. LPCTSTR ext = FindExtension(szFile);
  238. BOOL bImageAPI;
  239. for (int i = 0;
  240. GetInstalledFilters(bImport, i, NULL, 0, buf, sizeof(buf), szHandler, cb, bImageAPI);
  241. i++)
  242. {
  243. if (lstrcmpi(ext+1, buf) == 0)
  244. break;
  245. else
  246. *szHandler = 0;
  247. }
  248. // make sure the handler file does exist
  249. if (*szHandler && GetFileAttributes(szHandler) != -1)
  250. rc = TRUE;
  251. return rc;
  252. }
  253. //
  254. // FindBitmapInfo
  255. //
  256. // find the DIB bitmap in a memory meta file...
  257. //
  258. LPBITMAPINFOHEADER FindBitmapInfo(LPMETAHEADER pmh)
  259. {
  260. for (LPMETARECORD pmr = (LPMETARECORD)((LPBYTE)pmh + pmh->mtHeaderSize*2);
  261. pmr < (LPMETARECORD)((LPBYTE)pmh + pmh->mtSize*2);
  262. pmr = (LPMETARECORD)((LPBYTE)pmr + pmr->rdSize*2))
  263. {
  264. switch (pmr->rdFunction)
  265. {
  266. case META_DIBBITBLT:
  267. return (LPBITMAPINFOHEADER)&(pmr->rdParm[8]);
  268. case META_DIBSTRETCHBLT:
  269. return (LPBITMAPINFOHEADER)&(pmr->rdParm[10]);
  270. case META_STRETCHDIB:
  271. return (LPBITMAPINFOHEADER)&(pmr->rdParm[11]);
  272. case META_SETDIBTODEV:
  273. return (LPBITMAPINFOHEADER)&(pmr->rdParm[9]);
  274. }
  275. }
  276. return NULL;
  277. }
  278. #endif // _USE_FLT_API
  279. #ifdef _USE_IFL_API
  280. IFLERROR ReadGIFInterlacedImage(BYTE *ppbImageBuffer,
  281. IFLHANDLE pfpbFROM,
  282. int ImageHeight, DWORD dwWidthInBytes)
  283. {
  284. int iLine, iPass, iIntLine, iTempLine;
  285. IFLERROR idErr;
  286. WORD InterlaceMultiplier[] = { 8, 8, 4, 2 };
  287. WORD InterlaceOffset[] = { 0, 4, 2, 1 };
  288. idErr = IFLERR_NONE;
  289. iPass = 0;
  290. iIntLine = InterlaceOffset[iPass];
  291. iLine = 0;
  292. while (idErr == IFLERR_NONE && iLine < ImageHeight)
  293. {
  294. iTempLine = InterlaceMultiplier[iPass] * iIntLine + InterlaceOffset[iPass];
  295. if (iTempLine >= ImageHeight)
  296. {
  297. iPass++;
  298. iIntLine = 0;
  299. iTempLine = InterlaceOffset[iPass];
  300. }
  301. if (iTempLine < ImageHeight)
  302. {
  303. idErr = iflRead(pfpbFROM,
  304. (LPBYTE)ppbImageBuffer+((ImageHeight-iTempLine-1)*dwWidthInBytes),
  305. 1);
  306. iLine++;
  307. }
  308. iIntLine++;
  309. }
  310. return idErr;
  311. }
  312. #endif // _USE_IFL_API
  313. //
  314. // LoadDIBFromFile
  315. //
  316. // load a image file using a image import filter. The filters use ANSI strings.
  317. //
  318. HGLOBAL LoadDIBFromFileA(LPCSTR szFileName, GUID *pguidFltTypeUsed)
  319. {
  320. #ifdef _USE_IFL_API
  321. IFLTYPE iflType;
  322. iflImageType((LPSTR)szFileName, &iflType);
  323. // make sure the image is of a type we know how to import
  324. if (iflType == IFLT_PNG)
  325. {
  326. return NULL;
  327. }
  328. IFLHANDLE iflHandle = iflCreateReadHandle(iflType);
  329. if (!iflHandle)
  330. {
  331. //
  332. // No filter installed for this type
  333. //
  334. return NULL;
  335. }
  336. LPBYTE lpStart = 0;
  337. __try
  338. {
  339. IFLERROR iflErr = iflOpen(iflHandle, (LPSTR)szFileName, IFLM_READ);
  340. if (iflErr != IFLERR_NONE)
  341. {
  342. iflFreeHandle(iflHandle);
  343. return NULL;
  344. }
  345. ASSERT(pguidFltTypeUsed);
  346. switch (iflType)
  347. {
  348. case IFLT_GIF: *pguidFltTypeUsed = WiaImgFmt_GIF; break;
  349. case IFLT_BMP: *pguidFltTypeUsed = WiaImgFmt_BMP; break;
  350. case IFLT_JPEG: *pguidFltTypeUsed = WiaImgFmt_JPEG; break;
  351. case IFLT_TIFF: *pguidFltTypeUsed = WiaImgFmt_TIFF; break;
  352. case IFLT_PNG: *pguidFltTypeUsed = WiaImgFmt_PNG; break;
  353. case IFLT_PCD: *pguidFltTypeUsed = WiaImgFmt_PHOTOCD; break;
  354. default: *pguidFltTypeUsed = WiaImgFmt_UNDEFINED; break;
  355. }
  356. IFLCLASS iflClass = iflGetClass(iflHandle);
  357. IFLSEQUENCE iflSequence = iflGetSequence(iflHandle);
  358. IFLCOMPRESSION iflCompression = iflGetCompression(iflHandle);
  359. WORD iBPS = (WORD) iflGetBitsPerChannel(iflHandle);
  360. if (iflClass != IFLCL_RGB && iflClass != IFLCL_PALETTE &&
  361. iflClass != IFLCL_GRAY && iflClass != IFLCL_BILEVEL)
  362. {
  363. #ifdef _DEBUG
  364. TRACE(TEXT("LoadDIBFromFile: Not a RGB/PALETTE/GRAY/BW image.\n"));
  365. MessageBox (NULL, TEXT("Not a RGB/PALETTE/GRAY/BW image."),
  366. TEXT("Loadimag.cpp"), MB_OK);
  367. #endif
  368. iflClose(iflHandle);
  369. iflFreeHandle(iflHandle);
  370. return NULL;
  371. }
  372. // get the transparent color
  373. if (iflClass == IFLCL_RGB)
  374. {
  375. IFLCOLOR iflTransColor;
  376. g_bUseTrans = (IFLERR_NONE ==
  377. iflControl(iflHandle, IFLCMD_TRANS_RGB, 0, 0, &iflTransColor));
  378. if (g_bUseTrans)
  379. crTrans = RGB(iflTransColor.wRed,
  380. iflTransColor.wGreen,
  381. iflTransColor.wBlue);
  382. }
  383. else // must be IFLCL_PALETTE or IFLCL_GRAY or IFLCL_BILEVEL
  384. {
  385. BYTE byTransIdx;
  386. g_bUseTrans = (IFLERR_NONE ==
  387. iflControl(iflHandle, IFLCMD_TRANS_IDX, 0, 0, &byTransIdx));
  388. if (g_bUseTrans)
  389. crTrans = byTransIdx; // need to convert to COLORREF below
  390. }
  391. BITMAPINFOHEADER bi;
  392. memset(&bi, 0, sizeof(BITMAPINFOHEADER));
  393. bi.biSize = sizeof(BITMAPINFOHEADER); // should be 0x28 or 40 decimal
  394. bi.biWidth = iflGetWidth(iflHandle);
  395. bi.biHeight = iflGetHeight(iflHandle);
  396. bi.biPlanes = 1;
  397. if (iflClass == IFLCL_RGB)
  398. {
  399. #ifdef PNG_SUPPORT
  400. if (iflType == IFLT_PNG)
  401. {
  402. bi.biBitCount = iBPS*3;
  403. }
  404. else
  405. #endif // PNG_SUPPORT
  406. {
  407. bi.biBitCount = (WORD) iflGetBitsPerPixel (iflHandle);
  408. }
  409. }
  410. else // must be IFLCL_PALETTE or IFLCL_GRAY or IFLCL_BILEVEL
  411. {
  412. bi.biBitCount = 8;
  413. }
  414. bi.biCompression = 0;
  415. // convert width in pixels to bytes after rounding it up first
  416. DWORD dwWidthInBytes = ((bi.biWidth * bi.biBitCount + 31) & ~31)/8;
  417. bi.biSizeImage = abs(bi.biHeight) * dwWidthInBytes;
  418. // bi.biXPelsPerMeter = 0;
  419. // bi.biYPelsPerMeter = 0;
  420. if (iflClass == IFLCL_PALETTE || iflClass == IFLCL_GRAY
  421. || iflClass == IFLCL_BILEVEL)
  422. bi.biClrUsed = MAX_PAL_SIZE;
  423. // bi.biClrImportant = 0;
  424. LPBYTE lpBMP;
  425. if ((lpBMP = lpStart = (LPBYTE) GlobalAlloc(GMEM_FIXED,
  426. bi.biSize + bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage)) == NULL)
  427. goto exit;
  428. memcpy(lpBMP, &bi, bi.biSize);
  429. lpBMP += bi.biSize;
  430. BYTE byTemp;
  431. int i, j;
  432. switch (iflSequence)
  433. {
  434. case IFLSEQ_TOPDOWN:
  435. switch (iflClass)
  436. {
  437. case IFLCL_RGB:
  438. lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage -
  439. dwWidthInBytes;
  440. for (i = 0; i < abs(bi.biHeight); lpBMP-=dwWidthInBytes, i++)
  441. {
  442. // read in one line at a time
  443. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  444. // need to swap RED with BLUE for internal DIB display
  445. for (j = 0; j < bi.biWidth*3; j+=3)
  446. {
  447. byTemp = *(lpBMP+j);
  448. *(lpBMP+j) = *(lpBMP+j+2);
  449. *(lpBMP+j+2) = byTemp;
  450. }
  451. }
  452. break;
  453. case IFLCL_PALETTE:
  454. // get palette info first...
  455. RGBTRIPLE Pal3[MAX_PAL_SIZE];
  456. RGBQUAD Pal4[MAX_PAL_SIZE];
  457. ZeroMemory (Pal3, MAX_PAL_SIZE*(sizeof(RGBTRIPLE)));
  458. iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
  459. for (i = 0; i < MAX_PAL_SIZE; i++)
  460. {
  461. Pal4[i].rgbBlue = Pal3[i].rgbtRed;
  462. Pal4[i].rgbGreen = Pal3[i].rgbtGreen;
  463. Pal4[i].rgbRed = Pal3[i].rgbtBlue;
  464. Pal4[i].rgbReserved = 0;
  465. }
  466. memcpy(lpBMP, Pal4, sizeof(Pal4));
  467. if (g_bUseTrans)
  468. // convert the transparent color index to COLORREF
  469. crTrans = RGB(Pal4[crTrans].rgbRed,Pal4[crTrans].rgbGreen,
  470. Pal4[crTrans].rgbBlue);
  471. lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
  472. for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++)
  473. {
  474. // read in one line at a time
  475. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  476. }
  477. break;
  478. case IFLCL_GRAY:
  479. // get palette info first...
  480. //BYTE PalGray[MAX_PAL_SIZE];
  481. //iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &PalGray);
  482. for (i = 0; i < MAX_PAL_SIZE; i++)
  483. {
  484. Pal4[i].rgbBlue = (BYTE) i;//PalGray[i];
  485. Pal4[i].rgbGreen = (BYTE) i;//PalGray[i];
  486. Pal4[i].rgbRed = (BYTE) i;//PalGray[i];
  487. Pal4[i].rgbReserved = 0;
  488. }
  489. memcpy(lpBMP, Pal4, sizeof(Pal4));
  490. if (g_bUseTrans)
  491. // convert the transparent color index to COLORREF
  492. crTrans = RGB(Pal4[crTrans].rgbRed, Pal4[crTrans].rgbGreen,
  493. Pal4[crTrans].rgbBlue);
  494. lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
  495. for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++)
  496. {
  497. // read in one line at a time
  498. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  499. }
  500. break;
  501. case IFLCL_BILEVEL:
  502. // set color Black
  503. Pal4[0].rgbBlue = 0;
  504. Pal4[0].rgbGreen = 0;
  505. Pal4[0].rgbRed = 0;
  506. Pal4[0].rgbReserved = 0;
  507. // set color White
  508. Pal4[1].rgbBlue = 255;
  509. Pal4[1].rgbGreen = 255;
  510. Pal4[1].rgbRed = 255;
  511. Pal4[1].rgbReserved = 0;
  512. memcpy(lpBMP, Pal4, sizeof(Pal4));
  513. if (g_bUseTrans)
  514. // convert the transparent color index to COLORREF
  515. crTrans = RGB(Pal4[crTrans].rgbRed,
  516. Pal4[crTrans].rgbGreen,
  517. Pal4[crTrans].rgbBlue);
  518. lpBMP += sizeof(Pal4) + bi.biSizeImage - dwWidthInBytes;
  519. for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++)
  520. {
  521. // read in one line at a time
  522. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  523. }
  524. break;
  525. default:
  526. // currently not supported
  527. break;
  528. }
  529. break;
  530. case IFLSEQ_BOTTOMUP:
  531. lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage - dwWidthInBytes;
  532. for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++)
  533. {
  534. // read in one line at a time
  535. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  536. // need to swap RED with BLUE for internal DIB display
  537. for (j = 0; j < bi.biWidth*3; j+=3)
  538. {
  539. byTemp = *(lpBMP+j);
  540. *(lpBMP+j) = *(lpBMP+j+2);
  541. *(lpBMP+j+2) = byTemp;
  542. }
  543. }
  544. break;
  545. case IFLSEQ_GIF_INTERLACED:
  546. {
  547. // get color palette info first...
  548. RGBTRIPLE Pal3[MAX_PAL_SIZE];
  549. RGBQUAD Pal4[MAX_PAL_SIZE];
  550. iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
  551. for (i = 0; i < MAX_PAL_SIZE; i++)
  552. {
  553. Pal4[i].rgbBlue = Pal3[i].rgbtRed;
  554. Pal4[i].rgbGreen = Pal3[i].rgbtGreen;
  555. Pal4[i].rgbRed = Pal3[i].rgbtBlue;
  556. Pal4[i].rgbReserved = 0;
  557. }
  558. memcpy(lpBMP, Pal4, sizeof(Pal4));
  559. if (g_bUseTrans)
  560. // convert the transparent color index to COLORREF
  561. crTrans = RGB(Pal4[crTrans].rgbRed,Pal4[crTrans].rgbGreen,
  562. Pal4[crTrans].rgbBlue);
  563. LPBYTE lpTemp = lpBMP + sizeof(Pal4);
  564. ReadGIFInterlacedImage (lpTemp, iflHandle, bi.biHeight, dwWidthInBytes);
  565. }
  566. break;
  567. /* case 1010101:
  568. {
  569. int IM[] = { 8, 8, 4, 2 }; // interlace multiplier
  570. //int IO[] = { 1, 5, 3 ,2 }; // interface offset
  571. int IO[] = { 0, 4, 2,1 };
  572. for (j = 0; j < 4; j++)
  573. {
  574. lpBMP = lpTemp + bi.biSizeImage - dwWidthInBytes*IO[j];
  575. for (i = 0; i < abs(bi.biHeight) && lpBMP >= lpTemp;
  576. lpBMP-=dwWidthInBytes*IM[j], i+=8)
  577. {
  578. // read in one line at a time
  579. iflRead(iflHandle, (LPBYTE)lpBMP, 1);
  580. }
  581. }
  582. break;
  583. }*/
  584. #ifdef PNG_SUPPORT
  585. case IFLSEQ_ADAM7_INTERLACED:
  586. {
  587. // get color palette info first...
  588. RGBTRIPLE Pal3[MAX_PAL_SIZE];
  589. RGBQUAD Pal4[MAX_PAL_SIZE];
  590. iflErr = iflControl(iflHandle, IFLCMD_PALETTE, 0, 0, &Pal3);
  591. for (i = 0; i < MAX_PAL_SIZE; i++)
  592. {
  593. Pal4[i].rgbBlue = Pal3[i].rgbtRed;
  594. Pal4[i].rgbGreen = Pal3[i].rgbtGreen;
  595. Pal4[i].rgbRed = Pal3[i].rgbtBlue;
  596. Pal4[i].rgbReserved = 0;
  597. }
  598. memcpy(lpBMP, Pal4, sizeof(Pal4));
  599. if (g_bUseTrans)
  600. // convert the transparent color index to COLORREF
  601. crTrans = RGB(Pal4[crTrans].rgbRed,
  602. Pal4[crTrans].rgbGreen,
  603. Pal4[crTrans].rgbBlue);
  604. /////////////////////////////
  605. HANDLE hHeap = GetProcessHeap();
  606. LPBYTE *ppbRGBRowPtrs =(LPBYTE *)AllocateImageSpace(hHeap,
  607. bi.biHeight, dwWidthInBytes, /*bi.biWidth, */sizeof(BYTE));
  608. if (ppbRGBRowPtrs != NULL)
  609. {
  610. // First get the image. This function will de-interlace the image
  611. // AND any alpha channel information: it will also resize the alpha
  612. // channel data structure to the image height from the number of
  613. // raster lines, if necessary.
  614. iflErr = ReadADAM7InterlacedImage(ppbRGBRowPtrs, iflHandle,
  615. bi.biHeight, bi.biWidth,
  616. sizeof(BYTE)*3, iflClass);
  617. /////////////////////////////
  618. if (iflErr == IFLERR_NONE)
  619. {
  620. lpBMP += bi.biClrUsed*sizeof(RGBQUAD) + bi.biSizeImage -
  621. dwWidthInBytes;
  622. for (i = 0;i < abs(bi.biHeight);lpBMP-=dwWidthInBytes, i++)
  623. {
  624. // read in one line at a time
  625. memcpy((LPBYTE)lpBMP, ppbRGBRowPtrs[i], dwWidthInBytes);
  626. // need to swap RED with BLUE for internal DIB display
  627. for (j = 0; j < bi.biWidth*3; j+=3)
  628. {
  629. byTemp = *(lpBMP+j);
  630. *(lpBMP+j) = *(lpBMP+j+2);
  631. *(lpBMP+j+2) = byTemp;
  632. }
  633. }
  634. }
  635. ppbRGBRowPtrs = (LPBYTE *)FreeImageSpace(hHeap,
  636. ppbRGBRowPtrs,
  637. bi.biHeight);
  638. }
  639. break;
  640. }
  641. #endif // PNG_SUPPORT
  642. default:
  643. break;
  644. }
  645. }
  646. __except(EXCEPTION_EXECUTE_HANDLER)
  647. {
  648. }
  649. exit:
  650. iflClose(iflHandle);
  651. iflFreeHandle(iflHandle);
  652. return (HGLOBAL)lpStart;
  653. #endif // _USE_IFL_API
  654. //////////////////////////////////////////////////////////////////////////////
  655. #ifdef _USE_FLT_API
  656. HINSTANCE hLib = NULL;
  657. FILESPEC fileSpec; // file to load
  658. GRPI pict;
  659. UINT rc; // return code
  660. HANDLE hPrefMem = NULL; // filter-supplied preferences
  661. UINT wFilterType; // 2 = graphics filter
  662. char szHandler[128];
  663. HGLOBAL hDib = NULL;
  664. PFNGetFilterInfo lpfnGetFilterInfo;
  665. PFNImportGr lpfnImportGr;
  666. if (!GetHandlerForFile(TRUE, szFileName, szHandler, sizeof(szHandler)))
  667. return FALSE;
  668. if (szHandler[0] == 0)
  669. return FALSE;
  670. if ((hLib = LoadLibrary(szHandler)) == NULL)
  671. goto exit;
  672. // get a pointer to the ImportGR function
  673. lpfnGetFilterInfo = (PFNGetFilterInfo)GetProcAddress(hLib, "GetFilterInfo");
  674. lpfnImportGr = (PFNImportGr)GetProcAddress(hLib, "ImportGr");
  675. if (lpfnGetFilterInfo == NULL)
  676. lpfnGetFilterInfo = (PFNGetFilterInfo)GetProcAddress(hLib, "GetFilterInfo@16");
  677. if (lpfnImportGr == NULL)
  678. lpfnImportGr = (PFNImportGr)GetProcAddress(hLib, "ImportGr@16");
  679. if (lpfnImportGr == NULL)
  680. goto exit;
  681. if (lpfnGetFilterInfo != NULL)
  682. {
  683. wFilterType = (*lpfnGetFilterInfo)
  684. ((short) 2, // interface version no.
  685. (char *)NULL, // unused
  686. (HANDLE *) &hPrefMem, // fill in: preferences
  687. (DWORD) 0x00020000); // unused in Windows
  688. // the return value is the type of filter: 0=error,
  689. // 1=text-filter, 2=graphics-filter
  690. if (wFilterType != 2)
  691. goto exit;
  692. }
  693. fileSpec.slippery = FALSE; // TRUE if file may disappear
  694. fileSpec.write = FALSE; // TRUE if open for write
  695. fileSpec.unnamed = FALSE; // TRUE if unnamed
  696. fileSpec.linked = FALSE; // Linked to an FS FCB
  697. fileSpec.mark = FALSE; // Generic mark bit
  698. fileSpec.dcbFile = 0L;
  699. //the converters need a pathname without spaces...
  700. GetShortPathName(szFileName, fileSpec.szName, sizeof(fileSpec.szName));
  701. pict.hmf = NULL;
  702. rc = (*lpfnImportGr)
  703. (NULL, // "the target DC" (printer?)
  704. (FILESPEC *) &fileSpec, // file to read
  705. (GRPI *) &pict, // fill in: result metafile
  706. (HANDLE) hPrefMem); // preferences memory
  707. if (pict.hmf != NULL)
  708. {
  709. if (rc == 0)
  710. {
  711. // find the BITMAPINFO in the returned metafile
  712. LPMETAHEADER lpMetaHeader = (LPMETAHEADER) GlobalLock(pict.hmf);
  713. LPBITMAPINFOHEADER lpbi = FindBitmapInfo(lpMetaHeader);
  714. if (lpbi != NULL)
  715. {
  716. // copy the DIB
  717. SIZE_T nSize = FindDibSize(lpbi);
  718. hDib = GlobalAlloc(GMEM_FIXED, nSize);
  719. CopyMemory(hDib, lpbi, nSize);
  720. }
  721. GlobalUnlock(pict.hmf);
  722. }
  723. GlobalFree(pict.hmf);
  724. }
  725. exit:
  726. if (hPrefMem != NULL)
  727. GlobalFree(hPrefMem);
  728. if (hLib)
  729. FreeLibrary(hLib);
  730. return hDib;
  731. #endif // _USE_FLT_API
  732. return NULL;
  733. }
  734. CGdiplusInit::CGdiplusInit(
  735. Gdiplus::DebugEventProc debugEventCallback /*= 0*/,
  736. BOOL suppressBackgroundThread /*= FALSE*/,
  737. BOOL suppressExternalCodecs /*= FALSE*/
  738. )
  739. {
  740. Gdiplus::GdiplusStartupInput StartupInput(
  741. debugEventCallback,
  742. suppressBackgroundThread,
  743. suppressExternalCodecs
  744. );
  745. StartupStatus = GdiplusSafeStartup(&Token, &StartupInput, this);
  746. }
  747. CGdiplusInit::~CGdiplusInit()
  748. {
  749. if (StartupStatus == Gdiplus::Ok)
  750. {
  751. Gdiplus::GdiplusShutdown(Token);
  752. }
  753. }
  754. Gdiplus::Status
  755. CGdiplusInit::GdiplusSafeStartup(
  756. ULONG_PTR *token,
  757. const Gdiplus::GdiplusStartupInput *input,
  758. Gdiplus::GdiplusStartupOutput *output
  759. )
  760. {
  761. __try
  762. {
  763. return Gdiplus::GdiplusStartup(token, input, output);
  764. }
  765. __except(EXCEPTION_EXECUTE_HANDLER)
  766. {
  767. return Gdiplus::GdiplusNotInitialized;
  768. }
  769. }
  770. BOOL GetGdiplusDecoders(UINT *pnCodecs, Gdiplus::ImageCodecInfo **ppCodecs)
  771. {
  772. ASSERT(pnCodecs);
  773. ASSERT(ppCodecs);
  774. *ppCodecs = 0;
  775. *pnCodecs = 0;
  776. if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok)
  777. {
  778. __try
  779. {
  780. UINT cbCodecs;
  781. if (Gdiplus::GetImageDecodersSize(pnCodecs, &cbCodecs) == Gdiplus::Ok)
  782. {
  783. if (*pnCodecs > 0)
  784. {
  785. *ppCodecs = (Gdiplus::ImageCodecInfo *) LocalAlloc(LMEM_FIXED, cbCodecs);
  786. if (*ppCodecs != 0)
  787. {
  788. if (Gdiplus::GetImageDecoders(*pnCodecs, cbCodecs, *ppCodecs) == Gdiplus::Ok)
  789. {
  790. return TRUE;
  791. }
  792. }
  793. }
  794. }
  795. }
  796. __except(EXCEPTION_EXECUTE_HANDLER)
  797. {
  798. }
  799. LocalFree(*ppCodecs);
  800. *ppCodecs = 0;
  801. *pnCodecs = 0;
  802. }
  803. return FALSE;
  804. }
  805. BOOL GetGdiplusEncoders(UINT *pnCodecs, Gdiplus::ImageCodecInfo **ppCodecs)
  806. {
  807. ASSERT(pnCodecs);
  808. ASSERT(ppCodecs);
  809. *ppCodecs = 0;
  810. *pnCodecs = 0;
  811. if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok)
  812. {
  813. __try
  814. {
  815. UINT cbCodecs;
  816. if (Gdiplus::GetImageEncodersSize(pnCodecs, &cbCodecs) == Gdiplus::Ok)
  817. {
  818. if (*pnCodecs > 0)
  819. {
  820. *ppCodecs = (Gdiplus::ImageCodecInfo *) LocalAlloc(LMEM_FIXED, cbCodecs);
  821. if (*ppCodecs != 0)
  822. {
  823. if (Gdiplus::GetImageEncoders(*pnCodecs, cbCodecs, *ppCodecs) == Gdiplus::Ok)
  824. {
  825. return TRUE;
  826. }
  827. }
  828. }
  829. }
  830. }
  831. __except(EXCEPTION_EXECUTE_HANDLER)
  832. {
  833. }
  834. LocalFree(*ppCodecs);
  835. *ppCodecs = 0;
  836. *pnCodecs = 0;
  837. }
  838. return FALSE;
  839. }
  840. BOOL GetClsidOfEncoder(REFGUID guidFormatID, CLSID *pClsid)
  841. {
  842. Gdiplus::ImageCodecInfo *pCodecs = 0;
  843. UINT nCodecs = 0;
  844. GetGdiplusEncoders(&nCodecs, &pCodecs);
  845. for (UINT i = 0; i < nCodecs; ++i)
  846. {
  847. if (pCodecs[i].FormatID == guidFormatID)
  848. {
  849. if (pClsid)
  850. {
  851. *pClsid = pCodecs[i].Clsid;
  852. }
  853. LocalFree(pCodecs);
  854. return TRUE;
  855. }
  856. }
  857. LocalFree(pCodecs);
  858. return FALSE;
  859. }
  860. HGLOBAL LoadDIBGdiplus(LPCTSTR szFileName, GUID *pguidFltTypeUsed)
  861. {
  862. // check that the BMP encoder exists
  863. CLSID ClsidBmpEncoder;
  864. if (GetClsidOfEncoder(WiaImgFmt_BMP, &ClsidBmpEncoder))
  865. {
  866. // let GDI+ import the file
  867. USES_CONVERSION;
  868. Gdiplus::Bitmap image(T2CW(szFileName));
  869. if (image.GetLastStatus() == Gdiplus::Ok)
  870. {
  871. // read the image type
  872. ASSERT(pguidFltTypeUsed);
  873. image.GetRawFormat(pguidFltTypeUsed);
  874. // create a stream that emulates a bmp file
  875. CComPtr<CBmpStream> pStream;
  876. if (CBmpStream::Create(&pStream) == S_OK)
  877. {
  878. // convert the image into a BMP
  879. if (image.Save(pStream, &ClsidBmpEncoder, 0) == Gdiplus::Ok)
  880. {
  881. return pStream->GetBuffer();
  882. }
  883. pStream->FreeBuffer();
  884. }
  885. }
  886. }
  887. return 0;
  888. }
  889. HGLOBAL LoadDIBFromFile(LPCTSTR szFileName, GUID *pguidFltTypeUsed)
  890. {
  891. // Try GDI+ filters first. If it fails to convert the image or
  892. // if it's not available, try the old method
  893. HGLOBAL hResult = 0;
  894. if (theApp.GdiplusInit.StartupStatus == Gdiplus::Ok)
  895. {
  896. __try
  897. {
  898. hResult = LoadDIBGdiplus(szFileName, pguidFltTypeUsed);
  899. }
  900. __except(EXCEPTION_EXECUTE_HANDLER)
  901. {
  902. }
  903. }
  904. if (!hResult)
  905. {
  906. USES_CONVERSION;
  907. hResult = LoadDIBFromFileA(T2CA(szFileName), pguidFltTypeUsed);
  908. }
  909. return hResult;
  910. }