dibapi.cpp
上传用户:gzboli
上传日期:2013-04-10
资源大小:471k
文件大小:239k
源码类别:

图片显示

开发平台:

Visual C++

  1. //********************************************************************** 
  2. // 
  3. //  AIBAPI.CPP
  4. // 
  5. //  Source file for Device-Independent Bitmap (DIB) API. 
  6. // 
  7. //********************************************************************** 
  8.  
  9. #define     STRICT      // enable strict type checking 
  10.  
  11. #include "stdafx.h"
  12. #include <string.h> 
  13. #include <stdio.h> 
  14. #include <math.h> 
  15. #include <io.h> 
  16. #include <direct.h> 
  17. #include <stdlib.h> 
  18. #include <assert.h> 
  19. #include <windows.h> 
  20. #include <windowsx.h> 
  21. #include <mmsystem.h> 
  22. #include "dibapi.h" 
  23. #include "CqOctree.h"
  24. #include <sys/timeb.h>
  25. //#include <time.h>
  26. ////////////////////////////////////////////////////////////////////////////////////
  27. // Local use only function prototypes
  28. ////////////////////////////////////////////////////////////////////////////////////
  29. BOOL CopyColorTable(LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc);
  30. void DecreaseContrast(BYTE *pByte, const int Level, const float Grad);
  31. void IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad);
  32. double Value(double n1, double n2, double hue);
  33. HGLOBAL DitherImage(LPSTR lpImageData, WORD Width, WORD Height);
  34. void DitherLine(WORD Width, LPSTR pLine1, LPSTR pLine2);
  35. ////////////////////////////////////////////////////////////////////////////////////
  36.  
  37. /************************************************************************* 
  38.  * 
  39.  * CreateDIB() 
  40.  * 
  41.  * Parameters: 
  42.  * 
  43.  * DWORD dwWidth    - Width for new bitmap, in pixels 
  44.  * DWORD dwHeight   - Height for new bitmap  
  45.  * WORD  wBitCount  - Bit Count for new DIB (1, 4, 8, or 24) 
  46.  * 
  47.  * Return Value: 
  48.  * 
  49.  * HDIB             - Handle to new DIB 
  50.  * 
  51.  * Description: 
  52.  * 
  53.  * This function allocates memory for and initializes a new DIB by 
  54.  * filling in the BITMAPINFOHEADER, allocating memory for the color 
  55.  * table, and allocating memory for the bitmap bits.  As with all 
  56.  * HDIBs, the header, colortable and bits are all in one contiguous 
  57.  * memory block.  This function is similar to the CreateBitmap()  
  58.  * Windows API. 
  59.  * 
  60.  * The colortable and bitmap bits are left uninitialized (zeroed) in the 
  61.  * returned HDIB. 
  62.  * 
  63.  * 
  64.  ************************************************************************/ 
  65. HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount) 
  66.     BITMAPINFOHEADER    bi;             // bitmap header 
  67.     LPBITMAPINFOHEADER  lpbi;           // pointer to BITMAPINFOHEADER 
  68.     DWORD               dwLen;          // size of memory block 
  69.     HDIB                hDIB; 
  70.     DWORD               dwBytesPerLine; // Number of bytes per scanline 
  71.  
  72.  
  73.     // Make sure bits per pixel is valid 
  74.  
  75.     if (wBitCount <= 1) 
  76.         wBitCount = 1; 
  77.     else if (wBitCount <= 4) 
  78.         wBitCount = 4; 
  79.     else if (wBitCount <= 8) 
  80.         wBitCount = 8; 
  81.     else if (wBitCount <= 24) 
  82.         wBitCount = 24; 
  83.     else 
  84.         wBitCount = 4;  // set default value to 4 if parameter is bogus 
  85.  
  86.     // initialize BITMAPINFOHEADER 
  87.  
  88.     bi.biSize = sizeof(BITMAPINFOHEADER); 
  89.     bi.biWidth = dwWidth;         // fill in width from parameter 
  90.     bi.biHeight = dwHeight;       // fill in height from parameter 
  91.     bi.biPlanes = 1;              // must be 1 
  92.     bi.biBitCount = wBitCount;    // from parameter 
  93.     bi.biCompression = BI_RGB;     
  94.     bi.biSizeImage = 0;           // 0's here mean "default" 
  95.     bi.biXPelsPerMeter = 0; 
  96.     bi.biYPelsPerMeter = 0; 
  97.     bi.biClrUsed = 0; 
  98.     bi.biClrImportant = 0; 
  99.  
  100.     // calculate size of memory block required to store the DIB.  This 
  101.     // block should be big enough to hold the BITMAPINFOHEADER, the color 
  102.     // table, and the bits 
  103.  
  104.     dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth); 
  105.     dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight); 
  106.  
  107.     // alloc memory block to store our bitmap 
  108.  
  109.     hDIB = GlobalAlloc(GHND, dwLen); 
  110.  
  111.     // major bummer if we couldn't get memory block 
  112.  
  113.     if (!hDIB) 
  114.         return NULL; 
  115.  
  116.     // lock memory and get pointer to it 
  117.  
  118.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
  119.  
  120.     // use our bitmap info structure to fill in first part of 
  121.     // our DIB with the BITMAPINFOHEADER 
  122.  
  123.     *lpbi = bi; 
  124.  
  125.     // Since we don't know what the colortable and bits should contain, 
  126.     // just leave these blank.  Unlock the DIB and return the HDIB. 
  127.  
  128.     GlobalUnlock(hDIB); 
  129.  
  130.     //return handle to the DIB 
  131.  
  132.     return hDIB; 
  133.  
  134. /************************************************************************* 
  135.  * 
  136.  * CreateDefaultDIB() 
  137.  * 
  138.  * Parameters: 
  139.  * 
  140.  * DWORD dwWidth    - Width for new bitmap, in pixels 
  141.  * DWORD dwHeight   - Height for new bitmap  
  142.   * 
  143.  * Return Value: 
  144.  * 
  145.  * HDIB             - Handle to new DIB 
  146.  * 
  147.  * Description: 
  148.  * 
  149.  * This function allocates memory for and initializes a new DIB by 
  150.  * filling in the BITMAPINFOHEADER, allocating memory for the color 
  151.  * table, and allocating memory for the bitmap bits.  As with all 
  152.  * HDIBs, the header, colortable and bits are all in one contiguous 
  153.  * memory block.  This function is similar to the CreateBitmap()  
  154.  * Windows API. 
  155.  * 
  156.  * The colortable is initialized with system palette, but bitmap bits
  157.  * are left uninitialized (zeroed) in the returned HDIB. 
  158.  * 
  159.  * 
  160.  ************************************************************************/ 
  161. HDIB CreateDefaultDIB(DWORD dwWidth, DWORD dwHeight) 
  162. // Get DC
  163.     HDC hDC = GetDC(NULL); 
  164.     if (!hDC) 
  165.         return NULL; 
  166. // DC bts/pixel
  167. int nDeviceBitsPixel = GetDeviceCaps(hDC, BITSPIXEL);
  168. // create DIB according to DC
  169. HDIB hDIB = CreateDIB(dwWidth, dwHeight, nDeviceBitsPixel);
  170. // DIB buffer
  171. LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hDIB);
  172.     LPSTR lpDIBBits = FindDIBBits((LPSTR)lpbmi); 
  173.     DWORD dwBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  174. // set DIB color to White
  175. for (DWORD l=0; l<dwBitsSize; ++l)
  176. lpDIBBits[l] = (char)0xff;
  177. // if no palette, return DIB handle
  178. if (nDeviceBitsPixel > 8)
  179. {
  180. GlobalUnlock(hDIB);
  181.     ReleaseDC(NULL, hDC); 
  182. return hDIB;
  183. }
  184. // if there is palette, set system palette to DIB
  185. // colors in system palette
  186.     int nColors = PalEntriesOnDevice(hDC);   // Number of palette entries 
  187.   
  188.     // Copy the current system palette into our logical palette 
  189. PALETTEENTRY pe[256];
  190.     GetSystemPaletteEntries(hDC, 0, nColors, pe); 
  191. // set color table
  192. for (int i=0; i<nColors; ++i)
  193. {
  194. lpbmi->bmiColors[i].rgbRed = pe[i].peRed;
  195. lpbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
  196. lpbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
  197. lpbmi->bmiColors[i].rgbReserved = 0;
  198. }
  199.     // clean up 
  200. GlobalUnlock(hDIB);
  201.     ReleaseDC(NULL, hDC); 
  202. return hDIB;
  203. }
  204. /************************************************************************* 
  205.  * 
  206.  * DestroyDIB () 
  207.  * 
  208.  * Purpose:  Frees memory associated with a DIB 
  209.  * 
  210.  * Returns:  none 
  211.  * 
  212.  *************************************************************************/ 
  213. void DestroyDIB(HDIB hDib) 
  214.     GlobalFree(hDib); 
  215.  
  216. /************************************************************************* 
  217.  * 
  218.  * LoadDIB() 
  219.  * 
  220.  * Loads the specified DIB from a file, allocates memory for it, 
  221.  * and reads the disk file into the memory. 
  222.  * 
  223.  * 
  224.  * Parameters: 
  225.  * 
  226.  * LPCTSTR lpFileName - specifies the file to load a DIB from 
  227.  * 
  228.  * Returns: A handle to a DIB, or NULL if unsuccessful. 
  229.  * 
  230.  * NOTE: The DIB API were not written to handle OS/2 DIBs; This 
  231.  * function will reject any file that is not a Windows DIB. 
  232.  * 
  233.  *************************************************************************/ 
  234. HDIB LoadDIB(LPCTSTR lpFileName) 
  235.     HDIB        hDIB; 
  236.     HANDLE      hFile; 
  237.  
  238.     // Set the cursor to a hourglass, in case the loading operation 
  239.     // takes more than a sec, the user will know what's going on. 
  240.  
  241.     SetCursor(LoadCursor(NULL, IDC_WAIT)); 
  242.  
  243.     if ((hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
  244.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
  245.             NULL)) != INVALID_HANDLE_VALUE) 
  246.     { 
  247.         hDIB = ReadDIBFile(hFile); 
  248.         CloseHandle(hFile); 
  249.         SetCursor(LoadCursor(NULL, IDC_ARROW)); 
  250.         return hDIB; 
  251.     } 
  252.     else 
  253.     { 
  254.         SetCursor(LoadCursor(NULL, IDC_ARROW)); 
  255.         return NULL; 
  256.     } 
  257.  
  258.  
  259. /************************************************************************* 
  260.  * 
  261.  * SaveDIB() 
  262.  * 
  263.  * Saves the specified DIB into the specified file name on disk.  No 
  264.  * error checking is done, so if the file already exists, it will be 
  265.  * written over. 
  266.  * 
  267.  * Parameters: 
  268.  * 
  269.  * HDIB hDib - Handle to the dib to save 
  270.  * 
  271.  * LPCTSTR lpFileName - pointer to full pathname to save DIB under 
  272.  * 
  273.  * Return value: TRUE if successful
  274.  *  FALSE if failure
  275.  * 
  276.  *************************************************************************/ 
  277. BOOL SaveDIB(HDIB hDib, LPCTSTR lpFileName) 
  278.     HANDLE              fh;         // file handle for opened file 
  279.  
  280.     if (!hDib) 
  281.         return FALSE; 
  282.  
  283.     fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
  284.             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
  285.  
  286.     if (fh == INVALID_HANDLE_VALUE) 
  287.         return FALSE; 
  288. BOOL bSuccess = WriteDIBFile(hDib, fh);
  289.     CloseHandle(fh);
  290. return bSuccess;
  291. }
  292. /************************************************************************* 
  293.  * 
  294.  * Function:  ReadDIBFile (int) 
  295.  * 
  296.  *  Purpose:  Reads in the specified DIB file into a global chunk of 
  297.  *            memory. 
  298.  * 
  299.  *  Returns:  A handle to a dib (hDIB) if successful. 
  300.  *            NULL if an error occurs. 
  301.  * 
  302.  * Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything 
  303.  *            from the end of the BITMAPFILEHEADER structure on is 
  304.  *            returned in the global memory handle. 
  305.  * 
  306.  * 
  307.  * NOTE: The DIB API were not written to handle OS/2 DIBs, so this 
  308.  * function will reject any file that is not a Windows DIB. 
  309.  * 
  310.  *************************************************************************/ 
  311. HANDLE ReadDIBFile(HANDLE hFile) 
  312.     BITMAPFILEHEADER    bmfHeader; 
  313.     DWORD               dwBitsSize; 
  314.     UINT                nNumColors;   // Number of colors in table 
  315.     HANDLE              hDIB;         
  316.     HANDLE              hDIBtmp;      // Used for GlobalRealloc() //MPB 
  317.     LPBITMAPINFOHEADER  lpbi; 
  318.     DWORD               offBits; 
  319.     DWORD               dwRead; 
  320.  
  321.     // get length of DIB in bytes for use when reading 
  322.  
  323.     dwBitsSize = GetFileSize(hFile, NULL); 
  324.  
  325.     // Allocate memory for header & color table. We'll enlarge this 
  326.     // memory as needed. 
  327.  
  328.     hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 
  329.             256 * sizeof(RGBQUAD))); 
  330.  
  331.     if (!hDIB) 
  332.         return NULL; 
  333.  
  334.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
  335.  
  336.     if (!lpbi)  
  337.     { 
  338.         GlobalFree(hDIB); 
  339.         return NULL; 
  340.     } 
  341.  
  342.     // read the BITMAPFILEHEADER from our file 
  343.  
  344.     if (!ReadFile(hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER), 
  345.             &dwRead, NULL)) 
  346.         goto ErrExit; 
  347.  
  348.     if (sizeof (BITMAPFILEHEADER) != dwRead) 
  349.         goto ErrExit; 
  350.  
  351.     if (bmfHeader.bfType != 0x4d42)  // 'BM' 
  352.         goto ErrExit; 
  353.  
  354.     // read the BITMAPINFOHEADER 
  355.  
  356.     if (!ReadFile(hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER), &dwRead, 
  357.             NULL)) 
  358.         goto ErrExit; 
  359.  
  360.     if (sizeof(BITMAPINFOHEADER) != dwRead) 
  361.         goto ErrExit; 
  362.  
  363.     // Check to see that it's a Windows DIB -- an OS/2 DIB would cause 
  364.     // strange problems with the rest of the DIB API since the fields 
  365.     // in the header are different and the color table entries are 
  366.     // smaller. 
  367.     // 
  368.     // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL. 
  369.  
  370.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) 
  371.         goto ErrExit; 
  372.  
  373.     // Now determine the size of the color table and read it.  Since the 
  374.     // bitmap bits are offset in the file by bfOffBits, we need to do some 
  375.     // special processing here to make sure the bits directly follow 
  376.     // the color table (because that's the format we are susposed to pass 
  377.     // back) 
  378.  
  379.     if (!(nNumColors = (UINT)lpbi->biClrUsed)) 
  380.     { 
  381.         // no color table for 24-bit, default size otherwise 
  382.  
  383.         if (lpbi->biBitCount > 8) //(lpbi->biBitCount != 24) 
  384.             nNumColors = 1 << lpbi->biBitCount; // standard size table 
  385.     } 
  386.  
  387.     // fill in some default values if they are zero 
  388.  
  389.     if (lpbi->biClrUsed == 0) 
  390.         lpbi->biClrUsed = nNumColors; 
  391.  
  392.     if (lpbi->biSizeImage == 0) 
  393.     { 
  394.         lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 
  395.                 31) & ~31) >> 3) * lpbi->biHeight; 
  396.     } 
  397.  
  398.     // get a proper-sized buffer for header, color table and bits 
  399.  
  400.     GlobalUnlock(hDIB); 
  401.     hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * 
  402.             sizeof(RGBQUAD) + lpbi->biSizeImage, 0); 
  403.  
  404.     if (!hDIBtmp) // can't resize buffer for loading 
  405.         goto ErrExitNoUnlock; //MPB 
  406.     else 
  407.         hDIB = hDIBtmp; 
  408.  
  409.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
  410.  
  411.     // read the color table 
  412.  
  413.     ReadFile (hFile, (LPSTR)(lpbi) + lpbi->biSize, 
  414.             nNumColors * sizeof(RGBQUAD), &dwRead, NULL); 
  415.  
  416.     // offset to the bits from start of DIB header 
  417.  
  418.     offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD); 
  419.  
  420.     // If the bfOffBits field is non-zero, then the bits might *not* be 
  421.     // directly following the color table in the file.  Use the value in 
  422.     // bfOffBits to seek the bits. 
  423.  
  424.     if (bmfHeader.bfOffBits != 0L) 
  425.         SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN); 
  426.  
  427.     if (ReadFile(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage, &dwRead, 
  428.             NULL)) 
  429.         goto OKExit; 
  430.  
  431. ErrExit: 
  432.     GlobalUnlock(hDIB);     
  433.  
  434. ErrExitNoUnlock:     
  435.     GlobalFree(hDIB); 
  436.     return NULL; 
  437.  
  438. OKExit: 
  439.     GlobalUnlock(hDIB); 
  440.     return hDIB; 
  441. /************************************************************************* 
  442.  * 
  443.  * Function:  WriteDIBFile (HANDLE, int) 
  444.  * 
  445.  *  Purpose:  Writes a global chunk of DIB memory to specified file 
  446.  * 
  447.  *  Returns:  TRUE if success, else FALSE
  448.  * 
  449.  * Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything 
  450.  *            from the end of the BITMAPFILEHEADER structure on is 
  451.  *            returned in the global memory handle. 
  452.  * 
  453.  * 
  454.  * NOTE: The DIB API were not written to handle OS/2 DIBs, so this 
  455.  * function will reject any file that is not a Windows DIB. 
  456.  * 
  457.  *************************************************************************/ 
  458. BOOL WriteDIBFile(HDIB hDib, HANDLE fh) 
  459.     BITMAPFILEHEADER    bmfHdr;     // Header for Bitmap file 
  460.     LPBITMAPINFOHEADER  lpBI;       // Pointer to DIB info structure 
  461.     DWORD               dwDIBSize; 
  462.     DWORD               dwWritten; 
  463.     if (!hDib) 
  464.         return FALSE; 
  465.     // Get a pointer to the DIB memory, the first of which contains 
  466.     // a BITMAPINFO structure 
  467.  
  468.     lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
  469.     if (!lpBI) 
  470.     { 
  471.         CloseHandle(fh); 
  472.         return FALSE; 
  473.     } 
  474.  
  475.     // Check to see if we're dealing with an OS/2 DIB.  If so, don't 
  476.     // save it because our functions aren't written to deal with these 
  477.     // DIBs. 
  478.  
  479.     if (lpBI->biSize != sizeof(BITMAPINFOHEADER)) 
  480.     { 
  481.         GlobalUnlock(hDib); 
  482.         CloseHandle(fh); 
  483.         return FALSE; 
  484.     } 
  485.  
  486.     // Fill in the fields of the file header 
  487.  
  488.     // Fill in file type (first 2 bytes must be "BM" for a bitmap) 
  489.  
  490.     bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
  491.  
  492.     // Calculating the size of the DIB is a bit tricky (if we want to 
  493.     // do it right).  The easiest way to do this is to call GlobalSize() 
  494.     // on our global handle, but since the size of our global memory may have 
  495.     // been padded a few bytes, we may end up writing out a few too 
  496.     // many bytes to the file (which may cause problems with some apps, 
  497.     // like HC 3.0). 
  498.     // 
  499.     // So, instead let's calculate the size manually. 
  500.     // 
  501.     // To do this, find size of header plus size of color table.  Since the 
  502.     // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains 
  503.     // the size of the structure, let's use this. 
  504.  
  505.     // Partial Calculation 
  506.  
  507.     dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);   
  508.  
  509.     // Now calculate the size of the image 
  510.  
  511.     // It's an RLE bitmap, we can't calculate size, so trust the biSizeImage 
  512.     // field 
  513.  
  514.     if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
  515.         dwDIBSize += lpBI->biSizeImage; 
  516.     else 
  517.     { 
  518.         DWORD dwBmBitsSize;  // Size of Bitmap Bits only 
  519.  
  520.         // It's not RLE, so size is Width (DWORD aligned) * Height 
  521.  
  522.         dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * 
  523.                 lpBI->biHeight; 
  524.  
  525.         dwDIBSize += dwBmBitsSize; 
  526.  
  527.         // Now, since we have calculated the correct size, why don't we 
  528.         // fill in the biSizeImage field (this will fix any .BMP files which  
  529.         // have this field incorrect). 
  530.  
  531.         lpBI->biSizeImage = dwBmBitsSize; 
  532.     } 
  533.  
  534.  
  535.     // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
  536.                     
  537.     bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
  538.     bmfHdr.bfReserved1 = 0; 
  539.     bmfHdr.bfReserved2 = 0; 
  540.  
  541.     // Now, calculate the offset the actual bitmap bits will be in 
  542.     // the file -- It's the Bitmap file header plus the DIB header, 
  543.     // plus the size of the color table. 
  544.      
  545.     bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + 
  546.             PaletteSize((LPSTR)lpBI); 
  547.  
  548.     // Write the file header 
  549.  
  550.     WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
  551.  
  552.     // Write the DIB header and the bits -- use local version of 
  553.     // MyWrite, so we can write more than 32767 bytes of data 
  554.      
  555.     WriteFile(fh, (LPSTR)lpBI, dwDIBSize, &dwWritten, NULL); 
  556.  
  557.     GlobalUnlock(hDib); 
  558.  
  559.     if (dwWritten == 0) 
  560.         return FALSE; // oops, something happened in the write 
  561.     else 
  562.         return TRUE; // Success code 
  563.  
  564. /************************************************************************* 
  565.  * 
  566.  * FindDIBBits() 
  567.  * 
  568.  * Parameter: 
  569.  * 
  570.  * LPSTR lpDIB      - pointer to packed-DIB memory block 
  571.  * 
  572.  * Return Value: 
  573.  * 
  574.  * LPSTR            - pointer to the DIB bits 
  575.  * 
  576.  * Description: 
  577.  * 
  578.  * This function calculates the address of the DIB's bits and returns a 
  579.  * pointer to the DIB bits. 
  580.  * 
  581.  ***********************************************************************
  582. LPSTR FindDIBBits(LPSTR lpDIB) 
  583.    return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
  584. */ 
  585. /************************************************************************* 
  586.  * 
  587.  * DIBWidth() 
  588.  * 
  589.  * Parameter: 
  590.  * 
  591.  * LPSTR lpDIB      - pointer to packed-DIB memory block 
  592.  * 
  593.  * Return Value: 
  594.  * 
  595.  * DWORD            - width of the DIB 
  596.  * 
  597.  * Description: 
  598.  * 
  599.  * This function gets the width of the DIB from the BITMAPINFOHEADER 
  600.  * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 
  601.  * width field if it is an OS/2-style DIB. 
  602.  * 
  603.  *********************************************************************** 
  604. DWORD DIBWidth(LPSTR lpDIB) 
  605.     LPBITMAPINFOHEADER   lpbmi;  // pointer to a Win 3.0-style DIB 
  606.     LPBITMAPCOREHEADER   lpbmc;  // pointer to an OS/2-style DIB 
  607.  
  608.     // point to the header (whether Win 3.0 and OS/2) 
  609.  
  610.     lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
  611.     lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
  612.  
  613.     // return the DIB width if it is a Win 3.0 DIB 
  614.  
  615.     if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) 
  616.         return lpbmi->biWidth; 
  617.     else  // it is an OS/2 DIB, so return its width 
  618.         return (DWORD)lpbmc->bcWidth; 
  619. */ 
  620. long DIBWidth(HDIB hDIB) 
  621. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  622. long dw = DIBWidth(lpDIB);
  623. GlobalUnlock(hDIB);
  624. return dw;
  625.  
  626. /************************************************************************* 
  627.  * 
  628.  * DIBHeight() 
  629.  * 
  630.  * Parameter: 
  631.  * 
  632.  * LPSTR lpDIB      - pointer to packed-DIB memory block 
  633.  * 
  634.  * Return Value: 
  635.  * 
  636.  * DWORD            - height of the DIB 
  637.  * 
  638.  * Description: 
  639.  * 
  640.  * This function gets the height of the DIB from the BITMAPINFOHEADER 
  641.  * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 
  642.  * height field if it is an OS/2-style DIB. 
  643.  * 
  644.  *********************************************************************** 
  645. DWORD DIBHeight(LPSTR lpDIB) 
  646.    LPBITMAPINFOHEADER   lpbmi;  // pointer to a Win 3.0-style DIB 
  647.    LPBITMAPCOREHEADER   lpbmc;  // pointer to an OS/2-style DIB 
  648.  
  649.    // point to the header (whether OS/2 or Win 3.0 
  650.  
  651.    lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
  652.    lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
  653.  
  654.     // return the DIB height if it is a Win 3.0 DIB 
  655.     if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) 
  656.         return lpbmi->biHeight; 
  657.     else  // it is an OS/2 DIB, so return its height 
  658.         return (DWORD)lpbmc->bcHeight; 
  659. */ 
  660. long DIBHeight(HDIB hDIB) 
  661. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  662. long dw = DIBHeight(lpDIB);
  663. GlobalUnlock(hDIB);
  664. return dw;
  665.  
  666. /************************************************************************* 
  667.  * 
  668.  * PaletteSize() 
  669.  * 
  670.  * Parameter: 
  671.  * 
  672.  * LPSTR lpDIB      - pointer to packed-DIB memory block 
  673.  * 
  674.  * Return Value: 
  675.  * 
  676.  * WORD             - size of the color palette of the DIB 
  677.  * 
  678.  * Description: 
  679.  * 
  680.  * This function gets the size required to store the DIB's palette by 
  681.  * multiplying the number of colors by the size of an RGBQUAD (for a 
  682.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2- 
  683.  * style DIB). 
  684.  * 
  685.  *********************************************************************** 
  686. WORD PaletteSize(LPSTR lpDIB) 
  687.     // calculate the size required by the palette 
  688.     if (IS_WIN30_DIB (lpDIB)) 
  689.         return (DIBNumColors(lpDIB) * sizeof(RGBQUAD)); 
  690.     else 
  691.         return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE)); 
  692. */ 
  693. WORD PaletteSize(HDIB hDIB) 
  694. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  695. WORD wSize = PaletteSize(lpDIB);
  696. GlobalUnlock(hDIB);
  697. return wSize;
  698.  
  699. /************************************************************************* 
  700.  * 
  701.  * DIBNumColors() 
  702.  * 
  703.  * Parameter: 
  704.  * 
  705.  * LPSTR lpDIB      - pointer to packed-DIB memory block 
  706.  * 
  707.  * Return Value: 
  708.  * 
  709.  * WORD             - number of colors in the color table 
  710.  * 
  711.  * Description: 
  712.  * 
  713.  * This function calculates the number of colors in the DIB's color table 
  714.  * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style 
  715.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, 
  716.  * if 24, no colors in color table. 
  717.  * 
  718.  *********************************************************************** 
  719. WORD DIBNumColors(LPSTR lpDIB) 
  720.     WORD wBitCount;  // DIB bit count 
  721.  
  722.     // If this is a Windows-style DIB, the number of colors in the 
  723.     // color table can be less than the number of bits per pixel 
  724.     // allows for (i.e. lpbi->biClrUsed can be set to some value). 
  725.     // If this is the case, return the appropriate value. 
  726.      
  727.  
  728.     if (IS_WIN30_DIB(lpDIB)) 
  729.     { 
  730.         DWORD dwClrUsed; 
  731.  
  732.         dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; 
  733.         if (dwClrUsed) 
  734.  
  735.         return (WORD)dwClrUsed; 
  736.     } 
  737.  
  738.     // Calculate the number of colors in the color table based on 
  739.     // the number of bits per pixel for the DIB. 
  740.      
  741.     if (IS_WIN30_DIB(lpDIB)) 
  742.         wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; 
  743.     else 
  744.         wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; 
  745.  
  746.     // return number of colors based on bits per pixel 
  747.  
  748.     switch (wBitCount) 
  749.     { 
  750.         case 1: 
  751.             return 2; 
  752.  
  753.         case 4: 
  754.             return 16; 
  755.  
  756.         case 8: 
  757.             return 256; 
  758.  
  759.         default: 
  760.             return 0; 
  761.     } 
  762. */
  763. WORD DIBNumColors(HDIB hDIB) 
  764. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  765. WORD wSize = DIBNumColors(lpDIB);
  766. GlobalUnlock(hDIB);
  767. return wSize;
  768. WORD DIBBitCount(LPSTR lpDIB) 
  769.     if (IS_WIN30_DIB(lpDIB)) 
  770.         return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; 
  771.     else 
  772.         return ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; 
  773. WORD DIBBitCount(HDIB hDIB) 
  774. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  775. WORD wSize = DIBBitCount(lpDIB);
  776. GlobalUnlock(hDIB);
  777. return wSize;
  778.  
  779. /**************************************************************************** 
  780. *     FUNCTION: BytesPerLine 
  781. *     PURPOSE:  Calculates the number of bytes in one scan line. 
  782. *     PARAMS:   LPSTR lpDIB - pointer to the BITMAPINFOHEADER 
  783.                               that begins the CF_DIB block 
  784. *     RETURNS:  DWORD - number of bytes in one scan line (DWORD aligned) 
  785. ****************************************************************************/ 
  786. DWORD BytesPerLine(LPSTR lpDIB) 
  787.     return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount); 
  788. DWORD BytesPerLine(HDIB hDIB) 
  789. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  790. DWORD dw = BytesPerLine(lpDIB);
  791. GlobalUnlock(hDIB);
  792. return dw;
  793. /**************************************************************************** 
  794. *     FUNCTION: DIBlockSize 
  795. *     PURPOSE:  Calculates the number of bytes in one scan line. 
  796. *     PARAMS:   LPSTR lpDIB - pointer to the BITMAPINFOHEADER 
  797.                               that begins the CF_DIB block 
  798. *     RETURNS:  DWORD - DIB block size
  799. ****************************************************************************/ 
  800. DWORD DIBlockSize(LPSTR lpDIB)
  801. {
  802. if (((LPBITMAPINFOHEADER)lpDIB)->biSizeImage == 0)
  803. ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage = BytesPerLine(lpDIB) * ((LPBITMAPINFOHEADER)lpDIB)->biHeight;
  804. return ((LPBITMAPINFOHEADER)lpDIB)->biSize + PaletteSize(lpDIB) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage;
  805. }
  806. DWORD DIBlockSize(HDIB hDIB) 
  807. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  808. DWORD dw = DIBlockSize(lpDIB);
  809. GlobalUnlock(hDIB);
  810. return dw;
  811.  
  812. /************************************************************************* 
  813.  * 
  814.  * CreateDIBPalette() 
  815.  * 
  816.  * Parameter: 
  817.  * 
  818.  * LPSTR lpbi       - specifies the DIB 
  819.  * 
  820.  * Return Value: 
  821.  * 
  822.  * HPALETTE         - specifies the palette 
  823.  * 
  824.  * Description: 
  825.  * 
  826.  * This function creates a palette from a DIB by allocating memory for the 
  827.  * logical palette, reading and storing the colors from the DIB's color table 
  828.  * into the logical palette, creating a palette from this logical palette, 
  829.  * and then returning the palette's handle. This allows the DIB to be 
  830.  * displayed using the best possible colors (important for DIBs with 256 or 
  831.  * more colors). 
  832.  * 
  833.  ************************************************************************/ 
  834. HPALETTE CreateDIBPalette(LPSTR lpbi) 
  835.     LPLOGPALETTE        lpPal;          // pointer to a logical palette 
  836.     HANDLE              hLogPal;        // handle to a logical palette 
  837.     HPALETTE            hPal = NULL;    // handle to a palette 
  838.     int                 i, wNumColors;  // loop index, number of colors in color table 
  839.     LPBITMAPINFO        lpbmi;          // pointer to BITMAPINFO structure (Win3.0) 
  840.     LPBITMAPCOREINFO    lpbmc;          // pointer to BITMAPCOREINFO structure (OS/2) 
  841.     BOOL                bWinStyleDIB;   // Win3.0 DIB? 
  842.  
  843.     // if handle to DIB is invalid, return NULL 
  844.  
  845.     if (! lpbi) 
  846.         return NULL; 
  847.  
  848.     // get pointer to BITMAPINFO (Win 3.0) 
  849.  
  850.     lpbmi = (LPBITMAPINFO)lpbi; 
  851.  
  852.     // get pointer to BITMAPCOREINFO (OS/2 1.x) 
  853.  
  854.     lpbmc = (LPBITMAPCOREINFO)lpbi; 
  855.  
  856.     // get the number of colors in the DIB  
  857.  
  858.     wNumColors = DIBNumColors(lpbi); 
  859.  
  860.     // is this a Win 3.0 DIB? 
  861.  
  862.     bWinStyleDIB = IS_WIN30_DIB(lpbi); 
  863.     if (wNumColors) 
  864.     { 
  865.         // allocate memory block for logical palette 
  866.  
  867.         hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + 
  868.                 sizeof(PALETTEENTRY) * wNumColors); 
  869.  
  870.         // if not enough memory, clean up and return NULL 
  871.  
  872.         if (!hLogPal) 
  873.             return NULL; 
  874.  
  875.         // lock memory block and get pointer to it 
  876.  
  877.         lpPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
  878.  
  879.         // set version and number of palette entries 
  880.  
  881.         lpPal->palVersion = PALVERSION; 
  882.         lpPal->palNumEntries = wNumColors; 
  883.  
  884.         // store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB) 
  885.         // into palette 
  886.          
  887.         for (i = 0; i < wNumColors; i++) 
  888.         { 
  889.             if (bWinStyleDIB) 
  890.             { 
  891.                 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 
  892.                 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 
  893.                 lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; 
  894.                 lpPal->palPalEntry[i].peFlags = 0; 
  895.             } 
  896.             else 
  897.             { 
  898.                 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 
  899.                 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 
  900.                 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; 
  901.                 lpPal->palPalEntry[i].peFlags = 0; 
  902.             } 
  903.         } 
  904.  
  905.         // create the palette and get handle to it 
  906.  
  907.         hPal = CreatePalette(lpPal); 
  908.  
  909.         // cleanup
  910.  
  911.         GlobalUnlock(hLogPal); 
  912.         GlobalFree(hLogPal); 
  913.     } 
  914.  
  915.     // return handle to DIB's palette 
  916.     return hPal; 
  917.  
  918. /************************************************************************* 
  919.  * 
  920.  * CreateDIBPalette() 
  921.  * 
  922.  * Parameter: 
  923.  * 
  924.  * HDIB hDIB        - specifies the DIB 
  925.  * 
  926.  * Return Value: 
  927.  * 
  928.  * HPALETTE         - specifies the palette 
  929.  * 
  930.  * Description: 
  931.  * 
  932.  * This function creates a palette from a DIB by allocating memory for the 
  933.  * logical palette, reading and storing the colors from the DIB's color table 
  934.  * into the logical palette, creating a palette from this logical palette, 
  935.  * and then returning the palette's handle. This allows the DIB to be 
  936.  * displayed using the best possible colors (important for DIBs with 256 or 
  937.  * more colors). 
  938.  * 
  939.  ************************************************************************/ 
  940. HPALETTE CreateDIBPalette(HDIB hDIB) 
  941.     HPALETTE            hPal = NULL;    // handle to a palette 
  942.     LPSTR               lpbi;           // pointer to packed-DIB 
  943.  
  944.     // if handle to DIB is invalid, return NULL 
  945.  
  946.     if (!hDIB) 
  947.         return NULL; 
  948.  
  949.     // lock DIB memory block and get a pointer to it 
  950.  
  951.     lpbi = (LPSTR)GlobalLock(hDIB); 
  952.  
  953. hPal = CreateDIBPalette(lpbi);
  954. // Unlock hDIB
  955.     GlobalUnlock(hDIB); 
  956.  
  957.     // return handle to DIB's palette 
  958.     return hPal; 
  959.  
  960. /************************************************************************* 
  961.  * 
  962.  * DIBToBitmap() 
  963.  * 
  964.  * Parameters: 
  965.  * 
  966.  * HDIB hDIB        - specifies the DIB to convert 
  967.  * 
  968.  * HPALETTE hPal    - specifies the palette to use with the bitmap 
  969.  * 
  970.  * Return Value: 
  971.  * 
  972.  * HBITMAP          - identifies the device-dependent bitmap 
  973.  * 
  974.  * Description: 
  975.  * 
  976.  * This function creates a bitmap from a DIB using the specified palette. 
  977.  * If no palette is specified, default is used. 
  978.  * 
  979.  * NOTE: 
  980.  * 
  981.  * The bitmap returned from this funciton is always a bitmap compatible 
  982.  * with the screen (e.g. same bits/pixel and color planes) rather than 
  983.  * a bitmap with the same attributes as the DIB.  This behavior is by 
  984.  * design, and occurs because this function calls CreateDIBitmap to 
  985.  * do its work, and CreateDIBitmap always creates a bitmap compatible 
  986.  * with the hDC parameter passed in (because it in turn calls 
  987.  * CreateCompatibleBitmap). 
  988.  * 
  989.  * So for instance, if your DIB is a monochrome DIB and you call this 
  990.  * function, you will not get back a monochrome HBITMAP -- you will 
  991.  * get an HBITMAP compatible with the screen DC, but with only 2 
  992.  * colors used in the bitmap. 
  993.  * 
  994.  * If your application requires a monochrome HBITMAP returned for a 
  995.  * monochrome DIB, use the function SetDIBits(). 
  996.  * 
  997.  * Also, the DIBpassed in to the function is not destroyed on exit. This 
  998.  * must be done later, once it is no longer needed. 
  999.  * 
  1000.  ************************************************************************/ 
  1001. HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal) 
  1002.     LPSTR       lpDIBHdr, lpDIBBits;  // pointer to DIB header, pointer to DIB bits 
  1003.     HBITMAP     hBitmap;            // handle to device-dependent bitmap 
  1004.     HDC         hDC;                    // handle to DC 
  1005.     HPALETTE    hOldPal = NULL;    // handle to a palette 
  1006.  
  1007.     // if invalid handle, return NULL  
  1008.  
  1009.     if (!hDIB) 
  1010.         return NULL; 
  1011.  
  1012.     // lock memory block and get a pointer to it 
  1013.  
  1014.     lpDIBHdr = (LPSTR)GlobalLock(hDIB); 
  1015.  
  1016.     // get a pointer to the DIB bits 
  1017.  
  1018.     lpDIBBits = FindDIBBits(lpDIBHdr); 
  1019.  
  1020.     // get a DC  
  1021.  
  1022.     hDC = GetDC(NULL); 
  1023.     if (!hDC) 
  1024.     { 
  1025.         // clean up and return NULL 
  1026.         GlobalUnlock(hDIB); 
  1027.         return NULL; 
  1028.     } 
  1029.  
  1030.     // select and realize palette 
  1031.  
  1032.     if (hPal) 
  1033. {
  1034.         hOldPal = SelectPalette(hDC, hPal, FALSE); 
  1035.     RealizePalette(hDC); 
  1036. }
  1037.  
  1038.     // create bitmap from DIB info and bits 
  1039.     hBitmap = CreateDIBitmap(hDC, 
  1040. (LPBITMAPINFOHEADER)lpDIBHdr, 
  1041. CBM_INIT, 
  1042. lpDIBBits, 
  1043. (LPBITMAPINFO)lpDIBHdr, 
  1044. DIB_RGB_COLORS);
  1045.  
  1046.     // restore previous palette 
  1047.     if (hOldPal) 
  1048.         SelectPalette(hDC, hOldPal, FALSE); 
  1049.  
  1050.     // clean up 
  1051.     ReleaseDC(NULL, hDC); 
  1052.     GlobalUnlock(hDIB); 
  1053.  
  1054.     // return handle to the bitmap 
  1055.     return hBitmap; 
  1056.  
  1057.  
  1058. /************************************************************************* 
  1059.  * 
  1060.  * BitmapToDIB() 
  1061.  * 
  1062.  * Parameters: 
  1063.  * 
  1064.  * HBITMAP hBitmap  - specifies the bitmap to convert 
  1065.  * 
  1066.  * HPALETTE hPal    - specifies the palette to use with the bitmap 
  1067.  * 
  1068.  * Return Value: 
  1069.  * 
  1070.  * HDIB             - identifies the device-dependent bitmap 
  1071.  * 
  1072.  * Description: 
  1073.  * 
  1074.  * This function creates a DIB from a bitmap using the specified palette. 
  1075.  * 
  1076.  ************************************************************************/ 
  1077. HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal) 
  1078.     BITMAP              bm;         // bitmap structure 
  1079.     BITMAPINFOHEADER    bi;         // bitmap header 
  1080.     LPBITMAPINFOHEADER  lpbi;       // pointer to BITMAPINFOHEADER 
  1081.     DWORD               dwLen;      // size of memory block 
  1082.     HANDLE              hDIB, h;    // handle to DIB, temp handle 
  1083.     HDC                 hDC;        // handle to DC 
  1084.     WORD                biBits;     // bits per pixel 
  1085.  
  1086.     // check if bitmap handle is valid 
  1087.  
  1088.     if (!hBitmap) 
  1089.         return NULL; 
  1090.  
  1091.     // fill in BITMAP structure, return NULL if it didn't work 
  1092.  
  1093.     if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm)) 
  1094.         return NULL; 
  1095.  
  1096.     // if no palette is specified, use default palette 
  1097.  
  1098.     if (hPal == NULL) 
  1099.         hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); 
  1100.  
  1101.     // calculate bits per pixel 
  1102.  
  1103.     biBits = bm.bmPlanes * bm.bmBitsPixel; 
  1104.  
  1105.     // make sure bits per pixel is valid 
  1106.  
  1107.     if (biBits <= 1) 
  1108.         biBits = 1; 
  1109.     else if (biBits <= 4) 
  1110.         biBits = 4; 
  1111.     else if (biBits <= 8) 
  1112.         biBits = 8; 
  1113.     else // if greater than 8-bit, force to 24-bit 
  1114.         biBits = 24; 
  1115.  
  1116.     // initialize BITMAPINFOHEADER 
  1117.  
  1118.     bi.biSize = sizeof(BITMAPINFOHEADER); 
  1119.     bi.biWidth = bm.bmWidth; 
  1120.     bi.biHeight = bm.bmHeight; 
  1121.     bi.biPlanes = 1; 
  1122.     bi.biBitCount = biBits; 
  1123.     bi.biCompression = BI_RGB; 
  1124.     bi.biSizeImage = 0; 
  1125.     bi.biXPelsPerMeter = 0; 
  1126.     bi.biYPelsPerMeter = 0; 
  1127.     bi.biClrUsed = 0; 
  1128.     bi.biClrImportant = 0; 
  1129.  
  1130.     // calculate size of memory block required to store BITMAPINFO 
  1131.  
  1132.     dwLen = bi.biSize + PaletteSize((LPSTR)&bi); 
  1133.  
  1134.     // get a DC 
  1135.  
  1136.     hDC = GetDC(NULL); 
  1137.  
  1138.     // select and realize our palette 
  1139.  
  1140.     hPal = SelectPalette(hDC, hPal, FALSE); 
  1141.     RealizePalette(hDC); 
  1142.  
  1143.     // alloc memory block to store our bitmap 
  1144.  
  1145.     hDIB = GlobalAlloc(GHND, dwLen); 
  1146.  
  1147.     // if we couldn't get memory block 
  1148.  
  1149.     if (!hDIB) 
  1150.     { 
  1151.       // clean up and return NULL 
  1152.  
  1153.       SelectPalette(hDC, hPal, TRUE); 
  1154.       RealizePalette(hDC); 
  1155.       ReleaseDC(NULL, hDC); 
  1156.       return NULL; 
  1157.     } 
  1158.  
  1159.     // lock memory and get pointer to it 
  1160.  
  1161.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
  1162.  
  1163.     /// use our bitmap info. to fill BITMAPINFOHEADER 
  1164.  
  1165.     *lpbi = bi; 
  1166.  
  1167.     // call GetDIBits with a NULL lpBits param, so it will calculate the 
  1168.     // biSizeImage field for us     
  1169.  
  1170.     GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, 
  1171.         DIB_RGB_COLORS); 
  1172.  
  1173.     // get the info. returned by GetDIBits and unlock memory block 
  1174.  
  1175.     bi = *lpbi; 
  1176.     GlobalUnlock(hDIB); 
  1177.  
  1178.     // if the driver did not fill in the biSizeImage field, make one up  
  1179.     if (bi.biSizeImage == 0) 
  1180.         bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight; 
  1181.  
  1182.     // realloc the buffer big enough to hold all the bits 
  1183.  
  1184.     dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage; 
  1185.  
  1186.     if (h = GlobalReAlloc(hDIB, dwLen, 0)) 
  1187.         hDIB = h; 
  1188.     else 
  1189.     { 
  1190.         // clean up and return NULL 
  1191.  
  1192.         GlobalFree(hDIB); 
  1193.         hDIB = NULL; 
  1194.         SelectPalette(hDC, hPal, TRUE); 
  1195.         RealizePalette(hDC); 
  1196.         ReleaseDC(NULL, hDC); 
  1197.         return NULL; 
  1198.     } 
  1199.  
  1200.     // lock memory block and get pointer to it */ 
  1201.  
  1202.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
  1203.  
  1204.     // call GetDIBits with a NON-NULL lpBits param, and actualy get the 
  1205.     // bits this time 
  1206.  
  1207.     if (GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, (LPSTR)lpbi + 
  1208.             (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi, 
  1209.             DIB_RGB_COLORS) == 0) 
  1210.     { 
  1211.         // clean up and return NULL 
  1212.  
  1213.         GlobalUnlock(hDIB); 
  1214.         hDIB = NULL; 
  1215.         SelectPalette(hDC, hPal, TRUE); 
  1216.         RealizePalette(hDC); 
  1217.         ReleaseDC(NULL, hDC); 
  1218.         return NULL; 
  1219.     } 
  1220.  
  1221.     bi = *lpbi; 
  1222.  
  1223.     // clean up  
  1224.     GlobalUnlock(hDIB); 
  1225.     SelectPalette(hDC, hPal, TRUE); 
  1226.     RealizePalette(hDC); 
  1227.     ReleaseDC(NULL, hDC); 
  1228.  
  1229.     // return handle to the DIB 
  1230.     return hDIB; 
  1231.  
  1232. /************************************************************************* 
  1233.  * 
  1234.  * BitmapToDIB() 
  1235.  * 
  1236.  * Parameters: 
  1237.  * 
  1238.  * HBITMAP hBitmap  - specifies the bitmap to convert 
  1239.  * 
  1240.  * HPALETTE hPal    - specifies the palette to use with the bitmap 
  1241.  * 
  1242.  * WORD wBitCount   - specifies the DIB colorbits 
  1243.  *
  1244.  * Return Value: 
  1245.  * 
  1246.  * HDIB             - identifies the device-dependent bitmap 
  1247.  * 
  1248.  * Description: 
  1249.  * 
  1250.  * This function creates a DIB from a bitmap using the specified palette. 
  1251.  * 
  1252.  ************************************************************************/ 
  1253. HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPalette, WORD wBitCount)
  1254. HDIB hNewDib;
  1255. if (! hBitmap)
  1256.         return NULL; 
  1257. // get bitmap info
  1258. BITMAP  bm;         // bitmap structure 
  1259. GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); 
  1260. int biBits = bm.bmPlanes * bm.bmBitsPixel;
  1261. // make sure bits per pixel is valid 
  1262. if (biBits <= 1) 
  1263. biBits = 1; 
  1264. else if (biBits <= 4) 
  1265. biBits = 4; 
  1266. else if (biBits <= 8) 
  1267. biBits = 8; 
  1268. else // if greater than 8-bit, force to 24-bit 
  1269. biBits = 24; 
  1270. // get DIB handle from current bitmap
  1271. HDIB hDib = BitmapToDIB(hBitmap, hPalette);
  1272. if (! hDib)
  1273.         return NULL; 
  1274. if (wBitCount == biBits)
  1275. hNewDib = hDib;
  1276. else
  1277. {
  1278.     // DIB bits/pixel is not the same as device
  1279. // convert dib format to accordingly
  1280. hNewDib = ConvertDIBFormat(hDib, wBitCount, hPalette);
  1281. // cleanup hDib
  1282. GlobalFree(hDib);
  1283. }
  1284. return hNewDib;
  1285. /************************************************************************* 
  1286.  * 
  1287.  * ChangeBitmapFormat() 
  1288.  * 
  1289.  * Parameter: 
  1290.  * 
  1291.  * HBITMAP          - handle to a bitmap 
  1292.  * 
  1293.  * WORD             - desired bits per pixel 
  1294.  * 
  1295.  * DWORD            - desired compression format 
  1296.  * 
  1297.  * HPALETTE         - handle to palette 
  1298.  * 
  1299.  * Return Value: 
  1300.  * 
  1301.  * HDIB             - handle to the new DIB if successful, else NULL 
  1302.  * 
  1303.  * Description: 
  1304.  * 
  1305.  * This function will convert a bitmap to the specified bits per pixel 
  1306.  * and compression format. The bitmap and it's palette will remain 
  1307.  * after calling this function. 
  1308.  * 
  1309.  ************************************************************************/ 
  1310. HDIB ChangeBitmapFormat (HBITMAP hbm, WORD biBits, DWORD biCompression, HPALETTE hpal)
  1311. {
  1312.     BITMAP               bm;
  1313.     BITMAPINFOHEADER     bi;
  1314.     LPBITMAPINFOHEADER   lpbi;
  1315.     DWORD                dwLen;
  1316.     HANDLE               hdib;
  1317.     HANDLE               h;
  1318.     HDC                  hdc;
  1319.     if (!hbm)
  1320.         return NULL;
  1321.     if (hpal == NULL)
  1322.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  1323.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  1324.     if (biBits == 0)
  1325. {
  1326.         biBits =  bm.bmPlanes * bm.bmBitsPixel;
  1327. // make sure bits per pixel is valid 
  1328.     if (biBits <= 1) 
  1329.     biBits = 1; 
  1330.     else if (biBits <= 4) 
  1331.     biBits = 4; 
  1332.     else if (biBits <= 8) 
  1333.     biBits = 8; 
  1334. else // if greater than 8-bit, force to 24-bit 
  1335. biBits = 24; 
  1336. }
  1337.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  1338.     bi.biWidth              = bm.bmWidth;
  1339.     bi.biHeight             = bm.bmHeight;
  1340.     bi.biPlanes             = 1;
  1341.     bi.biBitCount           = biBits;
  1342.     bi.biCompression        = biCompression;
  1343.     bi.biSizeImage          = 0;
  1344.     bi.biXPelsPerMeter      = 0;
  1345.     bi.biYPelsPerMeter      = 0;
  1346.     bi.biClrUsed            = 0;
  1347.     bi.biClrImportant       = 0;
  1348.     dwLen  = bi.biSize + PaletteSize((LPSTR)&bi);
  1349.     hdc = GetDC(NULL);
  1350.     HPALETTE hpalT = SelectPalette(hdc,hpal,FALSE);
  1351.     RealizePalette(hdc);
  1352.     hdib = GlobalAlloc(GHND,dwLen);
  1353.     if (!hdib)
  1354. {
  1355.         SelectPalette(hdc,hpalT,FALSE);
  1356.         ReleaseDC(NULL,hdc);
  1357.         return NULL;
  1358.     }
  1359.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  1360.     *lpbi = bi;
  1361.     /*  call GetDIBits with a NULL lpBits param, so it will calculate the
  1362.      *  biSizeImage field for us
  1363.      */
  1364.     GetDIBits(hdc, hbm, 0L, (DWORD)bi.biHeight,
  1365.         (LPSTR)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
  1366.     bi = *lpbi;
  1367.     GlobalUnlock(hdib);
  1368.     /* If the driver did not fill in the biSizeImage field, make one up */
  1369.     if (bi.biSizeImage == 0)
  1370. {
  1371.         bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  1372.         if (biCompression != BI_RGB)
  1373.             bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  1374.     }
  1375.     /*  realloc the buffer big enough to hold all the bits */
  1376.     dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
  1377.     if (h = GlobalReAlloc(hdib,dwLen,0))
  1378.         hdib = h;
  1379.     else
  1380. {
  1381.         GlobalFree(hdib);
  1382.         hdib = NULL;
  1383.         SelectPalette(hdc,hpalT,FALSE);
  1384.         ReleaseDC(NULL,hdc);
  1385.         return hdib;
  1386.     }
  1387.     /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  1388.      *  bits this time
  1389.      */
  1390.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  1391.     if (! GetDIBits(hdc,
  1392.                     hbm,
  1393.                     0L,
  1394.                     (DWORD)bi.biHeight,
  1395.                     (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
  1396.                     (LPBITMAPINFO)lpbi, 
  1397. (DWORD)DIB_RGB_COLORS))
  1398. {
  1399.          GlobalUnlock(hdib);
  1400.          hdib = NULL;
  1401.          SelectPalette(hdc,hpalT,FALSE);
  1402.          ReleaseDC(NULL,hdc);
  1403.          return NULL;
  1404.     }
  1405.     bi = *lpbi;
  1406.    
  1407. GlobalUnlock(hdib);
  1408.     SelectPalette(hdc,hpalT,FALSE);
  1409.     ReleaseDC(NULL,hdc);
  1410.     return hdib;
  1411. }
  1412. /************************************************************************* 
  1413.  * 
  1414.  * ChangeDIBFormat() 
  1415.  * 
  1416.  * Parameter: 
  1417.  * 
  1418.  * HDIB             - handle to packed-DIB in memory 
  1419.  * 
  1420.  * WORD             - desired bits per pixel 
  1421.  * 
  1422.  * DWORD            - desired compression format 
  1423.  * 
  1424.  * Return Value: 
  1425.  * 
  1426.  * HDIB             - handle to the new DIB if successful, else NULL 
  1427.  * 
  1428.  * Description: 
  1429.  * 
  1430.  * This function will convert the bits per pixel and/or the compression 
  1431.  * format of the specified DIB. Note: If the conversion was unsuccessful, 
  1432.  * we return NULL. The original DIB is left alone. Don't use code like the 
  1433.  * following: 
  1434.  * 
  1435.  *    hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4); 
  1436.  * 
  1437.  * The conversion will fail, but hMyDIB will now be NULL and the original 
  1438.  * DIB will now hang around in memory. We could have returned the old 
  1439.  * DIB, but we wanted to allow the programmer to check whether this 
  1440.  * conversion succeeded or failed. 
  1441.  * 
  1442.  ************************************************************************/ 
  1443. HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression) 
  1444.     HBITMAP            hBitmap;         // Handle to bitmap 
  1445.     HDIB               hNewDIB = NULL;  // Handle to new DIB 
  1446.     HPALETTE           hPal; // Handle to palette
  1447.     // Check for a valid DIB handle 
  1448.  
  1449.     if (!hDIB) 
  1450.         return NULL; 
  1451.  
  1452.     // Save the old DIB's palette 
  1453.  
  1454.     hPal = CreateDIBPalette(hDIB); 
  1455.     if (hPal == NULL)
  1456.         hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  1457.  
  1458.     // Convert old DIB to a bitmap 
  1459.  
  1460.     hBitmap = DIBToBitmap(hDIB, hPal); 
  1461.     if (!hBitmap) 
  1462.     { 
  1463.         DeleteObject(hPal); 
  1464.         return NULL; 
  1465.     } 
  1466. // Change bitmap format
  1467. hNewDIB = ChangeBitmapFormat(hBitmap, wBitCount, dwCompression, hPal);
  1468.  
  1469.     // Clean up and return 
  1470.  
  1471.     DeleteObject(hBitmap); 
  1472.     DeleteObject(hPal); 
  1473.  
  1474.     return hNewDIB; 
  1475.  
  1476. /**************************************************************************** 
  1477. *     FUNCTION: ConvertDIBFormat 
  1478. *     PURPOSE:  Creates a new DIB of the requested format, copies the source 
  1479. *               image to the new DIB. 
  1480. *     PARAMS:   LPBITMAPINFO lpSrcDIB - the source CF_DIB 
  1481. *               UINT         nWidth   - width for new DIB 
  1482. *               UINT         nHeight  - height for new DIB 
  1483. *               UINT         nbpp     - bpp for new DIB 
  1484. *               BOOL         bStretch - TRUE to stretch source to dest 
  1485. *                                       FALSE to take upper left of image 
  1486. * HPALETTE  hPalSrc  - Palette used to set new DIB
  1487. * DWORD  dwSize   - return the size of new DIB pointer
  1488. *     RETURNS:  HDIB - Handle of CF_DIB memory block with new image 
  1489. *               NULL on failure 
  1490. ****************************************************************************/ 
  1491. HDIB ConvertDIBFormat(LPSTR lpDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc) 
  1492. LPBITMAPINFO lpSrcDIB =  (LPBITMAPINFO)lpDIB;
  1493.     LPBITMAPINFO lpbmi = NULL; 
  1494.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  1495.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  1496.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  1497.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; 
  1498. HDIB  hDib;
  1499.  
  1500.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  1501.     if (nbpp <= 8) 
  1502. dwColorNum = 1 << nbpp;
  1503. else
  1504. dwColorNum = 0;
  1505.     dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); 
  1506.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  1507.     lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  1508.     lpbmi->bmiHeader.biWidth = nWidth; 
  1509.     lpbmi->bmiHeader.biHeight = nHeight; 
  1510.     lpbmi->bmiHeader.biPlanes = 1; 
  1511.     lpbmi->bmiHeader.biBitCount = nbpp; 
  1512.     lpbmi->bmiHeader.biCompression = BI_RGB; 
  1513.     lpbmi->bmiHeader.biSizeImage = 0; 
  1514.     lpbmi->bmiHeader.biXPelsPerMeter = 0; 
  1515.     lpbmi->bmiHeader.biYPelsPerMeter = 0; 
  1516.     lpbmi->bmiHeader.biClrUsed = 0; 
  1517.     lpbmi->bmiHeader.biClrImportant = 0; 
  1518.     // Fill in the color table 
  1519.     if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) 
  1520.     { 
  1521.         free( lpbmi ); 
  1522.         return NULL; 
  1523.     } 
  1524.  
  1525.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  1526. hDC = GetDC( NULL ); 
  1527.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  1528.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  1529.     hSourceDC = CreateCompatibleDC( hDC ); 
  1530.     hTargetDC = CreateCompatibleDC( hDC ); 
  1531.  
  1532.     // Flip the bits on the source DIBSection to match the source DIB 
  1533.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  1534.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  1535.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  1536.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  1537.  
  1538.     // Select DIBSections into DCs 
  1539.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  1540.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  1541.  
  1542.     // Set the color tables for the DIBSections 
  1543.     if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
  1544.         SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
  1545.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  1546.         SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  1547.  
  1548.     // If we are asking for a straight copy, do it 
  1549.     if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) ) 
  1550.     { 
  1551.         BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1552.     } 
  1553.     else 
  1554.     { 
  1555.         // else, should we stretch it? 
  1556.         if( bStretch ) 
  1557.         { 
  1558.             SetStretchBltMode( hTargetDC, COLORONCOLOR ); 
  1559.             StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); 
  1560.         } 
  1561.         else 
  1562.         { 
  1563.             // or just take the upper left corner of the source 
  1564.             BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1565.         } 
  1566.     } 
  1567.  
  1568.     // Clean up and delete the DCs 
  1569.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  1570.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  1571.     DeleteDC( hSourceDC ); 
  1572.     DeleteDC( hTargetDC ); 
  1573.     ReleaseDC( NULL, hDC ); 
  1574.  
  1575.     // Flush the GDI batch, so we can play with the bits 
  1576.     GdiFlush(); 
  1577.  
  1578.     // Allocate enough memory for the new CF_DIB, and copy bits 
  1579.     hDib = GlobalAlloc(GHND, dwTargetHeaderSize + dwTargetBitsSize ); 
  1580.     lpResult = (LPSTR)GlobalLock(hDib); 
  1581.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  1582.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  1583.  
  1584.     // final cleanup 
  1585.     DeleteObject( hTargetBitmap ); 
  1586.     DeleteObject( hSourceBitmap ); 
  1587. free( lpbmi ); 
  1588.     GlobalUnlock(hDib);
  1589.  
  1590.     return hDib; 
  1591. /* End ConvertDIBFormat() 1***************************************************/ 
  1592. /**************************************************************************** 
  1593. *     FUNCTION: ConvertDIBFormat 
  1594. *     PURPOSE:  Creates a new DIB of the requested format, copies the source 
  1595. *               image to the new DIB. 
  1596. *     PARAMS:   HDIB  hDIB     - the source CF_DIB 
  1597. *               UINT         nWidth   - width for new DIB 
  1598. *               UINT         nHeight  - height for new DIB 
  1599. *               UINT         nbpp     - bpp for new DIB 
  1600. *               BOOL         bStretch - TRUE to stretch source to dest 
  1601. *                                       FALSE to take upper left of image 
  1602. * HPALETTE  hPalSrc  - Palette used to set new DIB
  1603. *     RETURNS:  HDIB - new CF_DIB handle
  1604. ****************************************************************************/ 
  1605. HDIB ConvertDIBFormat(HDIB hDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc)
  1606. {
  1607.     LPBITMAPINFO lpbmi = NULL; 
  1608.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  1609.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  1610.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  1611.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; 
  1612. HDIB  hNewDIB;
  1613. DWORD  dwSize;
  1614. // Get DIB pointer
  1615. if (! hDIB)
  1616. return NULL;
  1617. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  1618. if (! lpSrcDIB)
  1619. return NULL;
  1620.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  1621.     if (nbpp <= 8) 
  1622. dwColorNum = 1 << nbpp;
  1623. else
  1624. dwColorNum = 0;
  1625.     dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); 
  1626.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  1627.     lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  1628.     lpbmi->bmiHeader.biWidth = nWidth; 
  1629.     lpbmi->bmiHeader.biHeight = nHeight; 
  1630.     lpbmi->bmiHeader.biPlanes = 1; 
  1631.     lpbmi->bmiHeader.biBitCount = nbpp; 
  1632.     lpbmi->bmiHeader.biCompression = BI_RGB; 
  1633.     lpbmi->bmiHeader.biSizeImage = 0; 
  1634.     lpbmi->bmiHeader.biXPelsPerMeter = 0; 
  1635.     lpbmi->bmiHeader.biYPelsPerMeter = 0; 
  1636.     lpbmi->bmiHeader.biClrUsed = 0; 
  1637.     lpbmi->bmiHeader.biClrImportant = 0; 
  1638.     // Fill in the color table 
  1639.     if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) 
  1640.     { 
  1641.         free( lpbmi ); 
  1642.         return NULL; 
  1643.     } 
  1644.  
  1645.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  1646. hDC = GetDC( NULL ); 
  1647.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  1648.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  1649.     hSourceDC = CreateCompatibleDC( hDC ); 
  1650.     hTargetDC = CreateCompatibleDC( hDC ); 
  1651.  
  1652.     // Flip the bits on the source DIBSection to match the source DIB 
  1653.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  1654.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  1655.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  1656.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  1657.  
  1658.     // Select DIBSections into DCs 
  1659.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  1660.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  1661.  
  1662.     // Set the color tables for the DIBSections 
  1663.     if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
  1664.         SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
  1665.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  1666.         SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  1667.  
  1668.     // If we are asking for a straight copy, do it 
  1669.     if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) ) 
  1670.     { 
  1671.         BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1672.     } 
  1673.     else 
  1674.     { 
  1675.         // else, should we stretch it? 
  1676.         if( bStretch ) 
  1677.         { 
  1678.             SetStretchBltMode( hTargetDC, COLORONCOLOR ); 
  1679.             StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); 
  1680.         } 
  1681.         else 
  1682.         { 
  1683.             // or just take the upper left corner of the source 
  1684.             BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1685.         } 
  1686.     } 
  1687.  
  1688.     // Clean up and delete the DCs 
  1689.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  1690.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  1691.     DeleteDC( hSourceDC ); 
  1692.     DeleteDC( hTargetDC ); 
  1693.     ReleaseDC( NULL, hDC ); 
  1694.  
  1695.     // Flush the GDI batch, so we can play with the bits 
  1696.     GdiFlush(); 
  1697.  
  1698.     // Allocate enough memory for the new CF_DIB, and copy bits 
  1699. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  1700. hNewDIB = GlobalAlloc(GHND, dwSize);
  1701.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  1702.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  1703.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  1704.  
  1705.     // final cleanup 
  1706.     DeleteObject( hTargetBitmap ); 
  1707.     DeleteObject( hSourceBitmap ); 
  1708.     free( lpbmi ); 
  1709. GlobalUnlock(hDIB);
  1710. GlobalUnlock(hNewDIB);
  1711.  
  1712.     return hNewDIB;
  1713. }
  1714. /* End ConvertDIBFormat() 2***************************************************/ 
  1715. /**************************************************************************** 
  1716. *     FUNCTION: ConvertDIBFormat 
  1717. *     PURPOSE:  Creates a new DIB of the requested format, copies the source 
  1718. *               image to the new DIB. 
  1719. *     PARAMS:   LPSTR  lpDIB    - the source CF_DIB 
  1720. *               UINT         nbpp     - bpp for new DIB 
  1721. * HPALETTE  hPalSrc  - Palette used to set new DIB
  1722. *     RETURNS:  HDIB - new CF_DIB handle
  1723. ****************************************************************************/ 
  1724. HDIB ConvertDIBFormat(LPSTR lpDIB, UINT nbpp, HPALETTE hPalSrc)
  1725. {
  1726. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
  1727.     LPBITMAPINFO lpbmi = NULL; 
  1728.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  1729.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  1730.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  1731.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; 
  1732. HDIB  hNewDIB;
  1733. DWORD  dwSize;
  1734. int  nWidth, nHeight;
  1735. nWidth = lpSrcDIB->bmiHeader.biWidth;
  1736. nHeight = lpSrcDIB->bmiHeader.biHeight;
  1737.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  1738.     if (nbpp <= 8) 
  1739. dwColorNum = 1 << nbpp;
  1740. else
  1741. dwColorNum = 0;
  1742.     dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); 
  1743.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  1744.     lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  1745.     lpbmi->bmiHeader.biWidth = nWidth; 
  1746.     lpbmi->bmiHeader.biHeight = nHeight; 
  1747.     lpbmi->bmiHeader.biPlanes = 1; 
  1748.     lpbmi->bmiHeader.biBitCount = nbpp; 
  1749.     lpbmi->bmiHeader.biCompression = BI_RGB; 
  1750.     lpbmi->bmiHeader.biSizeImage = 0; 
  1751.     lpbmi->bmiHeader.biXPelsPerMeter = 0; 
  1752.     lpbmi->bmiHeader.biYPelsPerMeter = 0; 
  1753.     lpbmi->bmiHeader.biClrUsed = 0; 
  1754.     lpbmi->bmiHeader.biClrImportant = 0; 
  1755.     // Fill in the color table 
  1756.     if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) 
  1757.     { 
  1758.         free( lpbmi ); 
  1759.         return NULL; 
  1760.     } 
  1761.  
  1762.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  1763. hDC = GetDC( NULL ); 
  1764.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  1765.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  1766.     hSourceDC = CreateCompatibleDC( hDC ); 
  1767.     hTargetDC = CreateCompatibleDC( hDC ); 
  1768.  
  1769.     // Flip the bits on the source DIBSection to match the source DIB 
  1770.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  1771.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  1772.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  1773.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  1774.  
  1775.     // Select DIBSections into DCs 
  1776.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  1777.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  1778.  
  1779.     // Set the color tables for the DIBSections 
  1780.     if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
  1781.         SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
  1782.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  1783.         SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  1784.  
  1785.     // We are asking for a straight copy, do it 
  1786.     BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1787.  
  1788.     // Clean up and delete the DCs 
  1789.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  1790.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  1791.     DeleteDC( hSourceDC ); 
  1792.     DeleteDC( hTargetDC ); 
  1793.     ReleaseDC( NULL, hDC ); 
  1794.  
  1795.     // Flush the GDI batch, so we can play with the bits 
  1796.     GdiFlush(); 
  1797.  
  1798.     // Allocate enough memory for the new CF_DIB, and copy bits 
  1799. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  1800. hNewDIB = GlobalAlloc(GHND, dwSize);
  1801.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  1802.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  1803.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  1804.  
  1805.     // final cleanup 
  1806.     DeleteObject( hTargetBitmap ); 
  1807.     DeleteObject( hSourceBitmap ); 
  1808.     free( lpbmi ); 
  1809. GlobalUnlock(hNewDIB);
  1810.  
  1811.     return hNewDIB;
  1812. }
  1813. /* End ConvertDIBFormat() 3***************************************************/ 
  1814. /**************************************************************************** 
  1815. *     FUNCTION: ConvertDIBFormat 
  1816. *     PURPOSE:  Creates a new DIB of the requested format, copies the source 
  1817. *               image to the new DIB. 
  1818. *     PARAMS:   HDIB  hDIB     - the source CF_DIB 
  1819. *               UINT         nbpp     - bpp for new DIB 
  1820. * HPALETTE  hPalSrc  - Palette used to set new DIB
  1821. *     RETURNS:  HDIB - new CF_DIB handle
  1822. ****************************************************************************/ 
  1823. HDIB ConvertDIBFormat(HDIB hDIB, UINT nbpp, HPALETTE hPalSrc)
  1824. {
  1825. ASSERT(NULL != hDIB);
  1826.     LPBITMAPINFO lpbmi = NULL; 
  1827.     LPSTR lpSourceBits, lpTargetBits, lpResult; 
  1828.     HDC hDC = NULL, hSourceDC, hTargetDC; 
  1829.     HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  1830.     DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; 
  1831. HANDLE hNewDIB;
  1832. DWORD dwSize;
  1833. int nWidth, nHeight;
  1834. // Get DIB pointer
  1835. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  1836. if (! lpSrcDIB)
  1837. return NULL;
  1838. nWidth = lpSrcDIB->bmiHeader.biWidth;
  1839. nHeight = lpSrcDIB->bmiHeader.biHeight;
  1840.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  1841.     if (nbpp <= 8) 
  1842. dwColorNum = 1 << nbpp;
  1843. else
  1844. dwColorNum = 0;
  1845.     dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); 
  1846.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  1847.     lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  1848.     lpbmi->bmiHeader.biWidth = nWidth; 
  1849.     lpbmi->bmiHeader.biHeight = nHeight; 
  1850.     lpbmi->bmiHeader.biPlanes = 1; 
  1851.     lpbmi->bmiHeader.biBitCount = nbpp; 
  1852.     lpbmi->bmiHeader.biCompression = BI_RGB; 
  1853.     lpbmi->bmiHeader.biSizeImage = 0; 
  1854.     lpbmi->bmiHeader.biXPelsPerMeter = 0; 
  1855.     lpbmi->bmiHeader.biYPelsPerMeter = 0; 
  1856.     lpbmi->bmiHeader.biClrUsed = 0; 
  1857.     lpbmi->bmiHeader.biClrImportant = 0; 
  1858.     // Fill in the color table 
  1859.     if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) 
  1860.     { 
  1861.         free( lpbmi ); 
  1862.         return NULL; 
  1863.     } 
  1864.  
  1865.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  1866. hDC = GetDC( NULL ); 
  1867.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  1868.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  1869.     hSourceDC = CreateCompatibleDC( hDC ); 
  1870.     hTargetDC = CreateCompatibleDC( hDC ); 
  1871.  
  1872.     // Flip the bits on the source DIBSection to match the source DIB 
  1873.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  1874.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  1875.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  1876.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  1877.  
  1878.     // Select DIBSections into DCs 
  1879.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  1880.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  1881.  
  1882.     // Set the color tables for the DIBSections 
  1883.     if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
  1884.         SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
  1885.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  1886.         SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  1887.  
  1888.     // We are asking for a straight copy, do it 
  1889.     BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
  1890.  
  1891.     // Clean up and delete the DCs 
  1892.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  1893.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  1894.     DeleteDC( hSourceDC ); 
  1895.     DeleteDC( hTargetDC ); 
  1896.     ReleaseDC( NULL, hDC ); 
  1897.  
  1898.     // Flush the GDI batch, so we can play with the bits 
  1899.     GdiFlush(); 
  1900.  
  1901.     // Allocate enough memory for the new CF_DIB, and copy bits 
  1902. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  1903. hNewDIB = GlobalAlloc(GHND, dwSize);
  1904.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  1905.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  1906.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  1907.  
  1908.     // final cleanup 
  1909.     DeleteObject( hTargetBitmap ); 
  1910.     DeleteObject( hSourceBitmap ); 
  1911.     free( lpbmi ); 
  1912. GlobalUnlock(hDIB);
  1913. GlobalUnlock(hNewDIB);
  1914.  
  1915.     return hNewDIB;
  1916. }
  1917. /* End ConvertDIBFormat() 4***************************************************/ 
  1918.  
  1919. /**************************************************************************** 
  1920. *     FUNCTION: CopyColorTable 
  1921. *     PURPOSE:  Copies the color table from one CF_DIB to another. 
  1922. *     PARAMS:   LPBITMAPINFO lpTarget - pointer to target DIB 
  1923. *               LPBITMAPINFO lpSource - pointer to source DIB 
  1924. *     RETURNS:  BOOL - TRUE for success, FALSE for failure 
  1925. ****************************************************************************/ 
  1926. BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc ) 
  1927.     // What we do depends on the target's color depth 
  1928.     switch( lpTarget->bmiHeader.biBitCount ) 
  1929.     { 
  1930.         // 8bpp - need 256 entry color table 
  1931.         case 8: 
  1932. if (NULL != hPalSrc)
  1933. { // Palette is provided, use it
  1934. PALETTEENTRY    pe[256]; 
  1935. UINT            i; 
  1936. GetPaletteEntries( hPalSrc, 0, 256, pe ); 
  1937. for(i=0;i<256;i++) 
  1938. lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
  1939. lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
  1940. lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
  1941. lpTarget->bmiColors[i].rgbReserved = 0; 
  1942. }
  1943. else
  1944. { // no palette povided
  1945. if( lpSource->bmiHeader.biBitCount == 8 ) 
  1946. { // Source is 8bpp too, copy color table 
  1947. memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) ); 
  1948. else 
  1949. { // Source is != 8bpp, use Octree algorithm to create palette
  1950. HPALETTE        hPal; 
  1951. HDC            hDC = GetDC( NULL ); 
  1952. PALETTEENTRY    pe[256]; 
  1953. UINT            i; 
  1954.  
  1955. hPal = CreateOctreePalette((LPSTR)lpSource, 236, 8);
  1956. if (! hPal)  // use halftone palette                 
  1957. hPal = CreateHalftonePalette( hDC ); 
  1958. ReleaseDC( NULL, hDC ); 
  1959. GetPaletteEntries( hPal, 0, 256, pe ); 
  1960. DeleteObject( hPal ); 
  1961. for(i=0;i<256;i++) 
  1962. lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
  1963. lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
  1964. lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
  1965. lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; 
  1966. }
  1967. }
  1968. break; // end 8bpp 
  1969.  
  1970.         // 4bpp - need 16 entry color table 
  1971.         case 4: 
  1972. if (hPalSrc)
  1973. { // Palette is provided, use it
  1974. PALETTEENTRY    pe[16]; 
  1975. UINT            i; 
  1976. GetPaletteEntries( hPalSrc, 0, 16, pe ); 
  1977. for(i=0;i<16;i++) 
  1978. lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
  1979. lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
  1980. lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
  1981. lpTarget->bmiColors[i].rgbReserved = 0; 
  1982. }
  1983. else
  1984. { // No palette is provided
  1985. if( lpSource->bmiHeader.biBitCount == 4 ) 
  1986. { // Source is 4bpp too, copy color table 
  1987. memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) ); 
  1988. else 
  1989. { // Source is != 4bpp, use system palette 
  1990. HPALETTE        hPal; 
  1991. PALETTEENTRY    pe[256]; 
  1992. UINT            i; 
  1993.  
  1994. hPal = (HPALETTE)GetStockObject( DEFAULT_PALETTE ); 
  1995. GetPaletteEntries( hPal, 0, 16, pe ); 
  1996. for(i=0;i<16;i++) 
  1997. lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
  1998. lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
  1999. lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
  2000. lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; 
  2001. }
  2002.                 } 
  2003. }
  2004. break; // end 4bpp 
  2005.  
  2006.         // 1bpp - need 2 entry mono color table 
  2007.         case 1: 
  2008.             lpTarget->bmiColors[0].rgbRed = 0; 
  2009.             lpTarget->bmiColors[0].rgbGreen = 0; 
  2010.             lpTarget->bmiColors[0].rgbBlue = 0; 
  2011.             lpTarget->bmiColors[0].rgbReserved = 0; 
  2012.             lpTarget->bmiColors[1].rgbRed = 255; 
  2013.             lpTarget->bmiColors[1].rgbGreen = 255; 
  2014.             lpTarget->bmiColors[1].rgbBlue = 255; 
  2015.             lpTarget->bmiColors[1].rgbReserved = 0; 
  2016. break; // end 1bpp 
  2017.  
  2018.         // no color table for the > 8bpp modes 
  2019.         case 32: 
  2020.         case 24: 
  2021.         case 16: 
  2022.         default: 
  2023.         break; 
  2024.     } 
  2025.     return TRUE; 
  2026. /* End CopyColorTable() *****************************************************/ 
  2027. /**************************************************************************** 
  2028. *     FUNCTION: DIBToDIBSection 
  2029. *     PURPOSE:  Create DIBSECTION from DIB
  2030. *     PARAMS:   LPSTR lpDIB - pointer to DIB data buffer
  2031. *     RETURNS:  HBITMAP - handle of DIBSECTION, or NULL for failure 
  2032. ****************************************************************************/ 
  2033. HBITMAP DIBToDIBSection(LPSTR lpDIB) 
  2034. {
  2035.     LPSTR       lpSourceBits; 
  2036.     HDC  hDC = NULL, hSourceDC; 
  2037.     HBITMAP      hSourceBitmap, hOldSourceBitmap; 
  2038.     DWORD        dwSourceBitsSize; 
  2039. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
  2040. if (! lpSrcDIB)
  2041. return NULL;
  2042.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  2043. hDC = GetDC( NULL ); 
  2044.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  2045.     hSourceDC = CreateCompatibleDC( hDC ); 
  2046.  
  2047.     // Flip the bits on the source DIBSection to match the source DIB 
  2048.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  2049.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  2050.  
  2051.     // Select DIBSections into DCs 
  2052.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  2053.  
  2054.     // Set the color tables for the DIBSections 
  2055.     if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
  2056.         SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
  2057.     // Clean up and delete the DCs 
  2058.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  2059.     DeleteDC( hSourceDC ); 
  2060.     ReleaseDC( NULL, hDC ); 
  2061.  
  2062.     // Flush the GDI batch, so we can play with the bits 
  2063.     GdiFlush(); 
  2064.  
  2065.     return hSourceBitmap;
  2066. // Create DIBSECTION from DIB
  2067. HBITMAP DIBToDIBSection(HDIB hDIB) 
  2068. {
  2069.     HBITMAP      hSourceBitmap; 
  2070. // Get DIB pointer
  2071. if (! hDIB)
  2072. return NULL;
  2073. LPSTR lpSrcDIB = (LPSTR)GlobalLock(hDIB);
  2074. if (! lpSrcDIB)
  2075. return NULL;
  2076. hSourceBitmap = DIBToDIBSection(lpSrcDIB);
  2077.     // final cleanup 
  2078. GlobalUnlock(hDIB);
  2079.  
  2080.     return hSourceBitmap;
  2081. /**************************************************************************** 
  2082. *     FUNCTION: DIBSectionToDIB 
  2083. *     PURPOSE:  Create DIB from DIBSECTION
  2084. *     PARAMS:   HBITMAP - handle of DIBSECTION, or NULL for failure 
  2085. *     RETURNS:  HBITMAP hBitmap - DIB handle
  2086. ****************************************************************************/ 
  2087. HDIB DIBSectionToDIB(HBITMAP hBitmap)
  2088. {
  2089.     HDC  hDC = NULL, hSourceDC; 
  2090. HBITMAP  hOldSourceBitmap;
  2091. HANDLE  hNewDIB;
  2092.     LPBITMAPINFO lpbmi = NULL; 
  2093. DWORD  dwSize;
  2094. DIBSECTION   ds;
  2095.     DWORD  dwColorNum; 
  2096. // get DIB info
  2097. GetObject(hBitmap, sizeof(DIBSECTION), &ds);
  2098.     dwColorNum = ds.dsBmih.biClrUsed; 
  2099.     if (dwColorNum == 0 && ds.dsBmih.biBitCount <= 8) 
  2100. dwColorNum = 1 << ds.dsBmih.biBitCount;
  2101.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  2102. dwSize = sizeof(BITMAPINFOHEADER) + (dwColorNum * sizeof(RGBQUAD)) + ds.dsBmih.biSizeImage;
  2103. hNewDIB = GlobalAlloc(GHND, dwSize);
  2104. if (! hNewDIB)
  2105. return NULL;
  2106. lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  2107. if (! lpbmi)
  2108. return NULL;
  2109.     lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  2110.     lpbmi->bmiHeader.biWidth = ds.dsBm.bmWidth; 
  2111.     lpbmi->bmiHeader.biHeight = ds.dsBm.bmHeight; 
  2112.     lpbmi->bmiHeader.biPlanes = 1; 
  2113.     lpbmi->bmiHeader.biBitCount = ds.dsBmih.biBitCount; 
  2114.     lpbmi->bmiHeader.biCompression = ds.dsBmih.biCompression; 
  2115.     lpbmi->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage; 
  2116.     lpbmi->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter; 
  2117.     lpbmi->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter; 
  2118.     lpbmi->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed; 
  2119.     lpbmi->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant; 
  2120. // get DC for operation
  2121. hDC = GetDC( NULL ); 
  2122.  
  2123. // get DIB bits
  2124.     if (! GetDIBits(hDC,
  2125.                     hBitmap,
  2126.                     0L,
  2127.                     (DWORD)ds.dsBm.bmHeight,
  2128.                     (LPSTR)lpbmi + (WORD)lpbmi->bmiHeader.biSize + (dwColorNum*sizeof(RGBQUAD)),
  2129.                     (LPBITMAPINFO)lpbmi, 
  2130. (DWORD)DIB_RGB_COLORS))
  2131. {
  2132.          GlobalUnlock(hNewDIB);
  2133.          ReleaseDC(NULL,hDC);
  2134.          return NULL;
  2135.     }
  2136. // memory DC
  2137.     hSourceDC = CreateCompatibleDC( hDC ); 
  2138.     // Select DIBSections into DCs 
  2139.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hBitmap ); 
  2140.  
  2141.     // Fill in the color table from DIBSection
  2142.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  2143.         GetDIBColorTable( hSourceDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  2144.  
  2145.     // Clean up and delete the DCs 
  2146.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  2147.     DeleteDC( hSourceDC ); 
  2148.     ReleaseDC( NULL, hDC ); 
  2149. GlobalUnlock(hNewDIB);
  2150.  
  2151.     return hNewDIB; 
  2152. }
  2153. /************************************************************************* 
  2154.  * 
  2155.  * CopyScreenToBitmap() 
  2156.  * 
  2157.  * Parameter: 
  2158.  * 
  2159.  * LPRECT lpRect    - specifies the window 
  2160.  * 
  2161.  * Return Value: 
  2162.  * 
  2163.  * HDIB             - identifies the device-dependent bitmap 
  2164.  * 
  2165.  * Description: 
  2166.  * 
  2167.  * This function copies the specified part of the screen to a device- 
  2168.  * dependent bitmap. 
  2169.  * 
  2170.  * 
  2171.  ************************************************************************/ 
  2172. HBITMAP CopyScreenToBitmap(LPRECT lpRect) 
  2173.     HDC         hScrDC, hMemDC;         // screen DC and memory DC 
  2174.     HBITMAP     hBitmap, hOldBitmap;    // handles to deice-dependent bitmaps 
  2175.     int         nX, nY, nX2, nY2;       // coordinates of rectangle to grab 
  2176.     int         nWidth, nHeight;        // DIB width and height 
  2177.     int         xScrn, yScrn;           // screen resolution 
  2178.  
  2179.     // check for an empty rectangle 
  2180.  
  2181.     if (IsRectEmpty(lpRect)) 
  2182.       return NULL; 
  2183.  
  2184.     // create a DC for the screen and create 
  2185.     // a memory DC compatible to screen DC 
  2186.      
  2187.     hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
  2188.     hMemDC = CreateCompatibleDC(hScrDC); 
  2189.  
  2190.     // get points of rectangle to grab 
  2191.  
  2192.     nX = lpRect->left; 
  2193.     nY = lpRect->top; 
  2194.     nX2 = lpRect->right; 
  2195.     nY2 = lpRect->bottom; 
  2196.  
  2197.     // get screen resolution 
  2198.  
  2199.     xScrn = GetDeviceCaps(hScrDC, HORZRES); 
  2200.     yScrn = GetDeviceCaps(hScrDC, VERTRES); 
  2201.  
  2202.     //make sure bitmap rectangle is visible 
  2203.  
  2204.     if (nX < 0) 
  2205.         nX = 0; 
  2206.     if (nY < 0) 
  2207.         nY = 0; 
  2208.     if (nX2 > xScrn) 
  2209.         nX2 = xScrn; 
  2210.     if (nY2 > yScrn) 
  2211.         nY2 = yScrn; 
  2212.  
  2213.     nWidth = nX2 - nX; 
  2214.     nHeight = nY2 - nY; 
  2215.  
  2216.     // create a bitmap compatible with the screen DC 
  2217.     hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); 
  2218.  
  2219.     // select new bitmap into memory DC 
  2220.     hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); 
  2221.  
  2222.     // bitblt screen DC to memory DC 
  2223.     BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); 
  2224.  
  2225.     // select old bitmap back into memory DC and get handle to 
  2226.     // bitmap of the screen 
  2227.      
  2228.     hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); 
  2229.  
  2230.     // clean up 
  2231.  
  2232.     DeleteDC(hScrDC); 
  2233.     DeleteDC(hMemDC); 
  2234.  
  2235.     // return handle to the bitmap 
  2236.  
  2237.     return hBitmap; 
  2238. /************************************************************************* 
  2239.  * 
  2240.  * CopyWindowToBitmap() 
  2241.  * 
  2242.  * Parameters: 
  2243.  * 
  2244.  * HWND hWnd        - specifies the window 
  2245.  * 
  2246.  * WORD fPrintArea  - specifies the window area to copy into the device- 
  2247.  *                    dependent bitmap 
  2248.  * 
  2249.  * Return Value: 
  2250.  * 
  2251.  * HDIB         - identifies the device-dependent bitmap 
  2252.  * 
  2253.  * Description: 
  2254.  * 
  2255.  * This function copies the specified part(s) of the window to a device- 
  2256.  * dependent bitmap. 
  2257.  * 
  2258.  * 
  2259.  ************************************************************************/ 
  2260. HBITMAP CopyWindowToBitmap(HWND hWnd, WORD fPrintArea) 
  2261.     HBITMAP     hBitmap = NULL;  // handle to device-dependent bitmap 
  2262.  
  2263.     // check for a valid window handle 
  2264.  
  2265.     if (!hWnd) 
  2266.         return NULL; 
  2267.  
  2268.     switch (fPrintArea) 
  2269.     { 
  2270.         case PW_WINDOW: // copy entire window 
  2271.         { 
  2272.             RECT    rectWnd; 
  2273.  
  2274.             // get the window rectangle 
  2275.  
  2276.             GetWindowRect(hWnd, &rectWnd); 
  2277.  
  2278.             // get the bitmap of that window by calling 
  2279.             // CopyScreenToBitmap and passing it the window rect 
  2280.         
  2281.             hBitmap = CopyScreenToBitmap(&rectWnd); 
  2282.             break; 
  2283.         } 
  2284.          
  2285.  
  2286.         case PW_CLIENT: // copy client area 
  2287.         { 
  2288.             RECT rectClient; 
  2289.             POINT pt1, pt2; 
  2290.  
  2291.             // get client dimensions 
  2292.  
  2293.             GetClientRect(hWnd, &rectClient); 
  2294.  
  2295.             // convert client coords to screen coords 
  2296.  
  2297.             pt1.x = rectClient.left; 
  2298.             pt1.y = rectClient.top; 
  2299.             pt2.x = rectClient.right; 
  2300.             pt2.y = rectClient.bottom; 
  2301.             ClientToScreen(hWnd, &pt1); 
  2302.             ClientToScreen(hWnd, &pt2); 
  2303.             rectClient.left = pt1.x; 
  2304.             rectClient.top = pt1.y; 
  2305.             rectClient.right = pt2.x; 
  2306.             rectClient.bottom = pt2.y; 
  2307.  
  2308.             // get the bitmap of the client area by calling 
  2309.             // CopyScreenToBitmap and passing it the client rect 
  2310.              
  2311.             hBitmap = CopyScreenToBitmap(&rectClient); 
  2312.             break; 
  2313.         } 
  2314.      
  2315.         default:    // invalid print area 
  2316.             return NULL; 
  2317.     } 
  2318.  
  2319.     // return handle to the bitmap 
  2320.  
  2321.    return hBitmap; 
  2322.  
  2323.  
  2324. /************************************************************************* 
  2325.  * 
  2326.  * CopyClientRectToBitmap() 
  2327.  * 
  2328.  * Parameters: 
  2329.  * 
  2330.  * HWND hWnd        - specifies the window 
  2331.  * 
  2332.  * LPRECT lpRect    - specifies the client area rect to copy into the device- 
  2333.  *                    independent bitmap 
  2334.  * 
  2335.  * Return Value: 
  2336.  * 
  2337.  * HDIB             - identifies the device-independent bitmap 
  2338.  * 
  2339.  * Description: 
  2340.  * 
  2341.  * This function copies the specified part(s) of the window client to a 
  2342.  * device-independent bitmap. 
  2343.  * 
  2344.  ************************************************************************/ 
  2345. HBITMAP CopyClientRectToBitmap(HWND hWnd, LPRECT lpRect) 
  2346.    HBITMAP     hBitmap = NULL;  // handle to DIB 
  2347.  
  2348.    // check for a valid window handle 
  2349.  
  2350.     if (!hWnd) 
  2351.         return NULL; 
  2352.  
  2353.     POINT   pt1, pt2; 
  2354.     // convert client coords to screen coords 
  2355.     pt1.x = lpRect->left; 
  2356.     pt1.y = lpRect->top; 
  2357.     pt2.x = lpRect->right; 
  2358.     pt2.y = lpRect->bottom; 
  2359.     ClientToScreen(hWnd, &pt1); 
  2360.     ClientToScreen(hWnd, &pt2); 
  2361.     lpRect->left = pt1.x; 
  2362.     lpRect->top = pt1.y; 
  2363.     lpRect->right = pt2.x; 
  2364.     lpRect->bottom = pt2.y; 
  2365.     // get the DIB of the client area by calling 
  2366.     // CopyScreenToDIB and passing it the client rect 
  2367.     hBitmap = CopyScreenToBitmap(lpRect); 
  2368.  
  2369. // restore lpRect
  2370.     pt1.x = lpRect->left; 
  2371.     pt1.y = lpRect->top; 
  2372.     pt2.x = lpRect->right; 
  2373.     pt2.y = lpRect->bottom; 
  2374.     ScreenToClient(hWnd, &pt1); 
  2375.     ScreenToClient(hWnd, &pt2); 
  2376.     lpRect->left = pt1.x; 
  2377.     lpRect->top = pt1.y; 
  2378.     lpRect->right = pt2.x; 
  2379.     lpRect->bottom = pt2.y; 
  2380. // return the handle to the DIB 
  2381.  
  2382.    return hBitmap; 
  2383.  
  2384. /************************************************************************* 
  2385.  * 
  2386.  * CopyScreenToDIB() 
  2387.  * 
  2388.  * Parameter: 
  2389.  * 
  2390.  * LPRECT lpRect    - specifies the window 
  2391.  * 
  2392.  * Return Value: 
  2393.  * 
  2394.  * HDIB             - identifies the device-independent bitmap 
  2395.  * 
  2396.  * Description: 
  2397.  * 
  2398.  * This function copies the specified part of the screen to a device- 
  2399.  * independent bitmap. 
  2400.  * 
  2401.  ************************************************************************/ 
  2402. HDIB CopyScreenToDIB(LPRECT lpRect) 
  2403.     HBITMAP     hBitmap;        // handle to device-dependent bitmap 
  2404.     HPALETTE    hPalette;       // handle to palette 
  2405.     HDIB        hDIB = NULL;    // handle to DIB 
  2406.  
  2407.     // get the device-dependent bitmap in lpRect by calling 
  2408.     //  CopyScreenToBitmap and passing it the rectangle to grab 
  2409.  
  2410.     hBitmap = CopyScreenToBitmap(lpRect); 
  2411.  
  2412.     // check for a valid bitmap handle 
  2413.  
  2414.     if (!hBitmap) 
  2415.       return NULL; 
  2416.  
  2417.     // get the current palette 
  2418.  
  2419.     hPalette = GetSystemPalette(); 
  2420.  
  2421.     // convert the bitmap to a DIB 
  2422.  
  2423.     hDIB = BitmapToDIB(hBitmap, hPalette); 
  2424.  
  2425.     // clean up  
  2426.  
  2427.     DeleteObject(hPalette); 
  2428.     DeleteObject(hBitmap); 
  2429.  
  2430.     // return handle to the packed-DIB 
  2431.     return hDIB; 
  2432.  
  2433. /************************************************************************* 
  2434.  * 
  2435.  * CopyWindowToDIB() 
  2436.  * 
  2437.  * Parameters: 
  2438.  * 
  2439.  * HWND hWnd        - specifies the window 
  2440.  * 
  2441.  * WORD fPrintArea  - specifies the window area to copy into the device- 
  2442.  *                    independent bitmap 
  2443.  * 
  2444.  * Return Value: 
  2445.  * 
  2446.  * HDIB             - identifies the device-independent bitmap 
  2447.  * 
  2448.  * Description: 
  2449.  * 
  2450.  * This function copies the specified part(s) of the window to a device- 
  2451.  * independent bitmap. 
  2452.  * 
  2453.  ************************************************************************/ 
  2454. HDIB CopyWindowToDIB(HWND hWnd, WORD fPrintArea) 
  2455.    HDIB     hDIB = NULL;  // handle to DIB 
  2456.  
  2457.    // check for a valid window handle 
  2458.  
  2459.     if (!hWnd) 
  2460.         return NULL; 
  2461.  
  2462.     switch (fPrintArea) 
  2463.     { 
  2464.         case PW_WINDOW: // copy entire window 
  2465.         { 
  2466.             RECT    rectWnd; 
  2467.  
  2468.             // get the window rectangle 
  2469.  
  2470.             GetWindowRect(hWnd, &rectWnd); 
  2471.  
  2472.             // get the DIB of the window by calling 
  2473.             // CopyScreenToDIB and passing it the window rect 
  2474.              
  2475.             hDIB = CopyScreenToDIB(&rectWnd); 
  2476.             break; 
  2477.         } 
  2478.        
  2479.         case PW_CLIENT: // copy client area 
  2480.         { 
  2481.             RECT    rectClient; 
  2482.             POINT   pt1, pt2; 
  2483.  
  2484.             // get the client area dimensions 
  2485.  
  2486.             GetClientRect(hWnd, &rectClient); 
  2487.  
  2488.             // convert client coords to screen coords 
  2489.  
  2490.             pt1.x = rectClient.left; 
  2491.             pt1.y = rectClient.top; 
  2492.             pt2.x = rectClient.right; 
  2493.             pt2.y = rectClient.bottom; 
  2494.             ClientToScreen(hWnd, &pt1); 
  2495.             ClientToScreen(hWnd, &pt2); 
  2496.             rectClient.left = pt1.x; 
  2497.             rectClient.top = pt1.y; 
  2498.             rectClient.right = pt2.x; 
  2499.             rectClient.bottom = pt2.y; 
  2500.  
  2501.             // get the DIB of the client area by calling 
  2502.             // CopyScreenToDIB and passing it the client rect 
  2503.  
  2504.             hDIB = CopyScreenToDIB(&rectClient); 
  2505.             break; 
  2506.         } 
  2507.        
  2508.         default:    // invalid print area 
  2509.             return NULL; 
  2510.     } 
  2511.  
  2512.    // return the handle to the DIB 
  2513.  
  2514.    return hDIB; 
  2515.  
  2516. /************************************************************************* 
  2517.  * 
  2518.  * CopyClientRectToDIB() 
  2519.  * 
  2520.  * Parameters: 
  2521.  * 
  2522.  * HWND hWnd        - specifies the window 
  2523.  * 
  2524.  * LPRECT lpRect    - specifies the client area rect to copy into the device- 
  2525.  *                    independent bitmap 
  2526.  * 
  2527.  * Return Value: 
  2528.  * 
  2529.  * HDIB             - identifies the device-independent bitmap 
  2530.  * 
  2531.  * Description: 
  2532.  * 
  2533.  * This function copies the specified part(s) of the window client to a 
  2534.  * device-independent bitmap. 
  2535.  * 
  2536.  ************************************************************************/ 
  2537. HDIB CopyClientRectToDIB(HWND hWnd, LPRECT lpRect) 
  2538.    HDIB     hDIB = NULL;  // handle to DIB 
  2539.  
  2540.    // check for a valid window handle 
  2541.  
  2542.     if (!hWnd) 
  2543.         return NULL; 
  2544.  
  2545.     POINT   pt1, pt2; 
  2546.     // convert client coords to screen coords 
  2547.     pt1.x = lpRect->left; 
  2548.     pt1.y = lpRect->top; 
  2549.     pt2.x = lpRect->right; 
  2550.     pt2.y = lpRect->bottom; 
  2551.     ClientToScreen(hWnd, &pt1); 
  2552.     ClientToScreen(hWnd, &pt2); 
  2553.     lpRect->left = pt1.x; 
  2554.     lpRect->top = pt1.y; 
  2555.     lpRect->right = pt2.x; 
  2556.     lpRect->bottom = pt2.y; 
  2557.     // get the DIB of the client area by calling 
  2558.     // CopyScreenToDIB and passing it the client rect 
  2559.     hDIB = CopyScreenToDIB(lpRect); 
  2560.  
  2561. // restore lpRect
  2562.     pt1.x = lpRect->left; 
  2563.     pt1.y = lpRect->top; 
  2564.     pt2.x = lpRect->right; 
  2565.     pt2.y = lpRect->bottom; 
  2566.     ScreenToClient(hWnd, &pt1); 
  2567.     ScreenToClient(hWnd, &pt2); 
  2568.     lpRect->left = pt1.x; 
  2569.     lpRect->top = pt1.y; 
  2570.     lpRect->right = pt2.x; 
  2571.     lpRect->bottom = pt2.y; 
  2572. // return the handle to the DIB 
  2573.  
  2574.    return hDIB; 
  2575.  
  2576. /************************************************************************* 
  2577.  * 
  2578.  * PaintDIB() 
  2579.  * 
  2580.  * Parameters: 
  2581.  * 
  2582.  * HDC hDC          - DC to do output to 
  2583.  * 
  2584.  * LPRECT lpDCRect  - rectangle on DC to do output to 
  2585.  * 
  2586.  * HDIB hDIB        - handle to global memory with a DIB spec 
  2587.  *                    in it followed by the DIB bits 
  2588.  * 
  2589.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 
  2590.  *
  2591.  * HPALETTE hPal    - Palette used to diaplsy DIB, if is NULL, 
  2592.  *   use DIB palette to display
  2593.  *
  2594.  * DWORD dwRop      - ROP mode to display DIB
  2595.  * 
  2596.  * Return Value: 
  2597.  * 
  2598.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
  2599.  * 
  2600.  * Description: 
  2601.  *   Painting routine for a DIB.  Calls StretchDIBits() or 
  2602.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is 
  2603.  *   output to the specified DC, at the coordinates given 
  2604.  *   in lpDCRect.  The area of the DIB to be output is 
  2605.  *   given by lpDIBRect. 
  2606.  * 
  2607.  * NOTE: This function always selects the palette as background. Before 
  2608.  * calling this function, be sure your palette is selected to desired 
  2609.  * priority (foreground or background). 
  2610.  * 
  2611.  * 
  2612.  ************************************************************************/ 
  2613. BOOL PaintDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, 
  2614.         HPALETTE hPal, DWORD dwRop)
  2615.     LPSTR        lpDIBHdr;           // Pointer to BITMAPINFOHEADER 
  2616.     LPSTR        lpDIBBits;          // Pointer to DIB bits 
  2617.     BOOL         bSuccess=FALSE;     // Success/fail flag 
  2618.     HPALETTE     hOldPal=NULL;       // Previous palette 
  2619.  
  2620.     // Check for valid DIB handle 
  2621.  
  2622.     if (!hDIB) 
  2623.         return FALSE; 
  2624. // get DIB bitcount and device bits/pixel
  2625. int nDeviceBitsPixel = GetDeviceCaps(hDC, BITSPIXEL);
  2626. int nDIBBitsPixel = DIBBitCount(hDIB);
  2627. // if device can not display DIB color, dithering DIB
  2628. if (nDIBBitsPixel > 8 && nDeviceBitsPixel <= 8)
  2629. return DitherDisplayDIB(hDC, lpDCRect, hDIB, lpDIBRect, dwRop);
  2630.  
  2631.     // Lock down the DIB, and get a pointer to the beginning of the bit 
  2632.     // buffer 
  2633.      
  2634.     lpDIBHdr  = (LPSTR)GlobalLock(hDIB); 
  2635.     lpDIBBits = FindDIBBits(lpDIBHdr); 
  2636.  
  2637. // if no palette provided, create one from DIB
  2638.     if (! hPal) 
  2639. hPal = CreateDIBPalette(lpDIBHdr);
  2640.     // Select and realize our palette as background 
  2641.  
  2642.     if (hPal) 
  2643.     { 
  2644.         hOldPal = SelectPalette(hDC, hPal, TRUE); 
  2645.         RealizePalette(hDC); 
  2646.     } 
  2647.  
  2648.     // Make sure to use the stretching mode best for color pictures 
  2649.  
  2650.     SetStretchBltMode(hDC, COLORONCOLOR); 
  2651.  
  2652.     // Call StretchDIBits() with dwRop
  2653.  
  2654. bSuccess = StretchDIBits(hDC, 
  2655.  lpDCRect->left, 
  2656.  lpDCRect->top, 
  2657.  RECTWIDTH(lpDCRect), 
  2658.  RECTHEIGHT(lpDCRect), 
  2659.  lpDIBRect->left, 
  2660.              (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), 
  2661.  RECTWIDTH(lpDIBRect), 
  2662.  RECTHEIGHT(lpDIBRect), 
  2663.  lpDIBBits, 
  2664.  (LPBITMAPINFO)lpDIBHdr, 
  2665.  DIB_RGB_COLORS, 
  2666.  SRCCOPY); 
  2667.  
  2668.     // Unlock the memory block 
  2669.  
  2670.     GlobalUnlock(hDIB); 
  2671.  
  2672.     // Reselect old palette 
  2673.  
  2674.     if (hOldPal) 
  2675. SelectPalette(hDC, hOldPal, FALSE); 
  2676.  
  2677.     // Return with success/fail flag 
  2678.     return bSuccess; 
  2679. /************************************************************************* 
  2680.  * 
  2681.  * DitherDisplayDIB() 
  2682.  * 
  2683.  * Parameters: 
  2684.  * 
  2685.  * HDC hDC          - DC to do output to 
  2686.  * 
  2687.  * LPRECT lpDCRect  - rectangle on DC to do output to 
  2688.  * 
  2689.  * HDIB hDIB        - handle to global memory with a DIB spec 
  2690.  *                    in it followed by the DIB bits 
  2691.  * 
  2692.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 
  2693.  *
  2694.  * HPALETTE hPal    - Palette used to diaplsy DIB, if is NULL, 
  2695.  *   use DIB palette to display
  2696.  *
  2697.  * DWORD dwRop      - ROP mode to display DIB
  2698.  * 
  2699.  * Return Value: 
  2700.  * 
  2701.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
  2702.  * 
  2703.  * Description: 
  2704.  *   Painting routine with dithering, can display accuraly a DIB with
  2705.  *   more colors than the display device can support.
  2706.  * 
  2707.  ************************************************************************/ 
  2708. BOOL DitherDisplayDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, 
  2709.         DWORD dwRop)
  2710.     LPSTR        lpDIBHdr;           // Pointer to BITMAPINFOHEADER 
  2711.     LPSTR        lpDIBBits;          // Pointer to DIB bits 
  2712.     BOOL          bSuccess=FALSE;     // Success/fail flag 
  2713.     HPALETTE      hPal=NULL;   // used palette 
  2714.     HPALETTE      hOldPal=NULL;       // Previous palette 
  2715.  
  2716.     // Check for valid DIB handle 
  2717.  
  2718.     if (!hDIB) 
  2719.         return FALSE; 
  2720. // create dithered DIB to display
  2721. HDIB hDIBDisplay = CreateDither8BppDIB(hDIB);
  2722.     // Lock down the DIB, and get a pointer to the beginning of the bit 
  2723.     // buffer 
  2724.      
  2725.     lpDIBHdr  = (LPSTR)GlobalLock(hDIBDisplay); 
  2726.     lpDIBBits = FindDIBBits(lpDIBHdr); 
  2727.  
  2728. // create palette from DIB
  2729. hPal = CreateDIBPalette(lpDIBHdr);
  2730.     // Select and realize our palette as background 
  2731.     if (hPal) 
  2732.     { 
  2733. hOldPal = SelectPalette(hDC, hPal, TRUE); 
  2734.         RealizePalette(hDC); 
  2735.     } 
  2736.     // Make sure to use the stretching mode best for color pictures 
  2737.  
  2738.     SetStretchBltMode(hDC, COLORONCOLOR); 
  2739.  
  2740.     // call StretchDIBits() anyway with dwRop
  2741.  
  2742. bSuccess = StretchDIBits(hDC, 
  2743.  lpDCRect->left, 
  2744.  lpDCRect->top, 
  2745.  RECTWIDTH(lpDCRect), 
  2746.  RECTHEIGHT(lpDCRect), 
  2747.  lpDIBRect->left, 
  2748.              (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), 
  2749.  RECTWIDTH(lpDIBRect), 
  2750.  RECTHEIGHT(lpDIBRect), 
  2751.  lpDIBBits, 
  2752.  (LPBITMAPINFO)lpDIBHdr, 
  2753.  DIB_RGB_COLORS, 
  2754.  SRCCOPY); 
  2755.     // Unlock and free the memory block 
  2756.  
  2757.     GlobalUnlock(hDIBDisplay); 
  2758. GlobalFree(hDIBDisplay); 
  2759.     // Reselect old palette 
  2760.  
  2761.     if (hOldPal) 
  2762. SelectPalette(hDC, hOldPal, FALSE); 
  2763.  
  2764.     // Return with success/fail flag 
  2765.     return bSuccess; 
  2766. /************************************************************************* 
  2767.  * 
  2768.  * PaintBitmap() 
  2769.  * 
  2770.  * Parameters: 
  2771.  * 
  2772.  * HDC hDC          - DC to do output to 
  2773.  * 
  2774.  * LPRECT lpDCRect  - rectangle on DC to do output to 
  2775.  * 
  2776.  * HBITMAP hDDB     - handle to device-dependent bitmap (DDB) 
  2777.  * 
  2778.  * LPRECT lpDDBRect - rectangle of DDB to output into lpDCRect 
  2779.  * 
  2780.  * HPALETTE hPalette - handle to the palette to use with hDDB 
  2781.  * 
  2782.  * Return Value: 
  2783.  * 
  2784.  * BOOL             - TRUE if bitmap was drawn, FLASE otherwise 
  2785.  * 
  2786.  * Description: 
  2787.  * 
  2788.  * Painting routine for a DDB.  Calls BitBlt() or 
  2789.  * StretchBlt() to paint the DDB.  The DDB is 
  2790.  * output to the specified DC, at the coordinates given 
  2791.  * in lpDCRect.  The area of the DDB to be output is 
  2792.  * given by lpDDBRect.  The specified palette is used. 
  2793.  * 
  2794.  * NOTE: This function always selects the palette as background. Before 
  2795.  * calling this function, be sure your palette is selected to desired 
  2796.  * priority (foreground or background). 
  2797.  * 
  2798.  ************************************************************************/ 
  2799. BOOL PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB,  LPRECT lpDDBRect,  
  2800.         HPALETTE hPal, DWORD dwRop)
  2801.     HDC         hMemDC;            // Handle to memory DC 
  2802.     HBITMAP     hOldBitmap;        // Handle to previous bitmap 
  2803.     HPALETTE    hOldPal1 = NULL;   // Handle to previous palette 
  2804.     HPALETTE    hOldPal2 = NULL;   // Handle to previous palette 
  2805.     BOOL        bSuccess = FALSE;  // Success/fail flag 
  2806.  
  2807.     // Create a memory DC 
  2808.  
  2809.     hMemDC = CreateCompatibleDC (hDC); 
  2810.  
  2811.     // If this failed, return FALSE 
  2812.  
  2813.     if (!hMemDC) 
  2814.         return FALSE; 
  2815.  
  2816.     // If we have a palette, select and realize it 
  2817.  
  2818.     if (hPal) 
  2819.     { 
  2820.         hOldPal1 = SelectPalette(hMemDC, hPal, TRUE); 
  2821.         hOldPal2 = SelectPalette(hDC, hPal, TRUE); 
  2822.         RealizePalette(hDC); 
  2823.     } 
  2824.  
  2825.     // Select bitmap into the memory DC 
  2826.  
  2827.     hOldBitmap = (HBITMAP)SelectObject (hMemDC, hDDB); 
  2828.  
  2829.     // Make sure to use the stretching mode best for color pictures 
  2830.  
  2831.     SetStretchBltMode (hDC, COLORONCOLOR); 
  2832.  
  2833.     // Determine whether to call StretchBlt() or BitBlt() 
  2834.     if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDDBRect)) && 
  2835.             (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect))) 
  2836.         bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top, 
  2837.                 lpDCRect->right - lpDCRect->left, 
  2838.                 lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left, 
  2839.                 lpDDBRect->top, dwRop); 
  2840.     else 
  2841.         bSuccess = StretchBlt(hDC, lpDCRect->left,  lpDCRect->top,  
  2842.                 lpDCRect->right - lpDCRect->left, 
  2843.                 lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,  
  2844.                 lpDDBRect->top,  lpDDBRect->right - lpDDBRect->left, 
  2845.                 lpDDBRect->bottom - lpDDBRect->top, dwRop); 
  2846.  
  2847.     // Clean up 
  2848.  
  2849.     SelectObject(hMemDC, hOldBitmap); 
  2850.  
  2851.     if (hOldPal1) 
  2852.         SelectPalette (hMemDC, hOldPal1, FALSE); 
  2853.  
  2854.     if (hOldPal2) 
  2855.         SelectPalette (hDC, hOldPal2, FALSE); 
  2856.  
  2857.     DeleteDC (hMemDC); 
  2858.  
  2859.     // Return with success/fail flag 
  2860.  
  2861.     return bSuccess; 
  2862. /************************************************************************* 
  2863.  * 
  2864.  * DisplayPalette () 
  2865.  * 
  2866.  * Parameter: 
  2867.  * 
  2868.  * HDC hDC          - handle of device context to display palette
  2869.  * LPRECT lpRect      - rect range to show palette
  2870.  * HPALETTE hPal     - handle of palette to display
  2871.  * 
  2872.  * Return Value: 
  2873.  * 
  2874.  * BOOL            - TRUE, if success, else FALSE
  2875.  * 
  2876.  * Description: 
  2877.  * 
  2878.  * This function displays palette on the specified rectangle in a device context 
  2879.  * 
  2880.  ************************************************************************/ 
  2881. BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal)
  2882. {
  2883. if (! hPal)
  2884. return FALSE;
  2885. int nEntries;
  2886. PALETTEENTRY pe[256];
  2887. nEntries = GetPaletteEntries(hPal, 0, 256, pe);
  2888. int nSqr = (int)sqrt((double)nEntries);
  2889. int nWidth = (lpRect->right-lpRect->left)/nSqr;
  2890. int nHeight = (lpRect->bottom-lpRect->top)/nSqr;
  2891. lpRect->right = lpRect->left + nWidth*nSqr;
  2892. lpRect->bottom = lpRect->top + nHeight*nSqr;
  2893. HPALETTE hOldPal = (HPALETTE)SelectPalette(hDC, hPal, FALSE);
  2894. RealizePalette(hDC);
  2895. HBRUSH hBrush, hOldBrush;
  2896. int x, y;
  2897. for (int i=0; i<nEntries; ++i)
  2898. {
  2899. x = i%nSqr;
  2900. y = i/nSqr;
  2901. hBrush = CreateSolidBrush(RGB(pe[i].peRed, pe[i].peGreen, pe[i].peBlue));
  2902. hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
  2903. Rectangle(hDC, 
  2904.       lpRect->left + x*nWidth, 
  2905.   lpRect->top + y*nHeight, 
  2906.   lpRect->left + (x+1)*nWidth, 
  2907.   lpRect->top + (y+1) *nHeight);
  2908. SelectObject(hDC, hOldBrush);
  2909. DeleteObject(hBrush);
  2910. }
  2911. SelectPalette(hDC, hOldPal, FALSE);
  2912. return TRUE;
  2913. }
  2914. /************************************************************************* 
  2915.  * 
  2916.  * CopyPalette () 
  2917.  * 
  2918.  * Parameter: 
  2919.  * 
  2920.  * HPALETTE hPalSrc    - source palette handle
  2921.  * 
  2922.  * Return Value: 
  2923.  * 
  2924.  * HPALETTE          - destination palette handle
  2925.  * 
  2926.  * Description: 
  2927.  * 
  2928.  * This function copys the source palette to a new palette handle 
  2929.  * 
  2930.  ************************************************************************/ 
  2931. HPALETTE CopyPalette(HPALETTE hPalSrc)
  2932. {
  2933.     PLOGPALETTE     plogPal;
  2934.     int             iNumEntries=0;
  2935.     HPALETTE        hPal;
  2936. HANDLE h;
  2937. iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL);
  2938.     if (iNumEntries == 0) 
  2939.         return (HPALETTE) NULL;
  2940. h = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries);
  2941. if (! h)
  2942.         return (HPALETTE) NULL;
  2943. plogPal = (PLOGPALETTE)GlobalLock(h);
  2944.     if (! plogPal) 
  2945.         return (HPALETTE) NULL;
  2946.     plogPal->palVersion = 0x300;
  2947.     plogPal->palNumEntries = (WORD) iNumEntries;
  2948.     GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry);
  2949.     hPal = CreatePalette(plogPal);
  2950.     GlobalUnlock(h);
  2951.     GlobalFree(h);
  2952.     return hPal;
  2953. }
  2954.  
  2955. /************************************************************************* 
  2956.  * 
  2957.  * PalEntriesOnDevice() 
  2958.  * 
  2959.  * Parameter: 
  2960.  * 
  2961.  * HDC hDC          - device context 
  2962.  * 
  2963.  * Return Value: 
  2964.  * 
  2965.  * int              - number of palette entries on device 
  2966.  * 
  2967.  * Description: 
  2968.  * 
  2969.  * This function gets the number of palette entries on the specified device 
  2970.  * 
  2971.  ************************************************************************/ 
  2972. int PalEntriesOnDevice(HDC hDC) 
  2973.     int nColors;  // number of colors 
  2974.  
  2975.     // Find out the number of colors on this device. 
  2976.      
  2977.     nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES))); 
  2978.  
  2979.     assert(nColors); 
  2980.     return nColors; 
  2981.  
  2982.  
  2983. /************************************************************************* 
  2984.  * 
  2985.  * GetSystemPalette() 
  2986.  * 
  2987.  * Parameters: 
  2988.  * 
  2989.  * None 
  2990.  * 
  2991.  * Return Value: 
  2992.  * 
  2993.  * HPALETTE         - handle to a copy of the current system palette 
  2994.  * 
  2995.  * Description: 
  2996.  * 
  2997.  * This function returns a handle to a palette which represents the system 
  2998.  * palette.  The system RGB values are copied into our logical palette using 
  2999.  * the GetSystemPaletteEntries function.   
  3000.  * 
  3001.  ************************************************************************/ 
  3002. HPALETTE GetSystemPalette(void) 
  3003.     HDC hDC;                // handle to a DC 
  3004.     static HPALETTE hPal = NULL;   // handle to a palette 
  3005.     HANDLE hLogPal;         // handle to a logical palette 
  3006.     LPLOGPALETTE lpLogPal;  // pointer to a logical palette 
  3007.     int nColors;            // number of colors 
  3008.  
  3009.     // Find out how many palette entries we want. 
  3010.  
  3011.     hDC = GetDC(NULL); 
  3012.  
  3013.     if (!hDC) 
  3014.         return NULL; 
  3015.  
  3016.     nColors = PalEntriesOnDevice(hDC);   // Number of palette entries 
  3017.  
  3018.     // Allocate room for the palette and lock it. 
  3019.  
  3020.     hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * 
  3021.             sizeof(PALETTEENTRY)); 
  3022.  
  3023.     // if we didn't get a logical palette, return NULL 
  3024.  
  3025.     if (!hLogPal) 
  3026.         return NULL; 
  3027.  
  3028.     // get a pointer to the logical palette 
  3029.  
  3030.     lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
  3031.  
  3032.     // set some important fields 
  3033.  
  3034.     lpLogPal->palVersion = PALVERSION; 
  3035.     lpLogPal->palNumEntries = nColors; 
  3036.  
  3037.     // Copy the current system palette into our logical palette 
  3038.  
  3039.     GetSystemPaletteEntries(hDC, 0, nColors, 
  3040.             (LPPALETTEENTRY)(lpLogPal->palPalEntry)); 
  3041.  
  3042.     // Go ahead and create the palette.  Once it's created, 
  3043.     // we no longer need the LOGPALETTE, so free it.     
  3044.  
  3045.     hPal = CreatePalette(lpLogPal); 
  3046.  
  3047.     // clean up 
  3048.  
  3049.     GlobalUnlock(hLogPal); 
  3050.     GlobalFree(hLogPal); 
  3051.     ReleaseDC(NULL, hDC); 
  3052.  
  3053.     return hPal; 
  3054.  
  3055. /************************************************************************* 
  3056.  * 
  3057.  * CreateIdentifyPalette () 
  3058.  * 
  3059.  * Parameter: 
  3060.  * 
  3061.  * HPALETTE hPalSrc    - source palette handle
  3062.  * 
  3063.  * Return Value: 
  3064.  * 
  3065.  * HPALETTE          - destination identify palette handle
  3066.  * 
  3067.  * Description: 
  3068.  * 
  3069.  * This function creates an identify palette from the source palette handle 
  3070.  * 
  3071.  ************************************************************************/ 
  3072. HPALETTE CreateIdentifyPalette(HPALETTE hPalSrc)
  3073. {
  3074.     BOOL bResult = FALSE;
  3075.     int i, iSysColors, iPalEntries;
  3076.     HPALETTE hPalette, hpalOld;
  3077. if (! hPalSrc)
  3078. return NULL;
  3079. // create a new palette equal to input
  3080. hPalette = CopyPalette(hPalSrc);
  3081.     // Get a screen DC to work with
  3082.     HDC hdcScreen = GetDC(NULL);
  3083.     ASSERT(hdcScreen);
  3084.     // Make sure we are on a palettized device
  3085.     if (!(GetDeviceCaps(hdcScreen, RASTERCAPS) & RC_PALETTE)) 
  3086. {
  3087.         TRACE("Not a palettized device");
  3088.         goto abort;
  3089.     }
  3090.     // Get the number of system colors and the number of palette entries
  3091.     // Note that on a palletized device the number of colors is the
  3092.     // number of guaranteed colors.  I.e. the number of reserved system colors
  3093.     iSysColors = GetDeviceCaps(hdcScreen, NUMCOLORS);
  3094.     iPalEntries = GetDeviceCaps(hdcScreen, SIZEPALETTE);
  3095.     // if there are more than 256 colors we are wasting our time
  3096.     if (iSysColors > 256) goto abort;
  3097.     // Now we force the palette manager to reset its tables so that
  3098.     // the next palette to be realized will get its colors in the order they are 
  3099.     // in the logical palette. This is done by changing the number of
  3100.     // reserved colors.
  3101.     SetSystemPaletteUse(hdcScreen, SYSPAL_NOSTATIC);
  3102.     SetSystemPaletteUse(hdcScreen, SYSPAL_STATIC);
  3103.     // Select our palette into the screen DC and realize it so that
  3104.     // its colors will be entered into the free slots in the physical palette
  3105.     hpalOld = ::SelectPalette(hdcScreen,
  3106.                               hPalette, // our hpal
  3107.                               FALSE);
  3108.     ::RealizePalette(hdcScreen);
  3109.     // Now replace the old palette (but don't realize it)
  3110.     ::SelectPalette(hdcScreen, hpalOld, FALSE);
  3111.     // The physical palette now has our colors set in place and its own
  3112.     // reserved colors at either end.  We can grab the lot now
  3113.     PALETTEENTRY pe[256];
  3114.     GetSystemPaletteEntries(hdcScreen, 
  3115.                             0,
  3116.                             iPalEntries,
  3117.                             pe);
  3118.     // Set the PC_NOCOLLAPSE flag for each of our colors so that GDI
  3119.     // won't merge them together.  Be careful not to set PC_NOCOLLAPSE for the 
  3120.     // sys color entries or we'll get multpile copies of these colors in
  3121.     // the palette when we realize it.
  3122.     for (i = 0; i < iSysColors/2; i++) {
  3123.         pe[i].peFlags = 0;
  3124.     }
  3125.     for (; i < iPalEntries-iSysColors/2; i++) {
  3126.         pe[i].peFlags = PC_NOCOLLAPSE;
  3127.     }
  3128.     for (; i < iPalEntries; i++) {
  3129.         pe[i].peFlags = 0;
  3130.     }
  3131.     // Resize the palette in case it was smaller
  3132.     ResizePalette(hPalette, iPalEntries);
  3133.     // Update the palette entries with what is now in the physical palette
  3134.     SetPaletteEntries(hPalette, 0, iPalEntries, pe);
  3135.     bResult = TRUE;
  3136. abort:
  3137.     ::ReleaseDC(NULL, hdcScreen);
  3138.     return bResult ? hPalette : NULL;
  3139. }
  3140. /************************************************************************* 
  3141.  * 
  3142.  * MapDIBColorsToPalette () 
  3143.  * 
  3144.  * Parameter: 
  3145.  * 
  3146.  * HDIB hDIB     - DIB handle
  3147.  * HPALETTE hPalette    - given palette handle
  3148.  * 
  3149.  * Return Value: 
  3150.  * 
  3151.  * HPALETTE          - destination identify palette handle
  3152.  * 
  3153.  * Description: 
  3154.  * 
  3155.  * This function Map the colors in a DIB to a given palette.
  3156.  * 
  3157.  ************************************************************************/ 
  3158. BOOL MapDIBColorsToPalette(HDIB hDIB, HPALETTE hPalette)
  3159. {
  3160.     if (! hDIB)
  3161.         return FALSE;
  3162.     if (! hPalette)
  3163.         return FALSE;
  3164.     LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  3165.     if (! lpbi)
  3166.         return FALSE;
  3167.     LPRGBQUAD pctThis = (LPRGBQUAD)((LPSTR)lpbi + lpbi->biSize);
  3168.     // build an index translation table to map this DIBs colors
  3169.     // to those of the reference DIB
  3170.     BYTE imap[256];
  3171.     for (int i = 0; i < 256; i++) 
  3172. {
  3173.         imap[i] = (BYTE)GetNearestPaletteIndex(hPalette, 
  3174. RGB(pctThis->rgbRed,
  3175. pctThis->rgbGreen,
  3176. pctThis->rgbBlue));
  3177.         pctThis++;
  3178.     }
  3179.     // now map the DIB bits
  3180.     LPSTR pBits = (LPSTR)lpbi + lpbi->biSize + PaletteSize((LPSTR)lpbi);
  3181.     int iSize = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) * lpbi->biHeight;
  3182.     while (iSize--) 
  3183. {
  3184.         *pBits = imap[*pBits];
  3185.         pBits++;
  3186.     }
  3187.     // Now reset the DIB color table so that its RGB values match
  3188.     // those in the palette
  3189.     PALETTEENTRY pe[256];
  3190.     GetPaletteEntries(hPalette, 0, 256, pe);
  3191.     pctThis = (LPRGBQUAD)((LPSTR)lpbi + lpbi->biSize);
  3192.     for (i = 0; i < 256; i++) 
  3193. {
  3194.         pctThis->rgbRed = pe[i].peRed;    
  3195.         pctThis->rgbGreen = pe[i].peGreen;    
  3196.         pctThis->rgbBlue = pe[i].peBlue;
  3197.         pctThis++;    
  3198.     }
  3199. GlobalUnlock(hDIB);
  3200.     return TRUE;
  3201. }
  3202. /************************************************************************* 
  3203.  * 
  3204.  * DrawTransparentBitmap () 
  3205.  * 
  3206.  * Parameters: 
  3207.  * 
  3208.  * HDC hDC          - DC to do output to 
  3209.  * 
  3210.  * HBITMAP hBitmap    - handle of bitmap to draw transparently
  3211.  * 
  3212.  * LONG xStart, yStart   - start position to draw *
  3213.  *
  3214.  * COLORREF cTransparentColor - transparent color * 
  3215.  * Return Value: 
  3216.  * 
  3217.  * Description: none
  3218.  *  Draw bitmap transparently
  3219.  * 
  3220.  ************************************************************************/ 
  3221. void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, 
  3222.    LONG xStart, LONG yStart, 
  3223.    COLORREF cTransparentColor)
  3224. {
  3225.    BITMAP     bm;
  3226.    COLORREF   cColor;
  3227.    HBITMAP    bmAndBack, bmAndObject, bmAndMem, bmSave;
  3228.    HBITMAP    bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
  3229.    HDC        hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
  3230.    POINT      ptSize;
  3231.    hdcTemp = CreateCompatibleDC(hdc);
  3232.    SelectObject(hdcTemp, hBitmap);   // Select the bitmap
  3233.    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  3234.    ptSize.x = bm.bmWidth;            // Get width of bitmap
  3235.    ptSize.y = bm.bmHeight;           // Get height of bitmap
  3236.    DPtoLP(hdcTemp, &ptSize, 1);      // Convert from device
  3237.                                      // to logical points
  3238.    // Create some DCs to hold temporary data.
  3239.    hdcBack   = CreateCompatibleDC(hdc);
  3240.    hdcObject = CreateCompatibleDC(hdc);
  3241.    hdcMem    = CreateCompatibleDC(hdc);
  3242.    hdcSave   = CreateCompatibleDC(hdc);
  3243.    // Create a bitmap for each DC. DCs are required for a number of
  3244.    // GDI functions.
  3245.    // Monochrome DC
  3246.    bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
  3247.    // Monochrome DC
  3248.    bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
  3249.    bmAndMem    = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
  3250.    bmSave      = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
  3251.    // Each DC must select a bitmap object to store pixel data.
  3252.    bmBackOld   = (HBITMAP)SelectObject(hdcBack, bmAndBack);
  3253.    bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
  3254.    bmMemOld    = (HBITMAP)SelectObject(hdcMem, bmAndMem);
  3255.    bmSaveOld   = (HBITMAP)SelectObject(hdcSave, bmSave);
  3256.    // Set proper mapping mode.
  3257.    SetMapMode(hdcTemp, GetMapMode(hdc));
  3258.    // Save the bitmap sent here, because it will be overwritten.
  3259.    BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
  3260.    // Set the background color of the source DC to the color.
  3261.    // contained in the parts of the bitmap that should be transparent
  3262.    cColor = SetBkColor(hdcTemp, cTransparentColor);
  3263.    // Create the object mask for the bitmap by performing a BitBlt
  3264.    // from the source bitmap to a monochrome bitmap.
  3265.    BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
  3266.           SRCCOPY);
  3267.    // Set the background color of the source DC back to the original
  3268.    // color.
  3269.    SetBkColor(hdcTemp, cColor);
  3270.    // Create the inverse of the object mask.
  3271.    BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
  3272.           NOTSRCCOPY);
  3273.    // Copy the background of the main DC to the destination.
  3274.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
  3275.           SRCCOPY);
  3276.    // Mask out the places where the bitmap will be placed.
  3277.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
  3278.    // Mask out the transparent colored pixels on the bitmap.
  3279.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
  3280.    // XOR the bitmap with the background on the destination DC.
  3281.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
  3282.    // Copy the destination to the screen.
  3283.    BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
  3284.           SRCCOPY);
  3285.    // Place the original bitmap back into the bitmap sent here.
  3286.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
  3287.    // Delete the memory bitmaps.
  3288.    DeleteObject(SelectObject(hdcBack, bmBackOld));
  3289.    DeleteObject(SelectObject(hdcObject, bmObjectOld));
  3290.    DeleteObject(SelectObject(hdcMem, bmMemOld));
  3291.    DeleteObject(SelectObject(hdcSave, bmSaveOld));
  3292.    // Delete the memory DCs.
  3293.    DeleteDC(hdcMem);
  3294.    DeleteDC(hdcBack);
  3295.    DeleteDC(hdcObject);
  3296.    DeleteDC(hdcSave);
  3297.    DeleteDC(hdcTemp);
  3298. }
  3299. /************************************************************************* 
  3300.  * 
  3301.  * Fade() 
  3302.  * 
  3303.  * Parameters: 
  3304.  * 
  3305.  * int nDeltaR   -  change value of Red
  3306.  * int nDeltaG   -  change value of Green
  3307.  * int nDeltaB   -  change value of Blue
  3308.  * BYTE rm  -  maxinum value of Red
  3309.  * BYTE gm  -  maxinum value of Green
  3310.  * BYTE bm  -  maxinum value of Blue
  3311.  * BYTE *r  -  pointer of value of Red after change
  3312.  * BYTE *g  -  pointer of value of Green after change
  3313.  * BYTE *b  -  pointer of value of Blue after change
  3314.  * 
  3315.  * Return Value: 
  3316.  *
  3317.  * BOOL          -  TRUE if success, FALSE is failue
  3318.  * 
  3319.  * Description: 
  3320.  * 
  3321.  * This function change the value of R, G, b
  3322.  * 
  3323.  ************************************************************************/
  3324. BOOL Fade(int nDeltaR, int nDeltaG, int nDeltaB, 
  3325.   BYTE rm, BYTE gm, BYTE bm,
  3326.   BYTE *r, BYTE *g, BYTE *b)
  3327. {
  3328. int R = *r + nDeltaR;
  3329. int G = *g + nDeltaG;
  3330. int B = *b + nDeltaB;
  3331. if (nDeltaR < 0)
  3332. *r = (BYTE)BOUND(R, rm, 255);
  3333. else
  3334. *r = (BYTE)BOUND(R, 0, rm);
  3335. if (nDeltaG < 0)
  3336. *g = (BYTE)BOUND(G, gm, 255);
  3337. else
  3338. *g = (BYTE)BOUND(G, 0, gm);
  3339. if (nDeltaB < 0)
  3340. *b = (BYTE)BOUND(B, bm, 255);
  3341. else
  3342. *b = (BYTE)BOUND(B, 0, bm);
  3343. if (*r==rm && *g==gm && *b==bm)
  3344. return TRUE;
  3345. else
  3346. return FALSE;
  3347. }
  3348. /************************************************************************* 
  3349.  * 
  3350.  * Delay() 
  3351.  * 
  3352.  * Parameters: 
  3353.  * 
  3354.  * DWORD dwDelayTime   - ms to delay
  3355.  * 
  3356.  * Return Value: none
  3357.  * 
  3358.  * Description: 
  3359.  * 
  3360.  * This function Delay specified ms before perform next instruction 
  3361.  * 
  3362.  ************************************************************************/ 
  3363. void Delay(DWORD dwDelayTime)
  3364. {
  3365. _timeb _start, _end;
  3366. _ftime(&_start);
  3367. _ftime(&_end);
  3368. while(DWORD(_end.millitm - _start.millitm) < dwDelayTime)
  3369. {
  3370. _ftime(&_end);
  3371. }
  3372. }
  3373. /************************************************************************* 
  3374.  * 
  3375.  * CopyHandle() 
  3376.  * 
  3377.  * Parameters: 
  3378.  * 
  3379.  * HANDLE h         - source handle
  3380.  * 
  3381.  * Return Value: 
  3382.  * 
  3383.  * HANDLE           - duplicated handle
  3384.  * 
  3385.  * Description: 
  3386.  * 
  3387.  * Copy memory handle to another
  3388.  ***********************************************************************
  3389. HANDLE CopyHandle(HANDLE h)
  3390. {
  3391. if (h == NULL)
  3392. return NULL;
  3393. DWORD  dwLen = ::GlobalSize((HGLOBAL)h);
  3394. HANDLE hCopy = ::GlobalAlloc(GHND, dwLen);
  3395. if (hCopy == NULL)
  3396. return NULL;
  3397. void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
  3398. void* lp     = ::GlobalLock((HGLOBAL) h);
  3399. ::CopyMemory(lpCopy, lp, dwLen);
  3400. ::GlobalUnlock(hCopy);
  3401. ::GlobalUnlock(h);
  3402. return hCopy;
  3403. }
  3404. */ 
  3405. /************************************************************************* 
  3406.  * 
  3407.  * CropBitmap() 
  3408.  * 
  3409.  * Parameters: 
  3410.  * 
  3411.  * HBITMAP hBitmap - handle of DDB to be cropped
  3412.  * LPRECT lpRect   - specified rectangle to crop
  3413.  * 
  3414.  * Return Value: 
  3415.  * 
  3416.  * HDIB             - Handle to new bitmap 
  3417.  * 
  3418.  * Description: 
  3419.  * 
  3420.  * This function crop the specified rectangle in DDB, and return
  3421.  * the cropped DDB in a new DIB handle, let the source DDB unchanged
  3422.  * 
  3423.  ************************************************************************/ 
  3424. HBITMAP CropBitmap(HBITMAP hBitmap, LPRECT lpRect)
  3425. {
  3426. WaitCursorBegin();
  3427. // Get Curent DC
  3428. HDC hDC = GetDC(NULL);
  3429. // create bitmap
  3430. HBITMAP hNewBmp = CreateCompatibleBitmap(hDC, RECTWIDTH(lpRect), RECTHEIGHT(lpRect));
  3431. if (hNewBmp == NULL)
  3432. {
  3433. ReleaseDC(NULL, hDC);
  3434. WaitCursorEnd();
  3435. return NULL;
  3436. }
  3437. // Create memory DC
  3438. HDC hMemDC = CreateCompatibleDC(hDC);
  3439. if (hMemDC == NULL)
  3440. {
  3441. ReleaseDC(NULL, hDC);
  3442. DeleteObject(hNewBmp);
  3443. WaitCursorEnd();
  3444. return NULL;
  3445. }
  3446. HDC hSrcMemDC = CreateCompatibleDC(hDC);
  3447. if (hSrcMemDC == NULL)
  3448. {
  3449. DeleteDC(hMemDC);
  3450. ReleaseDC(NULL, hDC);
  3451. DeleteObject(hNewBmp);
  3452. WaitCursorEnd();
  3453. return NULL;
  3454. }
  3455. // Select new bitmap in memory DC
  3456. HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hNewBmp);
  3457. // select old bitmap in SrcMemDC
  3458. HBITMAP hSrcOldBitmap = (HBITMAP)SelectObject(hSrcMemDC, hBitmap);
  3459. // bitblt old bitmap in new bitmap 
  3460. if (! BitBlt(hMemDC, 
  3461.  0, 
  3462.  0,
  3463.  RECTWIDTH(lpRect), 
  3464.  RECTHEIGHT(lpRect),
  3465.  hSrcMemDC,
  3466.  lpRect->left,
  3467.  lpRect->top,
  3468.  SRCCOPY))
  3469. {
  3470. SelectObject(hMemDC, hOldBitmap);
  3471. SelectObject(hSrcMemDC, hSrcOldBitmap);
  3472. DeleteDC(hMemDC);
  3473. DeleteDC(hSrcMemDC);
  3474. ReleaseDC(NULL, hDC);
  3475. DeleteObject(hNewBmp);
  3476. WaitCursorEnd();
  3477. return NULL;
  3478. }
  3479. // restore
  3480. SelectObject(hMemDC, hOldBitmap);
  3481. SelectObject(hSrcMemDC, hSrcOldBitmap);
  3482. DeleteDC(hMemDC);
  3483. DeleteDC(hSrcMemDC);
  3484. ReleaseDC(NULL, hDC);
  3485. WaitCursorEnd();
  3486. // return
  3487. return hNewBmp;
  3488. }
  3489. /************************************************************************* 
  3490.  * 
  3491.  * CropDIB() 
  3492.  * 
  3493.  * Parameters: 
  3494.  * 
  3495.  * HDIB hDIB       - handle of DIB to be cropped
  3496.  * LPRECT lpRect   - specified rectangle to crop
  3497.  * 
  3498.  * Return Value: 
  3499.  * 
  3500.  * HDIB             - Handle to new DIB 
  3501.  * 
  3502.  * Description: 
  3503.  * 
  3504.  * This function crop the specified rectangle in DIB, and return
  3505.  * the cropped DIB in a new DIB handle, let the source DIB unchanged
  3506.  * 
  3507.  ************************************************************************/ 
  3508. HDIB CropDIB(HDIB hDIB, LPRECT lpRect)
  3509. {
  3510.     LPBITMAPINFO lpbmi = NULL; 
  3511.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  3512.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  3513.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  3514.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; 
  3515. int  nWidth, nHeight;
  3516. HDIB  hNewDIB;
  3517. DWORD  dwSize;
  3518. WaitCursorBegin();
  3519. // Get DIB pointer
  3520. if (! hDIB)
  3521. {
  3522. WaitCursorEnd();
  3523. return NULL;
  3524. }
  3525. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  3526. if (! lpSrcDIB)
  3527. {
  3528. WaitCursorEnd();
  3529. return NULL;
  3530. }
  3531.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  3532.     dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); 
  3533.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  3534. memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
  3535. nWidth = RECTWIDTH(lpRect);
  3536. nHeight = RECTHEIGHT(lpRect);
  3537.     lpbmi->bmiHeader.biWidth = nWidth; 
  3538.     lpbmi->bmiHeader.biHeight = nHeight; 
  3539.  
  3540.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  3541. hDC = GetDC( NULL ); 
  3542.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  3543.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  3544.     hSourceDC = CreateCompatibleDC( hDC ); 
  3545.     hTargetDC = CreateCompatibleDC( hDC ); 
  3546.  
  3547.     // Flip the bits on the source DIBSection to match the source DIB 
  3548.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  3549.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  3550.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  3551.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  3552.  
  3553.     // Select DIBSections into DCs 
  3554.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  3555.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  3556.  
  3557. // put old bitmap in new bitmap 
  3558.     BitBlt(hTargetDC, 0, 0, nWidth, nHeight, hSourceDC, lpRect->left, lpRect->top, SRCCOPY); 
  3559.  
  3560.     // Clean up and delete the DCs 
  3561.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  3562.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  3563.     DeleteDC( hSourceDC ); 
  3564.     DeleteDC( hTargetDC ); 
  3565.     ReleaseDC( NULL, hDC ); 
  3566.  
  3567.     // Flush the GDI batch, so we can play with the bits 
  3568.     GdiFlush(); 
  3569.  
  3570.     // Allocate enough memory for the new CF_DIB, and copy bits 
  3571. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  3572. hNewDIB = GlobalAlloc(GHND, dwSize);
  3573.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  3574.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  3575.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  3576.  
  3577.     // final cleanup 
  3578.     DeleteObject( hTargetBitmap ); 
  3579.     DeleteObject( hSourceBitmap ); 
  3580.     free( lpbmi ); 
  3581. GlobalUnlock(hDIB);
  3582. GlobalUnlock(hNewDIB);
  3583. WaitCursorEnd();
  3584.  
  3585.     return hNewDIB;
  3586. }
  3587. /************************************************************************* 
  3588.  * 
  3589.  * CutDIB() 
  3590.  * 
  3591.  * Parameters: 
  3592.  * 
  3593.  * HDIB hDIB       - handle of DIB to be cut
  3594.  * LPRECT lpRect   - specified rectangle to cut off
  3595.  * 
  3596.  * Return Value: 
  3597.  * 
  3598.  * HDIB             - Handle to new DIB 
  3599.  * 
  3600.  * Description: 
  3601.  * 
  3602.  * This function cut off the specified rectangle in DIB, and return
  3603.  * the cut DIB in a new DIB handle, let the source DIB unchanged
  3604.  * 
  3605.  ************************************************************************/ 
  3606. HDIB CutDIB(HDIB hDIB, LPRECT lpRect)
  3607. {
  3608.     LPBITMAPINFO lpbmi = NULL; 
  3609.     LPSTR       lpTargetBits; 
  3610.     HDC  hDC = NULL, hTargetDC; 
  3611.     HBITMAP      hTargetBitmap, hOldTargetBitmap; 
  3612.     DWORD        dwTargetBitsSize; 
  3613. HDIB  hNewDIB;
  3614. WaitCursorBegin();
  3615. // Get new DIB handle
  3616. if (! hDIB)
  3617. {
  3618. WaitCursorEnd();
  3619. return NULL;
  3620. }
  3621. hNewDIB = CopyHandle(hDIB);
  3622. if (! hNewDIB)
  3623. {
  3624. WaitCursorEnd();
  3625. return NULL;
  3626. }
  3627.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  3628. hDC = GetDC( NULL ); 
  3629.     lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); 
  3630.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  3631.     hTargetDC = CreateCompatibleDC( hDC ); 
  3632.  
  3633.     // Flip the bits on the source DIBSection to match the source DIB 
  3634.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  3635.     memcpy( lpTargetBits, FindDIBBits((LPSTR)lpbmi), dwTargetBitsSize ); 
  3636.     // Select DIBSections into DCs 
  3637.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  3638.  
  3639. // clear rectangle specified
  3640. HBRUSH hBrush = CreateSolidBrush(RGB(255,255,255));
  3641. HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
  3642. HBRUSH hOldBrush = (HBRUSH)SelectObject(hTargetDC, hBrush);
  3643. HPEN hOldPen = (HPEN)SelectObject(hTargetDC, hPen);
  3644. Rectangle(hTargetDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
  3645. SelectObject(hTargetDC, hOldBrush);
  3646. SelectObject(hTargetDC, hOldPen);
  3647.  
  3648.     // Clean up and delete the DCs 
  3649.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  3650.     DeleteDC( hTargetDC ); 
  3651.     ReleaseDC( NULL, hDC ); 
  3652.  
  3653.     // Flush the GDI batch, so we can play with the bits 
  3654.     GdiFlush(); 
  3655.  
  3656.     // copy bits 
  3657.     memcpy( FindDIBBits( (LPSTR)lpbmi ), lpTargetBits, dwTargetBitsSize ); 
  3658.  
  3659.     // final cleanup 
  3660.     DeleteObject( hTargetBitmap ); 
  3661. GlobalUnlock(hNewDIB);
  3662. WaitCursorEnd();
  3663.  
  3664.     return hNewDIB;
  3665. }
  3666. /************************************************************************* 
  3667.  * 
  3668.  * MergeDIB() 
  3669.  * 
  3670.  * Parameters: 
  3671.  * 
  3672.  * HDIB hDIB1       - handle of DIB to be merged to
  3673.  * HDIB hDIB2       - handle of DIB to be merged from
  3674.  * POINT ptTopLeft  - start merge position in hDIB1
  3675.  * 
  3676.  * Return Value: 
  3677.  * 
  3678.  * HDIB             - Handle to new DIB 
  3679.  * 
  3680.  * Description: 
  3681.  * 
  3682.  * This function merge the second DIB to the first DIB, and return
  3683.  * the merged DIB in a new DIB handle, let the source DIBs unchanged
  3684.  * 
  3685.  ************************************************************************/ 
  3686. HDIB MergeDIB(HDIB hDIB1, HDIB hDIB2, POINT ptTopLeft)
  3687. {
  3688.     LPBITMAPINFO lpbmi = NULL; 
  3689.     LPSTR       lpSourceBits, lpTargetBits; 
  3690.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  3691.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  3692.     DWORD        dwTargetBitsSize, dwSourceBitsSize; 
  3693. HDIB  hNewDIB;
  3694. int  nWidth, nHeight;
  3695. WaitCursorBegin();
  3696. // Get DIB pointer
  3697. if (! hDIB1 || ! hDIB2)
  3698. {
  3699. WaitCursorEnd();
  3700. return NULL;
  3701. }
  3702. // new DIB
  3703. hNewDIB = CopyHandle(hDIB1);
  3704. if (! hNewDIB)
  3705. {
  3706. WaitCursorEnd();
  3707. return NULL;
  3708. }
  3709.     // New DIB buffer
  3710.     lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  3711. if (! lpbmi)
  3712. {
  3713. WaitCursorBegin();
  3714. return NULL;
  3715. }
  3716. // DIB2 buffer
  3717. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB2);
  3718. if (! lpSrcDIB)
  3719. {
  3720. GlobalUnlock(hNewDIB);
  3721. DestroyDIB(hNewDIB);
  3722. WaitCursorBegin();
  3723. return NULL;
  3724. }
  3725. nWidth = DIBWidth(lpSrcDIB);
  3726. nHeight = DIBHeight(lpSrcDIB);
  3727.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  3728. hDC = GetDC( NULL ); 
  3729.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  3730.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  3731.     hSourceDC = CreateCompatibleDC( hDC ); 
  3732.     hTargetDC = CreateCompatibleDC( hDC ); 
  3733.  
  3734.     // Flip the bits on the source DIBSection to match the source DIB 
  3735.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  3736.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  3737.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  3738.     memcpy( lpTargetBits, FindDIBBits((LPSTR)lpbmi), dwTargetBitsSize ); 
  3739.     // Select DIBSections into DCs 
  3740.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  3741.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  3742.  
  3743. // Merge
  3744.     BitBlt(hTargetDC, ptTopLeft.x, ptTopLeft.y, nWidth, nHeight, hSourceDC, 0, 0, SRCCOPY); 
  3745.  
  3746.     // Clean up and delete the DCs 
  3747.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  3748.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  3749.     DeleteDC( hSourceDC ); 
  3750.     DeleteDC( hTargetDC ); 
  3751.     ReleaseDC( NULL, hDC ); 
  3752.  
  3753.     // Flush the GDI batch, so we can play with the bits 
  3754.     GdiFlush(); 
  3755.  
  3756.     // and copy bits 
  3757.     memcpy( FindDIBBits((LPSTR)lpbmi), lpTargetBits, dwTargetBitsSize ); 
  3758.  
  3759.     // final cleanup 
  3760.     DeleteObject( hTargetBitmap ); 
  3761.     DeleteObject( hSourceBitmap ); 
  3762. GlobalUnlock(hDIB2);
  3763. GlobalUnlock(hNewDIB);
  3764. WaitCursorEnd();
  3765.  
  3766.     return hNewDIB;
  3767. }
  3768. /************************************************************************* 
  3769.  * 
  3770.  * TransparentMergeDIB() 
  3771.  * 
  3772.  * Parameters: 
  3773.  * 
  3774.  * HDIB hDIB1       - handle of DIB to be merged to
  3775.  * HDIB hDIB2       - handle of DIB to be merged from
  3776.  * POINT ptTopLeft  - start merge position in hDIB1
  3777.  * COLORREF crTransparent - transparent color
  3778.  * 
  3779.  * Return Value: 
  3780.  * 
  3781.  * HDIB             - Handle to new DIB 
  3782.  * 
  3783.  * Description: 
  3784.  * 
  3785.  * This function merge the second DIB to the first DIB with transparent of specified
  3786.  * color, and return the merged DIB in a new DIB handle, let the source DIBs unchanged
  3787.  * 
  3788.  ************************************************************************/ 
  3789. HDIB TransparentMergeDIB(HDIB hDIB1, HDIB hDIB2, POINT ptTopLeft, COLORREF crTransparent)
  3790. {
  3791.     LPBITMAPINFO lpbmi = NULL; 
  3792.     LPSTR       lpTargetBits; 
  3793.     HDC  hDC = NULL, hTargetDC; 
  3794.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap; 
  3795.     DWORD        dwTargetBitsSize; 
  3796. HDIB  hNewDIB;
  3797. int  nWidth, nHeight;
  3798. // Get DIB pointer
  3799. if (! hDIB1 || ! hDIB2)
  3800. return NULL;
  3801. // new DIB
  3802. hNewDIB = CopyHandle(hDIB1);
  3803. if (! hNewDIB)
  3804. return NULL;
  3805.     // New DIB buffer
  3806.     lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  3807. if (! lpbmi)
  3808. return NULL;
  3809. // DIB2 
  3810. hSourceBitmap = DIBToBitmap(hDIB2, NULL);
  3811. if (! hSourceBitmap)
  3812. {
  3813. GlobalUnlock(hNewDIB);
  3814. DestroyDIB(hNewDIB);
  3815. return NULL;
  3816. }
  3817. BITMAP bm;
  3818. GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
  3819. nWidth = bm.bmWidth;
  3820. nHeight = bm.bmHeight;
  3821.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  3822. hDC = GetDC( NULL ); 
  3823.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  3824.     hTargetDC = CreateCompatibleDC( hDC ); 
  3825.  
  3826.     // Flip the bits on the source DIBSection to match the source DIB 
  3827.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  3828.     memcpy( lpTargetBits, FindDIBBits((LPSTR)lpbmi), dwTargetBitsSize ); 
  3829.     // Select DIBSections into DCs 
  3830.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  3831.     // Set the color tables for the DIBSections 
  3832.     if( lpbmi->bmiHeader.biBitCount <= 8 ) 
  3833.         SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
  3834.  
  3835. // Merge
  3836. DrawTransparentBitmap(hTargetDC, hSourceBitmap, ptTopLeft.x, ptTopLeft.y, crTransparent);
  3837.     // Clean up and delete the DCs 
  3838.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  3839.     DeleteDC( hTargetDC ); 
  3840.     ReleaseDC( NULL, hDC ); 
  3841.  
  3842.     // Flush the GDI batch, so we can play with the bits 
  3843.     GdiFlush(); 
  3844.  
  3845.     // and copy bits 
  3846.     memcpy( FindDIBBits((LPSTR)lpbmi), lpTargetBits, dwTargetBitsSize ); 
  3847.  
  3848.     // final cleanup 
  3849.     DeleteObject( hTargetBitmap ); 
  3850.     DeleteObject( hSourceBitmap ); 
  3851. GlobalUnlock(hDIB2);
  3852. GlobalUnlock(hNewDIB);
  3853.  
  3854.     return hNewDIB;
  3855. }