DIBS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:59k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. //ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright  1994-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  FILE:
  9. //    DIBS.C
  10. //
  11. //  PURPOSE:
  12. //    DIB routines for the ICMVIEW application.
  13. //
  14. //  PLATFORMS:
  15. //    Windows 95, Windows NT
  16. //
  17. //  SPECIAL INSTRUCTIONS: N/A
  18. //
  19. // Windows Header Files:
  20. #pragma warning(disable:4001)   // Single-line comment warnings
  21. #pragma warning(disable:4115)   // Named type definition in parentheses
  22. #pragma warning(disable:4201)   // Nameless struct/union warning
  23. #pragma warning(disable:4214)   // Bit field types other than int warnings
  24. #pragma warning(disable:4514)   // Unreferenced inline function has been removed
  25. // Windows Header Files:
  26. #include <Windows.h>
  27. #include <WindowsX.h>
  28. //#include <CommCtrl.h>
  29. #include <icm.h>
  30. // Restore the warnings--leave the single-line comment warning OFF
  31. #pragma warning(default:4115)   // Named type definition in parentheses
  32. #pragma warning(default:4201)   // Nameless struct/union warning
  33. #pragma warning(default:4214)   // Bit field types other than int warnings
  34. #pragma warning(default:4514)   // Unreferenced inline function has been removed
  35. // C RunTime Header Files
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <TCHAR.H>
  40. // Local Header Files
  41. #include "icmview.h"  // specific to this program
  42. #include "child.h"
  43. #include "dibinfo.h"
  44. #include "dibs.h"      // specific to this file
  45. #include "dialogs.h"
  46. #include "debug.h"
  47. #include "print.h"
  48. #include "regutil.h"
  49. #include "resource.h"
  50. // local definitions
  51. DWORD NumColorsInDIB(LPBITMAPINFOHEADER lpbi);
  52. LONG      DIBHeight (LPBYTE lpDIB);
  53. LONG      DIBWidth (LPBYTE lpDIB);
  54. LPLOGCOLORSPACE GetColorSpaceFromBitmap(LPBITMAPINFOHEADER lpBitmapInfo, DWORD dwIntent, LPBOOL pbDeleteProfile);
  55. HPROFILE  OpenColorProfileFromFile(LPTSTR lpszProfileName);
  56. BOOL TranslateColorTable(HTRANSFORM hColorTransform, PCOLOR paInputColors, DWORD nColors, COLORTYPE ctInput, PCOLOR paOutputColors, COLORTYPE ctOutput, int biBitCount);
  57. // default settings
  58. // external functions
  59. // external data
  60. // public data
  61. // private data
  62. // public functions
  63. // private functions
  64. ///////////////////////////////////////////////////////////////////////
  65. //
  66. // Function:   DIBPaint
  67. //
  68. // Purpose:    Painting routine for a DIB.  Calls StretchDIBits() or
  69. //             SetDIBitsToDevice() to paint the DIB.  The DIB is
  70. //             output to the specified DC, at the coordinates given
  71. //             in lpDCRect.  The area of the DIB to be output is
  72. //             given by lpDIBRect.  The specified palette is used.
  73. //
  74. // Parms:      hDC       == DC to do output to.
  75. //             lpDCRect  == Rectangle on DC to do output to.
  76. //             hDIB      == Handle to global memory with a DIB spec
  77. //                          in it (either a BITMAPINFO or BITMAPCOREINFO
  78. //                          followed by the DIB bits).
  79. //             lpDIBRect == Rect of DIB to output into lpDCRect.
  80. //             hPal      == Palette to be used.
  81. //
  82. ///////////////////////////////////////////////////////////////////////
  83. void DIBPaint (HDC hDC, LPRECT lpDCRect, HGLOBAL hDIB,LPRECT lpDIBRect,
  84.                LPDIBINFO lpDIBInfo)
  85. {
  86.     int                 iScanLines;
  87.     HDC                 hDCPrinter;
  88.     BOOL                bRC;
  89.     LPBYTE              lpbDIBBits;
  90.     HPALETTE            hOldPal;
  91.     LPBITMAPINFOHEADER  lpDIBHdr;
  92.     LPBITMAPINFOHEADER  lpbi;
  93.     // Initialize variables
  94.     if (!hDIB)
  95.     {
  96.         return;
  97.     }
  98.     ASSERT(hDC != NULL);
  99.     hDCPrinter = NULL;
  100.     SetLastError(0);
  101.     hOldPal = NULL;
  102.     lpbi = NULL;
  103.     // Lock down DIB, get a pointer to the beginning of the bit buffer.
  104.     lpDIBHdr  = GlobalLock(hDIB);
  105.     if (NULL == lpDIBHdr )
  106.     {
  107.         goto Release;
  108.     }
  109.     lpbDIBBits = FindDIBBits(lpDIBHdr);
  110.     if (NULL == lpbDIBBits)
  111.     {
  112.         goto Release;
  113.     }
  114.     // If size > BITMAPINFOHEADER header then
  115.     // need to convert to BITMAPINFOHEADER.
  116.     lpbi = lpDIBHdr;
  117. #ifdef OSR2
  118.     if (sizeof(BITMAPINFOHEADER) < lpDIBHdr->biSize)
  119.     {
  120.         DWORD dwColorTableSize;
  121.         DWORD dwHeaderDataSize;
  122.         // Allocate Bitmapinfo memory.
  123.         dwHeaderDataSize = sizeof(BITMAPINFOHEADER) + (lpDIBHdr->biCompression == BI_BITFIELDS ? 12 : 0);
  124.         dwColorTableSize = NumColorsInDIB(lpDIBHdr) * sizeof(RGBQUAD);
  125.         lpbi = (LPBITMAPINFOHEADER) GlobalAlloc(GPTR, dwHeaderDataSize + dwColorTableSize);
  126.         if (NULL == lpbi)
  127.         {
  128.             goto Release;
  129.         }
  130.         // Convert header data into bitmapinfo header.
  131.         memcpy(lpbi, lpDIBHdr, dwHeaderDataSize);
  132.         lpbi->biSize = sizeof(BITMAPINFOHEADER);
  133.         // Copy color table if any.
  134.         if (0 != dwColorTableSize)
  135.             memcpy((LPBYTE)lpbi + dwHeaderDataSize, (LPBYTE)lpDIBHdr + lpDIBHdr->biSize, dwColorTableSize);
  136.     }
  137. #endif
  138.     SetupDC(hDC, lpDIBInfo, &hOldPal, &hDCPrinter);
  139.     // Determine whether to call StretchDIBits() or SetDIBitsToDevice().
  140.     if (!(lpDIBInfo->bStretch))
  141.     {
  142.         iScanLines = SetDIBitsToDevice (hDC,          // hDC
  143.                                         lpDCRect->left,               // dest upper-left x
  144.                                         lpDCRect->top,                // dest upper-left y
  145.                                         RECTWIDTH (lpDCRect),         // src width
  146.                                         RECTHEIGHT (lpDCRect),        // src height
  147.                                         lpDIBRect->left,              // src lower-left x
  148.                                         (int) DIBHeight((LPBYTE)lpDIBHdr) -
  149.                                         lpDIBRect->top -
  150.                                         RECTHEIGHT (lpDIBRect),       // src lower-left y
  151.                                         0,                            // nStartScan
  152.                                         (UINT) DIBHeight((LPBYTE)lpDIBHdr),   // nNumScans
  153.                                         lpbDIBBits,                   // lpBits
  154.                                         (LPBITMAPINFO) lpbi,      // lpBitsInfo
  155.                                         DIB_RGB_COLORS);              // wUsage
  156.     }
  157.     else
  158.     {
  159.         // Use the specified stretch mode
  160.         SetStretchBltMode (hDC, (int)lpDIBInfo->dwStretchBltMode);
  161.         iScanLines = StretchDIBits (hDC,                          // hDC
  162.                                     lpDCRect->left,               // dest upper-left x
  163.                                     lpDCRect->top,                // dest upper-left y
  164.                                     RECTWIDTH (lpDCRect),         // src width
  165.                                     RECTHEIGHT (lpDCRect),        // src height
  166.                                     lpDIBRect->left,              // src lower-left x
  167.                                     lpDIBRect->top,               // src lower-left y
  168.                                     RECTWIDTH (lpDIBRect),        // nStartScan
  169.                                     RECTHEIGHT (lpDIBRect),       // nNumScans
  170.                                     lpbDIBBits,                   // lpBits
  171.                                     (LPBITMAPINFO)lpbi,                   // lpBitsInfo
  172.                                     DIB_RGB_COLORS,               // wUsage
  173.                                     SRCCOPY);                     // dwROP
  174.     }
  175.     if (DIBHeight((LPBYTE)lpDIBHdr) != iScanLines)
  176.     {
  177.         DebugMsg(__TEXT("DIBS.C : DIBPaint:  iScanLines expected %ld, returned %ldrn"), DIBHeight((LPBYTE)lpDIBHdr), iScanLines);
  178.     }
  179.     // Fix up the palette.
  180.     if (NULL == SelectPalette (hDC, hOldPal, TRUE))
  181.     {
  182.         DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  183.     }
  184.     Release:
  185.     if (lpbi != lpDIBHdr)
  186.         GlobalFree((HANDLE)lpbi);
  187.     if (NULL != lpDIBHdr)
  188.     {
  189.         GlobalUnlock(hDIB);
  190.     }
  191.     if (hDCPrinter)
  192.     {
  193.         bRC = ColorMatchToTarget(hDC, hDCPrinter, CS_DISABLE);
  194.         if (0 == bRC)
  195.         {
  196.             DebugMsg(__TEXT("DIBS.C : DIBPaint : ColorMatchToTarget failed to DISABLE transform.rn"));
  197.             DISPLAY_LASTERROR(LASTERROR_NOALLOC,GetLastError());
  198.         }
  199.         bRC = ColorMatchToTarget(hDC, hDCPrinter, CS_DELETE_TRANSFORM);
  200.         if (0 == bRC)
  201.         {
  202.             DebugMsg(  __TEXT(  "DIBS.C : DIBPaint : ColorMatchToTarget failed to DELETE transform.rn"));
  203.             DISPLAY_LASTERROR(LASTERROR_NOALLOC,GetLastError());
  204.         }
  205.         bRC = DeleteDC(hDCPrinter);
  206.         if (0 == bRC)
  207.         {
  208.             DebugMsg(__TEXT("DIBS.C : DIBPaint : Failed to delete printer DCrn"));
  209.             DISPLAY_LASTERROR(LASTERROR_NOALLOC,GetLastError());
  210.         }
  211.     }
  212. }
  213. ///////////////////////////////////////////////////////////////////////
  214. //
  215. // Function:   CreateDIBPalette
  216. //
  217. // Purpose:    Given a handle to a DIB, constructs a logical palette,
  218. //             and returns a handle to this palette.
  219. //
  220. //             Stolen almost verbatim from ShowDIB.
  221. //
  222. // Parms:      hDIB == HANDLE to global memory with a DIB header
  223. //                     (either BITMAPINFOHEADER or BITMAPCOREHEADER)
  224. //
  225. ///////////////////////////////////////////////////////////////////////
  226. HPALETTE CreateDIBPalette(HANDLE hDIB)
  227. {
  228.     LPLOGPALETTE          lpPal;
  229.     HGLOBAL               hLogPal;
  230.     HPALETTE              hPal = NULL;
  231.     UINT                  i;
  232.     DWORD                 dwNumColors;
  233.     LPBITMAPINFOHEADER    lpBmpInfoHdr;
  234.     LPBITMAPINFO          lpbmi;
  235.     LPBITMAPCOREINFO      lpbmc;
  236.     BOOL                  bWinStyleDIB;
  237.     if (!hDIB)
  238.     {
  239.         return NULL;
  240.     }
  241.     lpBmpInfoHdr = GlobalLock (hDIB);
  242.     lpbmi        = (LPBITMAPINFO)lpBmpInfoHdr;
  243.     lpbmc        = (LPBITMAPCOREINFO)lpBmpInfoHdr;
  244.     dwNumColors  = NumColorsInDIB(lpBmpInfoHdr);
  245.     bWinStyleDIB = IS_WIN30_DIB(lpBmpInfoHdr);
  246.     if (0 != dwNumColors)
  247.     {
  248.         hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * dwNumColors);
  249.         if (!hLogPal)
  250.         {
  251.             GlobalUnlock(hDIB);
  252.             return NULL;
  253.         }
  254.         lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
  255.         lpPal->palVersion    = PALVERSION;
  256.         lpPal->palNumEntries = (WORD)dwNumColors;
  257.         for (i = 0;  i < dwNumColors;  i++)
  258.         {
  259.             if (bWinStyleDIB)
  260.             {
  261.                 lpPal->palPalEntry[i].peRed   = lpbmi->bmiColors[i].rgbRed;
  262.                 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  263.                 lpPal->palPalEntry[i].peBlue  = lpbmi->bmiColors[i].rgbBlue;
  264.                 lpPal->palPalEntry[i].peFlags = 0;
  265.             }
  266.             else
  267.             {
  268.                 lpPal->palPalEntry[i].peRed   = lpbmc->bmciColors[i].rgbtRed;
  269.                 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  270.                 lpPal->palPalEntry[i].peBlue  = lpbmc->bmciColors[i].rgbtBlue;
  271.                 lpPal->palPalEntry[i].peFlags = 0;
  272.             }
  273.         }
  274.         hPal = CreatePalette (lpPal);
  275.         GlobalUnlock(hLogPal);
  276.         GlobalFree(hLogPal);
  277.     }
  278.     GlobalUnlock(hDIB);
  279.     return(hPal);
  280. }
  281. //////////////////////////////////////////////////////////////////////////
  282. //  Function:  GetDefaultICMProfile
  283. //
  284. //  Description:
  285. //    Uses GetICMProfile to retrieve the filename of the default ICM
  286. //    profile for the DC.
  287. //
  288. //  Parameters:
  289. //    @@@
  290. //
  291. //  Returns:
  292. //    LPTSTR
  293. //
  294. //  Comments:
  295. //
  296. //
  297. //////////////////////////////////////////////////////////////////////////
  298. LPTSTR GetDefaultICMProfile(HDC hDC)
  299. {
  300.     // Local variables
  301.     LPTSTR    lpszProfileName;
  302.     BOOL      bProfile;
  303.     DWORD     dwProfileLen;
  304.     TCHAR     stProfileName[MAX_PATH+1];
  305.     HGLOBAL   hFree;
  306.     //  Initialize variables
  307.     lpszProfileName = NULL;
  308.     dwProfileLen = 0;
  309.     stProfileName[0] = __TEXT('');
  310.     // Query for size of profile name string
  311.     bProfile = GetICMProfile(hDC, &dwProfileLen, NULL);
  312.     if (bProfile)
  313.     {
  314.         DebugMsg(__TEXT("GetDefaultICMProfile:  GetICMProfile returned TRUE on query, dwProfileLen = %ldrn"), dwProfileLen);
  315.         return(FALSE);
  316.     }
  317.     if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
  318.     {
  319.         DebugMsg(__TEXT("GetDefaultICMProfile:  GetICMProfile set unexpected LastError %ld on query, dwProfileLen = %ldrn"),
  320.                  GetLastError(), dwProfileLen);
  321.         DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  322.         dwProfileLen = MAX_PATH;
  323.     }
  324.     else
  325.     {
  326.         if (0 == dwProfileLen)
  327.         {
  328.             DebugMsg(__TEXT("GetDefaultICMProfile:  GetICMProfile returned FALSE on query, DID NOT SET dwProfileLenrn"));
  329.             return(FALSE);
  330.         }
  331.     }
  332.     // Fill in lpszProfileName with actual profile filename
  333.     lpszProfileName = GlobalAlloc(GPTR, (dwProfileLen+1) * sizeof(TCHAR));
  334.     if (lpszProfileName != NULL)
  335.     {
  336.         bProfile = GetICMProfile(hDC, &dwProfileLen, lpszProfileName);
  337.         if (!bProfile)
  338.         {
  339.             DebugMsg(__TEXT("GetDefaultICMProfile:  GetICMProfile FAILEDrn"));
  340.             DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  341.             hFree = GlobalFree(lpszProfileName);
  342.             return(NULL);
  343.         }
  344.         else  // Successfully id'd default profile
  345.         {
  346.             TCHAR   szName[MAX_PATH], szExt[MAX_PATH];
  347.             DebugMsg(__TEXT("Full profile name:  <%s>rn"), lpszProfileName);
  348.             _tsplitpath(lpszProfileName, NULL, NULL, szName, szExt);
  349.             wsprintf(lpszProfileName, __TEXT("%s%s"), szName, szExt);
  350.         }
  351.     }
  352.     else
  353.     {
  354.         DebugMsg(__TEXT("GetDefaultICMProfile:  Unable to allocate lpszProfileName.rn"));
  355.     }
  356.     return(lpszProfileName);
  357. } // End of function GetDefaultICMProfile
  358. //////////////////////////////////////////////////////////////////////////
  359. //  Function:  TransformDIBOutsideDC
  360. //
  361. //  Description:
  362. //    Transforms the provided hDIB using the provided profile names.
  363. //
  364. //  Parameters:
  365. //    HANDLE      Handle to DIB to process
  366. //    LPTSTR      Destination profile
  367. //    LPTSTR      Target profile
  368. //
  369. //  Returns:
  370. //    HANDLE to transformed bits; NULL upon failure.
  371. //
  372. //  Comments:
  373. //    Uses ICM functions
  374. //        CreateColorTransform
  375. //        TranslateBitmapBits
  376. //        TranslateColors
  377. //
  378. //////////////////////////////////////////////////////////////////////////
  379. HANDLE TransformDIBOutsideDC(HANDLE hDIB, BMFORMAT bmInput, LPTSTR lpszDestProfile,
  380.                              LPTSTR lpszTargetProfile, DWORD dwIntent, PBMCALLBACKFN pBMCallback,
  381.                              ULONG ulCallbackData)
  382. {
  383.     // Local variables
  384.     HANDLE          hDIBTransformed;    // Handle to transformed DIB
  385.     HPROFILE        hDestProfile, hTargetProfile;
  386.     HTRANSFORM      hTransform;
  387.     LPLOGCOLORSPACE lpLogColorSpace;
  388.     PVOID           pSrcBits, pDestBits;
  389.     LPBITMAPINFOHEADER  lpbSrcDIBHdr, lpbDestDIBHdr;
  390.     BOOL            bTranslated, bProfileClosed, bDeleted, bDeleteProfile;
  391.     DWORD           dwCopySize;
  392.     //  Initialize variables
  393.     ASSERT(NULL != hDIB);
  394.     ASSERT(NULL != lpszDestProfile);
  395.     hDIBTransformed = NULL;
  396.     SetLastError(0);
  397.     hTransform = NULL;
  398.     bTranslated = FALSE;
  399.     hDestProfile   = OpenColorProfileFromFile(lpszDestProfile );
  400.     hTargetProfile = OpenColorProfileFromFile(lpszTargetProfile);
  401.     if (NULL == hDestProfile)
  402.     {
  403.         DebugMsg(__TEXT("TransformDIBOutsideDC : NULL dest filern"));
  404.         return(NULL);
  405.     }
  406.     // Get bits from original DIB
  407.     lpbSrcDIBHdr = GlobalLock(hDIB);
  408.     pSrcBits = (PVOID)FindDIBBits(lpbSrcDIBHdr);
  409.     // Get LPLOGCOLORSPACE for transform
  410.     lpLogColorSpace = GetColorSpaceFromBitmap(lpbSrcDIBHdr, dwIntent, &bDeleteProfile);
  411.     if (NULL != lpLogColorSpace)
  412.     {
  413.         //Create the transform to use
  414.         SetLastError(0);
  415.         hTransform = CreateColorTransform(lpLogColorSpace, hDestProfile, hTargetProfile, ENABLE_GAMUT_CHECKING | NORMAL_MODE | 0x80000000);
  416.         if (NULL != hTransform)
  417.         {
  418.             // Allocate for new DIB
  419.             hDIBTransformed = GlobalAlloc(GHND, GlobalSize(hDIB));
  420.             lpbDestDIBHdr = GlobalLock(hDIBTransformed);
  421.             switch (BITCOUNT(lpbSrcDIBHdr))
  422.             {
  423.                 DWORD   dwSrcOffBytes, dwDestOffBytes;
  424.                 case 1: // BM_1GRAY:
  425.                 case 4:
  426.                 case 8:
  427.                     ASSERT((((LPBITMAPV5HEADER)lpbSrcDIBHdr)->bV5ClrUsed) <= (DWORD)( 1 << ((LPBITMAPV5HEADER)lpbSrcDIBHdr)->bV5BitCount));
  428.                     // Copy entire DIB.  Color table will be replaced by TranslateColors
  429.                     dwCopySize = GlobalSize(hDIB);
  430.                     memset(lpbDestDIBHdr, 0x17, dwCopySize);
  431.                     memcpy(lpbDestDIBHdr, lpbSrcDIBHdr, dwCopySize);
  432.                     dwSrcOffBytes = *(LPDWORD)lpbSrcDIBHdr;
  433.                     dwDestOffBytes   = *(LPDWORD)lpbDestDIBHdr;
  434.                     pSrcBits  = (PBYTE)lpbSrcDIBHdr  + dwSrcOffBytes;
  435.                     pDestBits = (PBYTE)lpbDestDIBHdr + dwDestOffBytes;
  436.                     // Needed to use different translation if BITMAPCORE bitmap.
  437.                     if (dwSrcOffBytes >= sizeof(BITMAPINFOHEADER))
  438.                     {
  439.                         bTranslated = TranslateColorTable(hTransform,
  440.                                                           (PCOLOR)pSrcBits, // paInputColors,
  441.                                                           ((LPBITMAPV5HEADER)lpbSrcDIBHdr)->bV5ClrUsed, // nColors,
  442.                                                           COLOR_RGB, // ctInput,
  443.                                                           (PCOLOR)pDestBits, // paOutputColors,
  444.                                                           COLOR_RGB,  // ctOutput)
  445.                                                           lpbSrcDIBHdr->biBitCount);
  446.                     }
  447.                     else
  448.                     {
  449.                         bTranslated = TranslateBitmapBits(hTransform,
  450.                                                           pSrcBits,
  451.                                                           BM_RGBTRIPLETS,
  452.                                                           NumColorsInDIB(lpbSrcDIBHdr),
  453.                                                           1,
  454.                                                           0,
  455.                                                           pDestBits,
  456.                                                           BM_RGBTRIPLETS,
  457.                                                           0,
  458.                                                           NULL,
  459.                                                           0);
  460.                     }
  461.                     if (0 == bTranslated)
  462.                     {
  463.                         DebugMsg(__TEXT("TransformDIBOutsideDC : TranslateColors failed, :"));
  464.                         DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  465.                     }
  466.                     break;
  467.                 case 16: // BM_RGBTRIPLETS:
  468.                 case 24: // BM_xRGBQUADS:
  469.                 case 32: // BM_x555RGB:
  470.                     // Copy header from original DIB to new DIB
  471.                     memcpy(lpbDestDIBHdr, lpbSrcDIBHdr, sizeof(BITMAPV5HEADER));
  472.                     pDestBits = (PVOID)FindDIBBits(lpbDestDIBHdr);
  473.                     bTranslated = TranslateBitmapBits(hTransform,
  474.                                                       pSrcBits,
  475.                                                       bmInput,
  476.                                                       BITMAPWIDTH(lpbSrcDIBHdr),
  477.                                                       abs(BITMAPHEIGHT(lpbSrcDIBHdr)),
  478.                                                       0,
  479.                                                       pDestBits,
  480.                                                       bmInput,
  481.                                                       0,
  482.                                                       pBMCallback,
  483.                                                       ulCallbackData);
  484.                     if (0 == bTranslated)
  485.                     {
  486.                         DebugMsg(__TEXT("TransformDIBOutsideDC : TranslateBitmapBits failed:rn"));
  487.                         DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  488.                     }
  489.                     break;
  490.                 default:  // 8bpp
  491.                     DebugMsg(__TEXT("TransformDIBOutsideDC : Unrecognized formatrn"));
  492.                     bTranslated = FALSE;
  493.                     break;
  494.             }
  495.             bDeleted = DeleteColorTransform(hTransform);
  496.             if (0 == bDeleted)
  497.             {
  498.                 DebugMsg(__TEXT("TransformDIBOutsideDC : DeleteColorTransform failed, : "));
  499.                 DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  500.             }
  501.         }
  502.         else
  503.         {
  504.             ErrMsg(NULL, __TEXT("TransformDIBOutsideDC : CreateColorTransform failed"));
  505.             DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  506.         }
  507.         if (bDeleteProfile)
  508.         {
  509.             DeleteFile(lpLogColorSpace->lcsFilename);
  510.         }
  511.         GlobalFree((HANDLE)lpLogColorSpace);
  512.     }
  513.     else // Failed to get LOGCOLORSPACE
  514.     {
  515.         ErrMsg(NULL, __TEXT("TransformDIBOutsideDC : Failed to get LOGCOLORSPACE"));
  516.     }
  517.     if (NULL != hDestProfile)
  518.     {
  519.         bProfileClosed = CloseColorProfile(hDestProfile);
  520.         if (0 == bProfileClosed)
  521.         {
  522.             DebugMsg(__TEXT("TransformDIBOutsideDC : Failed to close hDestProfile, "));
  523.             DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  524.         }
  525.     }
  526.     if (NULL != hTargetProfile)
  527.     {
  528.         bProfileClosed = CloseColorProfile(hTargetProfile);
  529.         if (0 == bProfileClosed)
  530.         {
  531.             DebugMsg(__TEXT("TransformDIBOutsideDC : Failed to close hTargetProfile, "));
  532.             DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  533.         }
  534.     }
  535.     if (NULL != hDIBTransformed)
  536.     {
  537.         GlobalUnlock(hDIBTransformed);
  538.     }
  539.     if ((NULL == hTransform) || (0 == bTranslated))
  540.     {
  541.         if (NULL != hDIBTransformed)
  542.         {
  543.             GlobalFree(hDIBTransformed);
  544.             hDIBTransformed = NULL;
  545.         }
  546.         lpbDestDIBHdr = NULL;
  547.         pDestBits = NULL;
  548.     }
  549.     return(hDIBTransformed);
  550. }   // End of function TransformDIBOutsideDC
  551. //////////////////////////////////////////////////////////////////////////
  552. //  Function:  OpenColorProfileFromFile
  553. //
  554. //  Description:
  555. //    Creates a color profile based upon the parameters passed.
  556. //
  557. //  Parameters:
  558. //    LPTSTR  Profile name
  559. //
  560. //  Returns:
  561. //    HPROFILE Handle to PROFILE structure, NULL if failure.
  562. //
  563. //  Comments:
  564. //
  565. //
  566. //////////////////////////////////////////////////////////////////////////
  567. HPROFILE OpenColorProfileFromFile(LPTSTR lpszProfileName)
  568. {
  569.     // Local variables
  570.     PPROFILE  pProfile;
  571.     HPROFILE  hProfile;
  572.     DWORD     cbDataSize;
  573.     DWORD     dwProfileSize;
  574.     TCHAR     stFullProfile[MAX_PATH];
  575.     BOOL      bValid;
  576.     //  Initialize variables
  577.     if (NULL == lpszProfileName)
  578.     {
  579.         return(NULL);
  580.     }
  581.     // Add COLOR dir path if profile name does not contain a path.
  582.     if ( (NULL == _tcschr(lpszProfileName, __TEXT(':')))
  583.          &&
  584.          (NULL == _tcschr(lpszProfileName, __TEXT('\')))
  585.        )
  586.     {
  587.         wsprintf(stFullProfile, __TEXT("%s\%s"), gstProfilesDir, lpszProfileName);
  588.     }
  589.     else
  590.     {
  591.         lstrcpy(stFullProfile, lpszProfileName);
  592.     }
  593.     dwProfileSize = sizeof(PROFILE);
  594.     cbDataSize = (lstrlen(stFullProfile) * sizeof(TCHAR)) + sizeof(TCHAR); // String plus NULL
  595.     pProfile = GlobalAlloc(GPTR, (dwProfileSize + cbDataSize));
  596. #ifdef _DEBUG
  597.     memset(pProfile, UNINIT_BYTE, (cbDataSize+dwProfileSize));
  598. #endif
  599.     pProfile->dwType = PROFILE_FILENAME;
  600.     pProfile->cbDataSize = cbDataSize;
  601.     pProfile->pProfileData = (PVOID)((LPBYTE)pProfile + dwProfileSize);
  602.     _tcscpy(pProfile->pProfileData, stFullProfile);
  603.     hProfile = OpenColorProfile(pProfile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);
  604.     if (NULL  == hProfile)
  605.     {
  606.         ErrMsg(NULL,__TEXT("Unable to open color profile <%s>"), stFullProfile);
  607.         DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  608.     }
  609.     else
  610.     {
  611.         // Validate the profile
  612.         bValid = IsColorProfileValid(hProfile, &bValid);
  613.         if (0 == bValid)
  614.         {
  615.             ErrMsg(NULL,__TEXT("Color profile %s is not valid"), stFullProfile);
  616.             DISPLAY_LASTERROR(LASTERROR_NOALLOC, GetLastError());
  617.             CloseColorProfile(hProfile);
  618.             hProfile = NULL;
  619.         }
  620.     }
  621.     // Cleanup
  622.     GlobalFree(GlobalHandle(pProfile));
  623.     return(hProfile);
  624. }   // End of function OpenColorProfileFromDisk
  625. ///////////////////////////////////////////////////////////////////////
  626. //
  627. // Function:   GetColorSpaceFromBitmap
  628. //
  629. // Purpose:    Creates a LOGCOLORSPACE based on information in bitmap.
  630. //
  631. //
  632. // Parms:      lpBitmapHeader   Pointer to bitmap header and info.
  633. //             dwIntent         Color Space Intent.
  634. //             pbDeleteProfile  Flag, on return, will indicate if the profile needs
  635. //                              to be deleted before LOGCOLORSPACE is freed.
  636. //
  637. //
  638. ///////////////////////////////////////////////////////////////////////
  639. LPLOGCOLORSPACE GetColorSpaceFromBitmap(LPBITMAPINFOHEADER lpBitmapInfo, DWORD dwIntent,
  640.                                         LPBOOL pbDeleteProfile)
  641. {
  642.     LPLOGCOLORSPACE lpColorSpace = NULL;
  643.     PBITMAPV5HEADER lpBitmapV5 = (PBITMAPV5HEADER) lpBitmapInfo;
  644.     // Validate parameters.
  645.     ASSERT(NULL != lpBitmapInfo);
  646.     if ( (NULL == lpBitmapInfo)
  647.          ||
  648.          (NULL == pbDeleteProfile)
  649.          ||
  650.          ( (sizeof(BITMAPCOREHEADER) != lpBitmapInfo->biSize)
  651.            &&
  652.            (sizeof(BITMAPINFOHEADER) != lpBitmapInfo->biSize)
  653.            &&
  654.            (sizeof(BITMAPV4HEADER) != lpBitmapInfo->biSize)
  655.            &&
  656.            (sizeof(BITMAPV5HEADER) != lpBitmapInfo->biSize)
  657.          )
  658.        )
  659.     {
  660.         return NULL;
  661.     }
  662.     // Initalize delete flag.
  663.     *pbDeleteProfile = FALSE;
  664.     // Allocate LOGCOLORSPACE.
  665.     lpColorSpace = (LPLOGCOLORSPACE) GlobalAlloc(GPTR, sizeof(LOGCOLORSPACE));
  666.     if (NULL == lpColorSpace)
  667.     {
  668.         return NULL;
  669.     }
  670.     // Initialize color space.
  671.     lpColorSpace->lcsSignature = 'PSOC';  // The signature should always be 'PSOC'.
  672.     lpColorSpace->lcsVersion = 0x400;
  673.     lpColorSpace->lcsSize = sizeof(LOGCOLORSPACE);
  674.     // If BITMAPCOREHEADER or BITMAPINFOHEADER, bitmap has no information
  675.     // about color space; use sRGB.
  676.     if (sizeof(BITMAPINFOHEADER) >= lpBitmapInfo->biSize)
  677.     {
  678.         // Set color space to default values.
  679.         lpColorSpace->lcsCSType = LCS_sRGB;
  680.         // Set endpoints to sRGB values.
  681.         lpColorSpace->lcsEndpoints.ciexyzRed.ciexyzX = __FXPT2DOT30(.64);
  682.         lpColorSpace->lcsEndpoints.ciexyzRed.ciexyzY = __FXPT2DOT30(.33);
  683.         lpColorSpace->lcsEndpoints.ciexyzRed.ciexyzZ = __FXPT2DOT30(.03);
  684.         lpColorSpace->lcsEndpoints.ciexyzGreen.ciexyzX = __FXPT2DOT30(.3);
  685.         lpColorSpace->lcsEndpoints.ciexyzGreen.ciexyzY = __FXPT2DOT30(.6);
  686.         lpColorSpace->lcsEndpoints.ciexyzGreen.ciexyzZ = __FXPT2DOT30(.1);
  687.         lpColorSpace->lcsEndpoints.ciexyzBlue.ciexyzX   =   __FXPT2DOT30(  .15);
  688.         lpColorSpace->lcsEndpoints.ciexyzBlue.ciexyzY = __FXPT2DOT30(.06);
  689.         lpColorSpace->lcsEndpoints.ciexyzBlue.ciexyzZ = __FXPT2DOT30(.79);
  690.         // Just so that if monitor has 2.2 gamma, the over all gamma is 1.0.
  691.         lpColorSpace->lcsGammaRed = __FXPT16DOT16(0.45);
  692.         lpColorSpace->lcsGammaGreen = __FXPT16DOT16(0.45);
  693.         lpColorSpace->lcsGammaBlue = __FXPT16DOT16(0.45);
  694.     }
  695.     else
  696.     {
  697.         // Copy information from portion that is similar between BITMAPV4HEADERs and
  698.         // BITMAPV5HEADERs.
  699.         memcpy(&lpColorSpace->lcsEndpoints, &lpBitmapV5->bV5Endpoints, sizeof(CIEXYZTRIPLE));
  700.         lpColorSpace->lcsGammaRed = lpBitmapV5->bV5GammaRed;
  701.         lpColorSpace->lcsGammaGreen = lpBitmapV5->bV5GammaGreen;
  702.         lpColorSpace->lcsGammaBlue = lpBitmapV5->bV5GammaBlue;
  703.         // BITMAPV4HEADERs do not have complete color space information,
  704.         // we need to assume some things.
  705.         if (sizeof(BITMAPV4HEADER) == lpBitmapInfo->biSize)
  706.         {
  707.             // Fill in default values for fields that do not
  708.             // have equivalents in BITMAPV4HEADER.
  709.             lpColorSpace->lcsCSType = lpBitmapV5->bV5CSType;
  710.             lpColorSpace->lcsIntent = LCS_GM_IMAGES;
  711.         }
  712.         else
  713.         {
  714.             // BITMAPV5HEADERs have complete color space information.
  715.             // No assumptions to make.
  716.             lpColorSpace->lcsIntent = lpBitmapV5->bV5Intent;
  717.             // Look to see if no, linked, or embedded profile.
  718.             switch (lpBitmapV5->bV5CSType)
  719.             {
  720.                 case 'MBED':
  721.                     // Need to create profile file and reference
  722.                     // profile in the color space.
  723.                     lpColorSpace->lcsCSType = LCS_CALIBRATED_RGB;
  724.                     // Make sure that profile data offset is valid and not zero length.
  725.                     if ( (lpBitmapV5->bV5Size > lpBitmapV5->bV5ProfileData)
  726.                          ||
  727.                          (0L == lpBitmapV5->bV5ProfileSize)
  728.                        )
  729.                     {
  730.                         GlobalFree((HANDLE)lpColorSpace);
  731.                         return NULL;
  732.                     }
  733.                     // Create unique temp name.
  734.                     {
  735.                         DWORD   dwWritten;
  736.                         TCHAR   szTempPath[MAX_PATH];
  737.                         HANDLE  hFile;
  738.                         GetTempPath(MAX_PATH, szTempPath);
  739.                         if (!GetTempFileName(szTempPath, __TEXT("ICM"), 0, lpColorSpace->lcsFilename))
  740.                         {
  741.                             GlobalFree((HANDLE)lpColorSpace);
  742.                             return NULL;
  743.                         }
  744.                         // Create temp profile that contains the embedded profile.
  745.                         hFile = CreateFile(lpColorSpace->lcsFilename, GENERIC_READ | GENERIC_WRITE,
  746.                                            0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  747.                         if (INVALID_HANDLE_VALUE == hFile)
  748.                         {
  749.                             GlobalFree((HANDLE)lpColorSpace);
  750.                             return NULL;
  751.                         }
  752.                         // Write embedded profile to disk.
  753.                         WriteFile(hFile, GETPROFILEDATA(lpBitmapV5), lpBitmapV5->bV5ProfileSize,
  754.                                   &dwWritten, NULL);
  755.                         // No longer need file open.
  756.                         CloseHandle(hFile);
  757.                         // Need to indicate to caller that this file needs to be deleted
  758.                         // before LOGCOLORSPACE is freed.
  759.                         *pbDeleteProfile = TRUE;
  760.                     }
  761.                     break;
  762.                 case 'LINK':
  763.                     // Need to reference profile.
  764.                     lpColorSpace->lcsCSType = LCS_CALIBRATED_RGB;
  765.                     lstrcpyn(lpColorSpace->lcsFilename, (LPTSTR) GETPROFILEDATA(lpBitmapV5), MAX_PATH);
  766.                     break;
  767.                 default:
  768.                     // Just use color space type in the bitmap.
  769.                     lpColorSpace->lcsCSType = lpBitmapV5->bV5CSType;
  770.                     break;
  771.             }
  772.         }
  773.     }
  774.     // Set intent to default or to users selection.
  775.     if (0xffffffffL == dwIntent)
  776.     {
  777.         lpColorSpace->lcsIntent = LCS_GM_IMAGES;
  778.     }
  779.     else
  780.     {
  781.         lpColorSpace->lcsIntent = dwIntent;
  782.     }
  783.     return(lpColorSpace);
  784. }
  785. //
  786. // Functions for extracting information from DIBs
  787. //
  788. //////////////////////////////////////////////////////////////////////////
  789. //  Function:  NumColorsInDIB
  790. //
  791. //  Description:
  792. //    Determines the number of colors in the DIB by looking at the
  793. //    BitCount field in the info block.
  794. //
  795. //  Parameters:
  796. //    LPBINTMAPV5HEADER Pointer to BITMAPINFO structure
  797. //
  798. //  Returns:
  799. //    DWORD   Number of colors in the DIB
  800. //
  801. //  Comments:
  802. //
  803. //
  804. //////////////////////////////////////////////////////////////////////////
  805. DWORD NumColorsInDIB(LPBITMAPINFOHEADER lpbi)
  806. {
  807.     WORD    wBitCount;
  808.     DWORD   dwColors = 0;
  809.     // If this is a Windows style DIB, the number of colors in the
  810.     //  color table can be less than the number of bits per pixel
  811.     //  allows for (i.e. lpbi->biClrUsed can be set to some value).
  812.     //  If this is the case, return the appropriate value.
  813.     if ( (sizeof(BITMAPINFOHEADER) <= lpbi->biSize)
  814.          &&
  815.          (0 != lpbi->biClrUsed)
  816.        )
  817.     {
  818.         dwColors = lpbi->biClrUsed;
  819.     }
  820.     else
  821.     {
  822.         // Calculate the number of colors in the color table based on
  823.         //  the number of bits per pixel for the DIB.
  824.         wBitCount = BITCOUNT(lpbi);
  825.         if (MAX_BPP_COLOR_TABLE >= wBitCount)
  826.         {
  827.             dwColors = 1 << wBitCount;  // Colors = 2^BitCount
  828.         }
  829.     }
  830.     return dwColors;
  831. }   // End of function NumColorsInDIB
  832. //////////////////////////////////////////////////////////////////////////
  833. //  Function:  PaletteSize
  834. //
  835. //  Description:
  836. //    Calculates the palette size in bytes.
  837. //
  838. //  Parameters:
  839. //    @@@
  840. //
  841. //  Returns:
  842. //    DWORD   Palette size in bytes.
  843. //
  844. //  Comments:
  845. //
  846. //
  847. //////////////////////////////////////////////////////////////////////////
  848. DWORD PaletteSize(LPBITMAPINFOHEADER lpbi)
  849. {
  850.     DWORD   dwSize = 0L;
  851.     if (sizeof(BITMAPINFOHEADER) <= lpbi->biSize)
  852.     {
  853.         dwSize = NumColorsInDIB(lpbi) * sizeof(RGBQUAD);
  854.         if ( (lpbi->biCompression == BI_BITFIELDS)
  855.              &&
  856.              (sizeof(BITMAPV4HEADER) > lpbi->biSize)
  857.            )
  858.         {
  859.             dwSize = 3 * sizeof(DWORD);
  860.         }
  861.     }
  862.     else
  863.     {
  864.         dwSize = NumColorsInDIB(lpbi) * sizeof (RGBTRIPLE);
  865.     }
  866.     return dwSize;
  867. }   // End of function PaletteSize
  868. ///////////////////////////////////////////////////////////////////////
  869. //
  870. // Function:   FindDIBBits
  871. //
  872. // Purpose:    Given a pointer to a DIB, returns a pointer to the
  873. //             DIB's bitmap bits.
  874. //
  875. // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
  876. //                       or BITMAPCOREHEADER)
  877. //
  878. ///////////////////////////////////////////////////////////////////////
  879. LPBYTE FindDIBBits(LPBITMAPINFOHEADER lpbi)
  880. {
  881.     ASSERT(NULL != lpbi);
  882.     return ((LPBYTE)lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi) + PROFILESIZE(lpbi));
  883. }
  884. ///////////////////////////////////////////////////////////////////////
  885. //
  886. // Function:   FindDIBBits
  887. //
  888. // Purpose:    Given a pointer to a DIB, returns a pointer to the
  889. //             DIB's bitmap bits.
  890. //
  891. // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
  892. //                       or BITMAPCOREHEADER)
  893. //
  894. ///////////////////////////////////////////////////////////////////////
  895. LPBYTE FindColorTable(LPBITMAPINFOHEADER lpbi)
  896. {
  897.     ASSERT(NULL != lpbi);
  898.     return ((LPBYTE)lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi) + PROFILESIZE(lpbi));
  899. }
  900. ///////////////////////////////////////////////////////////////////////
  901. //
  902. // Function:   DIBHeight
  903. //
  904. // Purpose:    Given a pointer to a DIB, returns the ABSOLUTE VALUE of
  905. //             its height.  Note that it returns a DWORD (since a Win30
  906. //             DIB can have a DWORD in its height field), but under
  907. //             Win30, the high order word isn't used!
  908. //
  909. // Parms:      lpDIB == pointer to DIB header (either BITMAPINFOHEADER
  910. //                       or BITMAPCOREHEADER)
  911. //
  912. ///////////////////////////////////////////////////////////////////////
  913. LONG DIBHeight (LPBYTE lpDIB)
  914. {
  915.     LPBITMAPINFOHEADER lpbmi;
  916.     LPBITMAPCOREHEADER lpbmc;
  917.     lpbmi = (LPBITMAPINFOHEADER) lpDIB;
  918.     lpbmc = (LPBITMAPCOREHEADER) lpDIB;
  919.     if (lpbmi->biSize >= sizeof (BITMAPINFOHEADER))
  920.     {
  921.         return labs(lpbmi->biHeight); // biHeight can now be negative! 8/9/93
  922.     }
  923.     else
  924.     {
  925.         return (LONG) lpbmc->bcHeight;
  926.     }
  927. }
  928. ///////////////////////////////////////////////////////////////////////
  929. //
  930. // Function:   DIBWidth
  931. //
  932. // Purpose:    Given a pointer to a DIB, returns its width.  Note
  933. //             that it returns a DWORD (since a Win30 DIB can have
  934. //             a DWORD in its width field), but under Win30, the
  935. //             high order word isn't used!
  936. //
  937. // Parms:      lpDIB == pointer to DIB header (either BITMAPINFOHEADER
  938. //                       or BITMAPCOREHEADER)
  939. //
  940. ///////////////////////////////////////////////////////////////////////
  941. LONG DIBWidth (LPBYTE lpDIB)
  942. {
  943.     LPBITMAPINFOHEADER lpbmi;
  944.     LPBITMAPCOREHEADER lpbmc;
  945.     lpbmi = (LPBITMAPINFOHEADER) lpDIB;
  946.     lpbmc = (LPBITMAPCOREHEADER) lpDIB;
  947.     if (lpbmi->biSize >= sizeof (BITMAPINFOHEADER))
  948.     {
  949.         return lpbmi->biWidth;
  950.     }
  951.     else
  952.     {
  953.         return (LONG) lpbmc->bcWidth;
  954.     }
  955. }
  956. //
  957. //  Functions for reading DIBs
  958. //
  959. //////////////////////////////////////////////////////////////////////////
  960. //  Function:  ReadDIBFile
  961. //
  962. //  Description:
  963. //     Open a DIB file and create
  964. //          -a memory DIB
  965. //          -a memory handle containing BITMAPINFO, palette, and the bits
  966. //
  967. //
  968. //  Parameters:
  969. //    @@@
  970. //
  971. //  Returns:
  972. //    HGLOBAL Handle to DIB memory; NULL upon failure.
  973. //
  974. //  Comments:
  975. //
  976. //////////////////////////////////////////////////////////////////////////
  977. HGLOBAL ReadDIBFile(LPTSTR lpszFileName)
  978. {
  979.     // Local variables
  980.     HGLOBAL             hDIBInfo;
  981.     LPDIBINFO           lpDIBInfo;
  982.     BOOL                bGotDIBInfo;
  983.     //  Initialize variables
  984.     hDIBInfo = CreateDIBInfo();
  985.     if (hDIBInfo == NULL)
  986.     {
  987.         return(NULL);
  988.     }
  989.     lpDIBInfo = GlobalLock(hDIBInfo);
  990.     if (lpDIBInfo == (LPDIBINFO)NULL)
  991.     {
  992.         GlobalFree(hDIBInfo);
  993.         return(NULL);
  994.     }
  995.     bGotDIBInfo =  fReadDIBInfo(lpszFileName, lpDIBInfo);
  996.     GlobalUnlock(hDIBInfo);
  997.     if (0 == bGotDIBInfo)  // failed to open file
  998.     {
  999.         fFreeDIBInfo(hDIBInfo, TRUE);
  1000.         hDIBInfo = NULL;
  1001.     }
  1002.     return(hDIBInfo);
  1003. }   // End of function ReadDIBFile
  1004. //////////////////////////////////////////////////////////////////////////
  1005. //  Function:   ReadDIBFromFile
  1006. //
  1007. //  Description:
  1008. //      Reads in the bitmap information.
  1009. //
  1010. //  Parameters:
  1011. //      hFile   Handle to bitmap file.
  1012. //
  1013. //  Returns:  Handle to DIB Bitmap.  NULL on error.
  1014. //
  1015. //  Comments:
  1016. //
  1017. //////////////////////////////////////////////////////////////////////////
  1018. HANDLE ReadDIBFromFile(HANDLE hFile)
  1019. {
  1020.     UINT                    nNumColors;
  1021.     DWORD                   offBits;
  1022.     DWORD                   dwRead;
  1023.     DWORD                   dwImageBytes;
  1024.     DWORD                   dwSizeImage;
  1025.     HANDLE                  hDIB;
  1026.     BITMAPFILEHEADER        BmpFileHeader;
  1027.     LPBITMAPINFOHEADER      lpbi;
  1028.     // Make sure non-null file handle.
  1029.     if (NULL == hFile)
  1030.     {
  1031.         return NULL;
  1032.     }
  1033.     // Read in Bitmap file header.
  1034.     if (0L != SetFilePointer(hFile, 0, NULL, FILE_BEGIN))
  1035.     {
  1036.         return NULL;
  1037.     }
  1038.     ReadFile(hFile, &BmpFileHeader, sizeof(BITMAPFILEHEADER), &dwRead, NULL);
  1039.     if (sizeof(BITMAPFILEHEADER) != dwRead)
  1040.     {
  1041.         return NULL;
  1042.     }
  1043.     // Make sure that the file is a bitmap file.
  1044.     if (BFT_BITMAP != BmpFileHeader.bfType)
  1045.     {
  1046.         return NULL;
  1047.     }
  1048.     // Detemine size of bitmap header.
  1049.     ReadFile(hFile, &dwImageBytes, sizeof(DWORD), &dwRead, NULL);
  1050.     if (sizeof(DWORD) != dwRead)
  1051.     {
  1052.         return NULL;
  1053.     }
  1054.     // Allocate memory for header & color table.
  1055.     // We'll enlarge this memory as needed.
  1056.     hDIB = GlobalAlloc(GHND, dwImageBytes + (256L * sizeof(RGBQUAD)));
  1057.     if (!hDIB)
  1058.     {
  1059.         return NULL;
  1060.     }
  1061.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1062.     if (!lpbi)
  1063.     {
  1064.         GlobalFree(hDIB);
  1065.         return NULL;
  1066.     }
  1067.     // Back up to begining of bitmap header and read bitmap header.
  1068.     SetFilePointer(hFile, sizeof(BITMAPFILEHEADER), NULL, FILE_BEGIN);
  1069.     ReadFile(hFile, lpbi, dwImageBytes, &dwRead, NULL);
  1070.     if (dwRead != dwImageBytes)
  1071.     {
  1072.         GlobalUnlock(hDIB);
  1073.         GlobalFree(hDIB);
  1074.         return NULL;
  1075.     }
  1076.     // Dump debug info about type of bitmap opened.
  1077. #ifdef MAXDEBUG
  1078.     DumpBmpHeader((LPVOID)lpbi);
  1079. #endif
  1080.     // Check to see that it's a Windows DIB or an OS/2 DIB.
  1081.     // It assumed that anything that is not a OS/2 DIB is a Windows DIB.
  1082.     // This at least allows the opening of newer bitmap types, although GDI
  1083.     // may not handle them so we may not be able to display them.
  1084.     // More critical checking could be done by checking against
  1085.     // BITMAPV4HEADER and BITMAPV5HEADER sizes.
  1086.     if (lpbi->biSize >= sizeof(BITMAPINFOHEADER))
  1087.     {
  1088.         DWORD   dwProfileData = 0;
  1089.         DWORD   dwColorTableSize;
  1090.         HANDLE  hTemp;
  1091.         // Now determine the size of the color table and read it.  Since the
  1092.         // bitmap bits are offset in the file by bfOffBits, we need to do some
  1093.         // special processing here to make sure the bits directly follow
  1094.         // the color table (because that's the format we are susposed to pass
  1095.         // back)
  1096.         // no color table for 24-bit, default size otherwise
  1097.         nNumColors = (UINT)lpbi->biClrUsed;
  1098.         if (0 == nNumColors)
  1099.         {
  1100.             if (lpbi->biBitCount <= MAX_BPP_COLOR_TABLE)
  1101.             {
  1102.                 nNumColors = 1 << lpbi->biBitCount;             // standard size table
  1103.             }
  1104.         }
  1105.         // Fill in some default values if they are zero
  1106.         if (0 == lpbi->biClrUsed)
  1107.         {
  1108.             lpbi->biClrUsed = nNumColors;
  1109.         }
  1110.         if (0 == lpbi->biSizeImage)
  1111.         {
  1112.             // Calculate size using DWORD alignment
  1113.             dwSizeImage = (((lpbi->biWidth * lpbi->biBitCount + 31) & ~31)
  1114.                            >> 3) * abs(lpbi->biHeight);
  1115.         }
  1116.         else
  1117.         {
  1118.             dwSizeImage = lpbi->biSizeImage;
  1119.         }
  1120.         // get a proper-sized buffer for header, color table and bits
  1121.         // Figure out the size of the bitmap AND it's color table.
  1122.         dwColorTableSize = PaletteSize(lpbi);
  1123.         // Calculate profile data size;
  1124.         // zero if not BITMAPV5HEADER, else in use bV5ProfileSize.
  1125.         dwProfileData =  PROFILESIZE(lpbi);
  1126.         // Resize DIB buffer.
  1127.         dwImageBytes = lpbi->biSize + dwSizeImage + dwColorTableSize + dwProfileData;
  1128.         GlobalUnlock(hDIB);
  1129.         hTemp = GlobalReAlloc(hDIB, dwImageBytes, GHND);
  1130.         DebugMsg(__TEXT("ReadDIBFromFile:  Allocating %lu bytes for header, color table, and imagern"), dwImageBytes);
  1131.         if (NULL == hTemp) // can't resize buffer for loading
  1132.         {
  1133.             GlobalFree(hDIB);
  1134.             return NULL;
  1135.         }
  1136.         hDIB = hTemp;
  1137.         lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1138.         // read the color table, if any, into buffer starting past Bitmap header.
  1139.         if (0 != dwColorTableSize)
  1140.         {
  1141.             ReadFile(hFile, (LPBYTE)lpbi + lpbi->biSize, dwColorTableSize, &dwRead, NULL);
  1142.             if (dwColorTableSize != dwRead)
  1143.             {
  1144.                 GlobalUnlock(hDIB);
  1145.                 GlobalFree(hDIB);
  1146.                 return NULL;
  1147.             }
  1148.         }
  1149.         // Load profile data, if any.
  1150.         if (0 != dwProfileData)
  1151.         {
  1152.             // Move to profile data.
  1153.             SetFilePointer(hFile, sizeof(BITMAPFILEHEADER)
  1154.                            + ((LPBITMAPV5HEADER)lpbi)->bV5ProfileData, NULL, FILE_BEGIN);
  1155.             // Read the profile data in after the header and color table.
  1156.             ReadFile(hFile, (LPBYTE)lpbi + lpbi->biSize + dwColorTableSize, dwProfileData, &dwRead, NULL);
  1157.             if (dwProfileData != dwRead)
  1158.             {
  1159.                 GlobalUnlock(hDIB);
  1160.                 GlobalFree(hDIB);
  1161.                 return NULL;
  1162.             }
  1163.             // Need to change the offset in the header.
  1164.             ((LPBITMAPV5HEADER)lpbi)->bV5ProfileData = lpbi->biSize + dwColorTableSize;
  1165.         }
  1166.         // offset to the bits from start of DIB header
  1167.         offBits = lpbi->biSize + dwColorTableSize + dwProfileData;
  1168.         DumpBmpHeader((LPVOID)lpbi);
  1169.     }
  1170.     else
  1171.     {
  1172.         // It's an OS/2 DIB, the color table is an array of RGBTRIPLEs.
  1173.         HANDLE                          hTemp;
  1174.         LPBITMAPCOREHEADER      lpbc = (LPBITMAPCOREHEADER) lpbi;
  1175.         // Gotta back up to beginning of color table.
  1176.         SetFilePointer(hFile, sizeof (BITMAPFILEHEADER) + sizeof (BITMAPCOREHEADER), NULL, FILE_BEGIN);
  1177.         // Now determine the size of the color table and read it.  Since the
  1178.         // bitmap bits are offset in the file by bfOffBits, we need to do some
  1179.         // special processing here to make sure the bits directly follow
  1180.         // the color table (because that's the format we are susposed to pass
  1181.         // back)
  1182.         if (lpbc->bcBitCount <= MAX_BPP_COLOR_TABLE)
  1183.         {
  1184.             nNumColors = 1 << lpbc->bcBitCount;    // standard size table
  1185.         }
  1186.         else
  1187.         {
  1188.             nNumColors = 0;
  1189.         }
  1190.         // Determine the size of the image
  1191.         dwSizeImage = (((lpbc->bcWidth * lpbc->bcBitCount + 31) & ~31) >> 3)
  1192.                       * lpbc->bcHeight;
  1193.         // get a proper-sized buffer for header, color table and bits
  1194.         GlobalUnlock(hDIB);
  1195.         hTemp = GlobalReAlloc(hDIB, lpbc->bcSize + (nNumColors * sizeof(RGBTRIPLE))
  1196.                               + dwSizeImage, GHND);
  1197.         if (!hTemp) // can't resize buffer for loading
  1198.         {
  1199.             GlobalFree(hDIB);
  1200.             return NULL;
  1201.         }
  1202.         hDIB = hTemp;
  1203.         lpbc = (LPBITMAPCOREHEADER) GlobalLock(hDIB);
  1204.         lpbi = (LPBITMAPINFOHEADER) lpbc;
  1205.         // read the color table
  1206.         ReadFile(hFile, (LPBYTE)lpbc + lpbc->bcSize, nNumColors * sizeof(RGBTRIPLE), &dwRead, NULL);
  1207.         if (nNumColors * sizeof(RGBTRIPLE) != dwRead)
  1208.         {
  1209.             GlobalUnlock(hDIB);
  1210.             GlobalFree(hDIB);
  1211.             return NULL;
  1212.         }
  1213.         // offset to the bits from start of DIB header
  1214.         offBits = lpbc->bcSize + nNumColors * sizeof(RGBTRIPLE);
  1215.     }
  1216.     // If the bfOffBits field is non-zero, then the bits might *not* be
  1217.     // directly following the color table in the file.  Use the value in
  1218.     // bfOffBits to seek the bits.
  1219.     if (BmpFileHeader.bfOffBits != 0L)
  1220.     {
  1221.         SetFilePointer(hFile, BmpFileHeader.bfOffBits, NULL, FILE_BEGIN);
  1222.     }
  1223.     // Read the actual bits
  1224.     ReadFile(hFile, (LPBYTE)lpbi + offBits, dwSizeImage, &dwRead, NULL);
  1225.     if (dwRead != dwSizeImage)
  1226.     {
  1227.         GlobalUnlock(hDIB);
  1228.         GlobalFree(hDIB);
  1229.         return NULL;
  1230.     }
  1231.     GlobalUnlock(hDIB);
  1232.     return hDIB;
  1233. }  // End of function ReadDIBFromFile
  1234. //////////////////////////////////////////////////////////////////////////
  1235. //  Function:  TranslateColorTable
  1236. //
  1237. //  Description:
  1238. //
  1239. //
  1240. //  Parameters:
  1241. //    @@@
  1242. //
  1243. //  Returns:
  1244. //    BOOL
  1245. //
  1246. //  Comments:
  1247. //
  1248. //
  1249. //////////////////////////////////////////////////////////////////////////
  1250. BOOL TranslateColorTable(HTRANSFORM hColorTransform,
  1251.                          PCOLOR    paInputColors,
  1252.                          DWORD   nColors,
  1253.                          COLORTYPE     ctInput,
  1254.                          PCOLOR    paOutputColors,
  1255.                          COLORTYPE   ctOutput,
  1256.                          int         biBitCount
  1257.                         )
  1258. {
  1259.     //  Initialize variables
  1260.     if (ctInput == COLOR_RGB)
  1261.     {
  1262.         return(TranslateBitmapBits(hColorTransform,
  1263.                                    (PVOID)paInputColors,
  1264.                                    BM_xRGBQUADS,
  1265.                                    1<<biBitCount,
  1266.                                    1,
  1267.                                    0,
  1268.                                    (PVOID)paOutputColors,
  1269.                                    BM_xRGBQUADS,
  1270.                                    0,
  1271.                                    NULL,
  1272.                                    0));
  1273.     }
  1274.     else
  1275.     {
  1276.         return(TranslateColors(hColorTransform, paInputColors, nColors, ctInput, paOutputColors, ctOutput));
  1277.     }
  1278. }   // End of function TranslateColorTable
  1279. //////////////////////////////////////////////////////////////////////////
  1280. //  Function:  SaveDIBToFile
  1281. //
  1282. //  Description:
  1283. //
  1284. //
  1285. //  Parameters:
  1286. //    @@@
  1287. //
  1288. //  Returns:
  1289. //    BOOL
  1290. //
  1291. //  Comments:
  1292. //
  1293. //
  1294. //////////////////////////////////////////////////////////////////////////
  1295. BOOL SaveDIBToFile(HWND hWnd, LPCTSTR lpszFileName, LPDIBINFO lpDIBInfo, DWORD dwType)
  1296. {
  1297.     BOOL                bResult = FALSE;
  1298.     HANDLE              hFile;
  1299.     HANDLE              hDIBTransformed = NULL;
  1300.     PBITMAPINFOHEADER   pBitmapInfo;
  1301.     // Validate Parameters.
  1302.     if ( (NULL == lpszFileName)
  1303.          ||
  1304.          (NULL == lpDIBInfo)
  1305.          ||
  1306.          (NULL == lpDIBInfo->hDIB)
  1307.          ||
  1308.          ( (LCS_sRGB != dwType)
  1309.            &&
  1310.            (LCS_CALIBRATED_RGB != dwType)
  1311.            &&
  1312.            (PROFILE_LINKED != dwType)
  1313.            &&
  1314.            (PROFILE_EMBEDDED != dwType)
  1315.          )
  1316.        )
  1317.     {
  1318.         return FALSE;
  1319.     }
  1320.     pBitmapInfo = (PBITMAPINFOHEADER) GlobalLock(lpDIBInfo->hDIB);
  1321.     // Open file handle.
  1322.     hFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1323.                        FILE_ATTRIBUTE_NORMAL, NULL);
  1324.     if (INVALID_HANDLE_VALUE != hFile)
  1325.     {
  1326.         DWORD               dwBytes;
  1327.         DWORD               dwProfileSize;
  1328.         PBYTE               pProfileData;
  1329.         LPSTR               lpszProfileName;
  1330.         BITMAPV5HEADER      BitmapHeader;
  1331.         BITMAPFILEHEADER    FileHeader;
  1332.         // Initialize variables.
  1333.         dwProfileSize = PROFILESIZE(pBitmapInfo);
  1334.         pProfileData = GETPROFILEDATA(pBitmapInfo);
  1335.         lpszProfileName = NULL;
  1336.         memset(&BitmapHeader, 0, sizeof(BITMAPV5HEADER));
  1337.         memset(&FileHeader, 0, sizeof(BITMAPFILEHEADER));
  1338.         // Convert to proper type.
  1339.         if (dwType != BITMAPCSTYPE(pBitmapInfo))
  1340.         {
  1341.             if (PROFILE_LINKED == dwType)
  1342.             {
  1343.                 ASSERT(PROFILE_EMBEDDED == BITMAPCSTYPE(pBitmapInfo));
  1344.                 // Going from Embedded profile to linked.
  1345.                 // Save embedded profile data to file.
  1346.                 // Create file name from manufacture and model name of profile header.
  1347.                 lpszProfileName = (LPSTR) GlobalAlloc(GPTR, 1024);
  1348.                 // Get save name and save profile data.
  1349.                 if (GetProfileSaveName(hWnd, &lpszProfileName, 1024))
  1350.                 {
  1351.                     HANDLE  hProfile;
  1352.                     hProfile = CreateFileA(lpszProfileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1353.                                            FILE_ATTRIBUTE_NORMAL, NULL);
  1354.                     if (INVALID_HANDLE_VALUE != hProfile)
  1355.                     {
  1356.                         WriteFile(hProfile, pProfileData, dwProfileSize, &dwBytes, NULL);
  1357.                         CloseHandle(hProfile);
  1358.                     }
  1359.                     // Change profile variables to point to linked name.
  1360.                     pProfileData = (PBYTE) lpszProfileName;
  1361.                     dwProfileSize = strlen(lpszProfileName);
  1362.                 }
  1363.             }
  1364.             else if (PROFILE_EMBEDDED == dwType)
  1365.             {
  1366.                 DWORD       dwSize = 0;
  1367.                 PROFILE     Profile;
  1368.                 HPROFILE    hProfile;
  1369.                 ASSERT(PROFILE_EMBEDDED == BITMAPCSTYPE(pBitmapInfo));
  1370.                 // Going from linked profile to Embedded.
  1371.                 // Embed Linked profile data.
  1372.                 // Open profile.
  1373.                 Profile.dwType = PROFILE_FILENAME;
  1374.                 Profile.pProfileData = pProfileData;
  1375.                 Profile.cbDataSize = dwProfileSize;
  1376.                 hProfile = OpenColorProfile(&Profile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);
  1377.                 // Get profile data form handle.
  1378.                 if (NULL != hProfile)
  1379.                 {
  1380.                     GetColorProfileFromHandle(hProfile, NULL, &dwSize);
  1381.                     lpszProfileName = (LPSTR) GlobalAlloc(GPTR, dwSize);
  1382.                     GetColorProfileFromHandle(hProfile, (PBYTE) lpszProfileName, &dwSize);
  1383.                     CloseColorProfile(hProfile);
  1384.                 }
  1385.                 // Change profile variables to point at data to embed.
  1386.                 pProfileData = (PBYTE) lpszProfileName;
  1387.                 dwProfileSize = dwSize;
  1388.             }
  1389.             else if (LCS_sRGB == dwType)
  1390.             {
  1391.                 DWORD       dwSize;
  1392.                 LPTSTR      pszSRGB;
  1393.                 // Need to translate from current type to sRGB.
  1394.                 // Open sRGB profile.
  1395.                 GetStandardColorSpaceProfile(NULL, LCS_sRGB, NULL, &dwSize);
  1396.                 pszSRGB = (LPTSTR) GlobalAlloc(GPTR, dwSize);
  1397.                 GetStandardColorSpaceProfile(NULL, LCS_sRGB, pszSRGB, &dwSize);
  1398.                 if (NULL != pszSRGB)
  1399.                 {
  1400.                     // Translate DIB.
  1401.                     hDIBTransformed = TransformDIBOutsideDC(lpDIBInfo->hDIB,
  1402.                                                             lpDIBInfo->bmFormat,
  1403.                                                             pszSRGB,
  1404.                                                             NULL,
  1405.                                                             USE_BITMAP_INTENT,
  1406.                                                             NULL,
  1407.                                                             0);
  1408.                     // Clean up.
  1409.                     GlobalFree((HANDLE)pszSRGB);
  1410.                     // Change bitmap info variable to point at tranlated DIB.
  1411.                     pBitmapInfo = (PBITMAPINFOHEADER) GlobalLock(hDIBTransformed);
  1412.                 }
  1413.             }
  1414.         }
  1415.         if (NULL != pBitmapInfo)
  1416.         {
  1417.             // Create file header and write it to the file.
  1418.             FileHeader.bfType = BFT_BITMAP;
  1419.             FileHeader.bfSize = sizeof(BITMAPFILEHEADER);
  1420.             FileHeader.bfSize += sizeof(BITMAPV5HEADER);
  1421.             FileHeader.bfSize += NumColorsInDIB(pBitmapInfo) * sizeof(RGBQUAD);
  1422.             FileHeader.bfSize += BITMAPSIZE(pBitmapInfo);
  1423.             FileHeader.bfSize += dwProfileSize;
  1424.             FileHeader.bfOffBits = sizeof(BITMAPFILEHEADER);
  1425.             FileHeader.bfOffBits += sizeof(BITMAPV5HEADER);
  1426.             FileHeader.bfOffBits += NumColorsInDIB(pBitmapInfo) * sizeof(RGBQUAD);
  1427.             WriteFile(hFile, &FileHeader, sizeof(BITMAPFILEHEADER), &dwBytes, NULL);
  1428.             // Create bitmap header and write it to file.
  1429.             BitmapHeader.bV5Size = sizeof(BITMAPV5HEADER);
  1430.             BitmapHeader.bV5Width = BITMAPWIDTH(pBitmapInfo);
  1431.             BitmapHeader.bV5Height = BITMAPHEIGHT(pBitmapInfo);
  1432.             BitmapHeader.bV5Planes = 1;
  1433.             BitmapHeader.bV5BitCount = (WORD) BITCOUNT(pBitmapInfo);
  1434.             BitmapHeader.bV5Compression = BITMAPCOMPRESSION(pBitmapInfo);
  1435.             BitmapHeader.bV5SizeImage = BITMAPIMAGESIZE(pBitmapInfo);
  1436.             BitmapHeader.bV5ClrUsed = BITMAPCLRUSED(pBitmapInfo);
  1437.             BitmapHeader.bV5ClrImportant = BITMAPCLRIMPORTANT(pBitmapInfo);
  1438.             BitmapHeader.bV5RedMask = BITMAPREDMASK(pBitmapInfo);
  1439.             BitmapHeader.bV5GreenMask = BITMAPGREENMASK(pBitmapInfo);
  1440.             BitmapHeader.bV5BlueMask = BITMAPBLUEMASK(pBitmapInfo);
  1441.             BitmapHeader.bV5CSType = dwType;
  1442.             if (sizeof(BITMAPV4HEADER) <= *(LPDWORD)pBitmapInfo)
  1443.             {
  1444.                 memcpy(&BitmapHeader.bV5Endpoints, &((PBITMAPV4HEADER)pBitmapInfo)->bV4Endpoints,
  1445.                        sizeof(CIEXYZTRIPLE) + sizeof(DWORD) * 3);
  1446.             }
  1447.             BitmapHeader.bV5Intent = BITMAPINTENT(pBitmapInfo);
  1448.             BitmapHeader.bV5ProfileData = sizeof(BITMAPV5HEADER);
  1449.             BitmapHeader.bV5ProfileData += NumColorsInDIB(pBitmapInfo) * sizeof(RGBQUAD);
  1450.             BitmapHeader.bV5ProfileData += BITMAPSIZE(pBitmapInfo);
  1451.             BitmapHeader.bV5ProfileSize = dwProfileSize;
  1452.             WriteFile(hFile, &BitmapHeader, sizeof(BITMAPV5HEADER), &dwBytes, NULL);
  1453.             // Write color table.
  1454.             if (!IS_BITMAPCOREHEADER(pBitmapInfo))
  1455.             {
  1456.                 PBYTE   pColorTable;
  1457.                 DWORD   dwColorTableSize;
  1458.                 dwColorTableSize = NumColorsInDIB(pBitmapInfo) * sizeof(RGBQUAD);
  1459.                 pColorTable = (PBYTE)pBitmapInfo + *(LPDWORD)pBitmapInfo;
  1460.                 if ( IS_BITMAPINFOHEADER(pBitmapInfo)
  1461.                      &&
  1462.                      (BI_BITFIELDS == BITMAPCOMPRESSION(pBitmapInfo))
  1463.                    )
  1464.                 {
  1465.                     dwColorTableSize += sizeof(DWORD) * 3;
  1466.                 }
  1467.                 WriteFile(hFile, pColorTable, dwColorTableSize, &dwBytes, NULL);
  1468.             }
  1469.             else
  1470.             {
  1471.                 PBYTE   pColorTable;
  1472.                 DWORD   dwCount;
  1473.                 RGBQUAD ColorTable[256];
  1474.                 pColorTable = (PBYTE)pBitmapInfo + *(LPDWORD)pBitmapInfo;
  1475.                 memset(ColorTable, 0, sizeof(ColorTable));
  1476.                 for (dwCount = 0; dwCount < NumColorsInDIB(pBitmapInfo); dwCount++)
  1477.                     memcpy(ColorTable + dwCount, pColorTable + dwCount, sizeof(RGBTRIPLE));
  1478.                 WriteFile(hFile, ColorTable, NumColorsInDIB(pBitmapInfo) * sizeof(RGBQUAD), &dwBytes, NULL);
  1479.             }
  1480.             // Save bitmap data.
  1481.             WriteFile(hFile, FindDIBBits(pBitmapInfo), BITMAPSIZE(pBitmapInfo), &dwBytes, NULL);
  1482.             // Save profile data.
  1483.             if (0 != dwProfileSize)
  1484.             {
  1485.                 WriteFile(hFile, pProfileData, dwProfileSize, &dwBytes, NULL);
  1486.             }
  1487.             bResult = TRUE;
  1488.         }
  1489.         // Clean up.
  1490.         CloseHandle(hFile);
  1491.         if (NULL != lpszProfileName)
  1492.             GlobalFree((HANDLE)lpszProfileName);
  1493.         if (NULL != hDIBTransformed)
  1494.         {
  1495.             GlobalUnlock(hDIBTransformed);
  1496.             GlobalFree(hDIBTransformed);
  1497.         }
  1498.         // If failed, delete file.
  1499.         if (!bResult)
  1500.             DeleteFile(lpszFileName);
  1501.     }
  1502.     //Clean up.
  1503.     GlobalUnlock(lpDIBInfo->hDIB);
  1504.     return bResult;
  1505. }