dibapi.cpp
上传用户:elida16851
上传日期:2022-08-05
资源大小:2048k
文件大小:102k
源码类别:

图形图象

开发平台:

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