home *** CD-ROM | disk | FTP | other *** search
/ Computer Buyer 1996 August / DKMMSAMP.iso / win_g / utils.c_ / utils.c
C/C++ Source or Header  |  1994-09-20  |  16KB  |  613 lines

  1. /**************************************************************************
  2.  
  3.     UTILS.C - useful functions for WinG Sample Apps
  4.  
  5.  **************************************************************************/
  6. /**************************************************************************
  7.  
  8.     (C) Copyright 1994 Microsoft Corp.  All rights reserved.
  9.  
  10.     You have a royalty-free right to use, modify, reproduce and 
  11.     distribute the Sample Files (and/or any modified version) in 
  12.     any way you find useful, provided that you agree that 
  13.     Microsoft has no warranty obligations or liability for any 
  14.     Sample Application Files which are modified. 
  15.  
  16.  **************************************************************************/
  17.  
  18. /*----------------------------------------------------------------------------*\
  19. |   Functions for handling Device Independent Bitmaps and clearing the         | 
  20. |   System Palette.                                                            |
  21. \*----------------------------------------------------------------------------*/
  22.  
  23. #include <windows.h>
  24. #include <windowsx.h>
  25. #include "utils.h"
  26.  
  27. #if defined(WIN32) || defined(_WIN32)
  28.     #include <memory.h>             // for _fmemcpy()
  29.     #define _huge
  30.     #define hmemcpy memcpy
  31. #endif
  32.  
  33. #define BFT_ICON   0x4349   /* 'IC' */
  34. #define BFT_BITMAP 0x4d42   /* 'BM' */
  35. #define BFT_CURSOR 0x5450   /* 'PT' */
  36.  
  37. /* flags for _lseek */
  38. #define  SEEK_CUR 1
  39. #define  SEEK_END 2
  40. #define  SEEK_SET 0
  41.  
  42.  
  43. /*
  44.  *  Clear the System Palette so that we can ensure an identity palette 
  45.  *  mapping for fast performance.
  46.  */
  47.  
  48. void ClearSystemPalette(void)
  49. {
  50.   //*** A dummy palette setup
  51.   struct
  52.   {
  53.     WORD Version;
  54.     WORD NumberOfEntries;
  55.     PALETTEENTRY aEntries[256];
  56.   } Palette =
  57.   {
  58.     0x300,
  59.     256
  60.   };
  61.  
  62.   HPALETTE ScreenPalette = 0;
  63.   HDC ScreenDC;
  64.   int Counter;
  65.   UINT nMapped = 0;
  66.   BOOL bOK = FALSE;
  67.   int  nOK = 0;
  68.   
  69.   //*** Reset everything in the system palette to black
  70.   for(Counter = 0; Counter < 256; Counter++)
  71.   {
  72.     Palette.aEntries[Counter].peRed = 0;
  73.     Palette.aEntries[Counter].peGreen = 0;
  74.     Palette.aEntries[Counter].peBlue = 0;
  75.     Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
  76.   }
  77.  
  78.   //*** Create, select, realize, deselect, and delete the palette
  79.   ScreenDC = GetDC(NULL);
  80.   ScreenPalette = CreatePalette((LOGPALETTE *)&Palette);
  81.  
  82.   if (ScreenPalette)
  83.   {
  84.     ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
  85.     nMapped = RealizePalette(ScreenDC);
  86.     ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
  87.     bOK = DeleteObject(ScreenPalette);
  88.   }
  89.  
  90.   nOK = ReleaseDC(NULL, ScreenDC);
  91.  
  92.   return;
  93. }
  94.  
  95.  
  96. /*
  97.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  98.  *
  99.  *   BITMAP INFO    bi
  100.  *   palette data
  101.  *   bits....
  102.  */
  103.  
  104. PDIB DibOpenFile(LPSTR szFile)
  105. {
  106.     HFILE               fh;
  107.     DWORD               dwLen;
  108.     DWORD               dwBits;
  109.     PDIB                pdib;
  110.     LPVOID              p;
  111.     OFSTRUCT            of;
  112.  
  113. #if defined(WIN32) || defined(_WIN32)
  114.     #define GetCurrentInstance()    GetModuleHandle(NULL)
  115. #else
  116.     #define GetCurrentInstance()    (HINSTANCE)SELECTOROF((LPVOID)&of)
  117. #endif
  118.  
  119.     fh = OpenFile(szFile, &of, OF_READ);
  120.  
  121.     if (fh == -1)
  122.     {
  123.         HRSRC h;
  124.  
  125.         h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
  126.  
  127. #if defined(WIN32) || defined(_WIN32)
  128.         //!!! can we call GlobalFree() on this? is it the right format.
  129.         //!!! can we write to this resource?
  130.         if (h)
  131.             return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
  132. #else
  133.         if (h)
  134.             fh = AccessResource(GetCurrentInstance(), h);
  135. #endif
  136.     }
  137.  
  138.     if (fh == -1)
  139.         return NULL;
  140.  
  141.     pdib = DibReadBitmapInfo(fh);
  142.  
  143.     if (!pdib)
  144.         return NULL;
  145.  
  146.     /* How much memory do we need to hold the DIB */
  147.  
  148.     dwBits = pdib->biSizeImage;
  149.     dwLen  = pdib->biSize + DibPaletteSize(pdib) + dwBits;
  150.  
  151.     /* Can we get more memory? */
  152.  
  153.     p = GlobalReAllocPtr(pdib,dwLen,0);
  154.  
  155.     if (!p)
  156.     {
  157.         GlobalFreePtr(pdib);
  158.         pdib = NULL;
  159.     }
  160.     else
  161.     {
  162.         pdib = (PDIB)p;
  163.     }
  164.  
  165.     if (pdib)
  166.     {
  167.         /* read in the bits */
  168.         _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib), dwBits);
  169.     }
  170.  
  171.     _lclose(fh);
  172.  
  173.     return pdib;
  174. }
  175.  
  176.  
  177. /*
  178.  *  ReadDibBitmapInfo()
  179.  *
  180.  *  Will read a file in DIB format and return a global HANDLE to its
  181.  *  BITMAPINFO.  This function will work with both "old" and "new"
  182.  *  bitmap formats, but will always return a "new" BITMAPINFO.
  183.  */
  184.  
  185. PDIB DibReadBitmapInfo(HFILE fh)
  186. {
  187.     DWORD     off;
  188.     HANDLE    hbi = NULL;
  189.     int       size;
  190.     int       i;
  191.     int       nNumColors;
  192.  
  193.     RGBQUAD FAR       *pRgb;
  194.     BITMAPINFOHEADER   bi;
  195.     BITMAPCOREHEADER   bc;
  196.     BITMAPFILEHEADER   bf;
  197.     PDIB               pdib;
  198.  
  199.     if (fh == -1)
  200.         return NULL;
  201.  
  202.     off = _llseek(fh,0L,SEEK_CUR);
  203.  
  204.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  205.         return FALSE;
  206.  
  207.     /*
  208.      *  do we have a RC HEADER?
  209.      */
  210.     if (bf.bfType != BFT_BITMAP)
  211.     {
  212.         bf.bfOffBits = 0L;
  213.         _llseek(fh,off,SEEK_SET);
  214.     }
  215.  
  216.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  217.         return FALSE;
  218.  
  219.     /*
  220.      *  what type of bitmap info is this?
  221.      */
  222.     switch (size = (int)bi.biSize)
  223.     {
  224.         default:
  225.         case sizeof(BITMAPINFOHEADER):
  226.             break;
  227.  
  228.         case sizeof(BITMAPCOREHEADER):
  229.             bc = *(BITMAPCOREHEADER*)&bi;
  230.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  231.             bi.biWidth              = (DWORD)bc.bcWidth;
  232.             bi.biHeight             = (DWORD)bc.bcHeight;
  233.             bi.biPlanes             =  (UINT)bc.bcPlanes;
  234.             bi.biBitCount           =  (UINT)bc.bcBitCount;
  235.             bi.biCompression        = BI_RGB;
  236.             bi.biSizeImage          = 0;
  237.             bi.biXPelsPerMeter      = 0;
  238.             bi.biYPelsPerMeter      = 0;
  239.             bi.biClrUsed            = 0;
  240.             bi.biClrImportant       = 0;
  241.  
  242.             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  243.  
  244.             break;
  245.     }
  246.  
  247.     nNumColors = DibNumColors(&bi);
  248.  
  249. #if 0
  250.     if (bi.biSizeImage == 0)
  251.         bi.biSizeImage = DibSizeImage(&bi);
  252.  
  253.     if (bi.biClrUsed == 0)
  254.         bi.biClrUsed = DibNumColors(&bi);
  255. #else
  256.     FixBitmapInfo(&bi);
  257. #endif
  258.  
  259.     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  260.  
  261.     if (!pdib)
  262.         return NULL;
  263.  
  264.     *pdib = bi;
  265.  
  266.     pRgb = DibColors(pdib);
  267.  
  268.     if (nNumColors)
  269.     {
  270.         if (size == sizeof(BITMAPCOREHEADER))
  271.         {
  272.             /*
  273.              * convert a old color table (3 byte entries) to a new
  274.              * color table (4 byte entries)
  275.              */
  276.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
  277.  
  278.             for (i=nNumColors-1; i>=0; i--)
  279.             {
  280.                 RGBQUAD rgb;
  281.  
  282.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  283.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  284.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  285.                 rgb.rgbReserved = (BYTE)0;
  286.  
  287.                 pRgb[i] = rgb;
  288.             }
  289.         }
  290.         else
  291.         {
  292.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
  293.         }
  294.     }
  295.  
  296.     if (bf.bfOffBits != 0L)
  297.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  298.  
  299.     return pdib;
  300. }
  301.  
  302. /*
  303.  *  DibSetUsage(hdib,hpal,wUsage)
  304.  *
  305.  *  Modifies the color table of the passed DIB for use with the wUsage
  306.  *  parameter specifed.
  307.  *
  308.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  309.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  310.  *      in the passed palette
  311.  */
  312.  
  313. BOOL DibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
  314. {
  315.     PALETTEENTRY       ape[256];
  316.     RGBQUAD FAR *      pRgb;
  317.     WORD FAR *         pw;
  318.     int                nColors;
  319.     int                n;
  320.  
  321.     if (hpal == NULL)
  322.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  323.  
  324.     if (!pdib)
  325.         return FALSE;
  326.  
  327.     nColors = DibNumColors(pdib);
  328.     
  329.     if (nColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  330.         nColors = 0;
  331.  
  332.     if (nColors > 0)
  333.     {
  334.         pRgb = DibColors(pdib);
  335.  
  336.         switch (wUsage)
  337.         {
  338.             //
  339.             // Set the DIB color table to palette indexes
  340.             //
  341.             case DIB_PAL_COLORS:
  342.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  343.                     *pw = n;
  344.                 break;
  345.  
  346.             //
  347.             // Set the DIB color table to RGBQUADS
  348.             //
  349.             default:
  350.             case DIB_RGB_COLORS:
  351.                 nColors = min(nColors,256);
  352.  
  353.                 GetPaletteEntries(hpal,0,nColors,ape);
  354.  
  355.                 for (n=0; n<nColors; n++)
  356.                 {
  357.                     pRgb[n].rgbRed      = ape[n].peRed;
  358.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  359.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  360.                     pRgb[n].rgbReserved = 0;
  361.                 }
  362.                 break;
  363.         }
  364.     }
  365.     return TRUE;
  366. }
  367.  
  368. /*
  369.  *  DibCreate(bits, dx, dy)
  370.  *
  371.  *  Creates a new packed DIB with the given dimensions and the
  372.  *  given number of bits per pixel
  373.  */
  374.  
  375. PDIB DibCreate(int bits, int dx, int dy)
  376. {
  377.     LPBITMAPINFOHEADER lpbi ;
  378.     DWORD       dwSizeImage;
  379.     int         i;
  380.     DWORD FAR  *pdw;
  381.  
  382.     dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
  383.  
  384.     lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
  385.  
  386.     if (lpbi == NULL)
  387.         return NULL;
  388.  
  389.     lpbi->biSize            = sizeof(BITMAPINFOHEADER) ;
  390.     lpbi->biWidth           = dx;
  391.     lpbi->biHeight          = dy;
  392.     lpbi->biPlanes          = 1;
  393.     lpbi->biBitCount        = bits ;
  394.     lpbi->biCompression     = BI_RGB ;
  395.     lpbi->biSizeImage       = dwSizeImage;
  396.     lpbi->biXPelsPerMeter   = 0 ;
  397.     lpbi->biYPelsPerMeter   = 0 ;
  398.     lpbi->biClrUsed         = 0 ;
  399.     lpbi->biClrImportant    = 0 ;
  400.  
  401.     if (bits == 4)
  402.         lpbi->biClrUsed = 16;
  403.  
  404.     else if (bits == 8)
  405.         lpbi->biClrUsed = 256;
  406.  
  407.     pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
  408.  
  409.     for (i=0; i<(int)lpbi->biClrUsed/16; i++)
  410.     {
  411.         *pdw++ = 0x00000000;    // 0000  black
  412.         *pdw++ = 0x00800000;    // 0001  dark red
  413.         *pdw++ = 0x00008000;    // 0010  dark green
  414.         *pdw++ = 0x00808000;    // 0011  mustard
  415.         *pdw++ = 0x00000080;    // 0100  dark blue
  416.         *pdw++ = 0x00800080;    // 0101  purple
  417.         *pdw++ = 0x00008080;    // 0110  dark turquoise
  418.         *pdw++ = 0x00C0C0C0;    // 1000  gray
  419.         *pdw++ = 0x00808080;    // 0111  dark gray
  420.         *pdw++ = 0x00FF0000;    // 1001  red
  421.         *pdw++ = 0x0000FF00;    // 1010  green
  422.         *pdw++ = 0x00FFFF00;    // 1011  yellow
  423.         *pdw++ = 0x000000FF;    // 1100  blue
  424.         *pdw++ = 0x00FF00FF;    // 1101  pink (magenta)
  425.         *pdw++ = 0x0000FFFF;    // 1110  cyan
  426.         *pdw++ = 0x00FFFFFF;    // 1111  white
  427.     }
  428.  
  429.     return (PDIB)lpbi;
  430. }
  431.  
  432. static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  433. {
  434.     DWORD dw;
  435.  
  436. #ifdef __cplusplus
  437.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  438. #else
  439.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
  440. #endif
  441.         *pb = xlat[*pb];
  442. }
  443.  
  444. static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  445. {
  446.     DWORD dw;
  447.  
  448. #ifdef __cplusplus
  449.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  450. #else
  451.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
  452. #endif
  453.         *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
  454. }
  455.  
  456. #define RLE_ESCAPE  0
  457. #define RLE_EOL     0
  458. #define RLE_EOF     1
  459. #define RLE_JMP     2
  460.  
  461. static void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  462. {
  463.     BYTE    cnt;
  464.     BYTE    b;
  465.     BYTE _huge *prle = pb;
  466.  
  467.     for(;;)
  468.     {
  469.         cnt = *prle++;
  470.         b   = *prle;
  471.  
  472.         if (cnt == RLE_ESCAPE)
  473.         {
  474.             prle++;
  475.  
  476.             switch (b)
  477.             {
  478.                 case RLE_EOF:
  479.                     return;
  480.  
  481.                 case RLE_EOL:
  482.                     break;
  483.  
  484.                 case RLE_JMP:
  485.                     prle++;     // skip dX
  486.                     prle++;     // skip dY
  487.                     break;
  488.  
  489.                 default:
  490.                     cnt = b;
  491.                     for (b=0; b<cnt; b++,prle++)
  492.                         *prle = xlat[*prle];
  493.  
  494.                     if (cnt & 1)
  495.                         prle++;
  496.  
  497.                     break;
  498.             }
  499.         }
  500.         else
  501.         {
  502.             *prle++ = xlat[b];
  503.         }
  504.     }
  505. }
  506.  
  507. static void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  508. {
  509. }
  510.  
  511. static void hmemmove(BYTE _huge *d, BYTE _huge *s, LONG len)
  512. {
  513.     d += len-1;
  514.     s += len-1;
  515.  
  516.     while (len--)
  517.         *d-- = *s--;
  518. }
  519.  
  520. /*
  521.  *  DibMapToPalette(pdib, hpal)
  522.  *
  523.  *  Map the colors of the DIB, using GetNearestPaletteIndex, to
  524.  *  the colors of the given palette.
  525.  */
  526.  
  527. void DibMapToPalette(PDIB pdib, HPALETTE hpal)
  528. {
  529.     LPBITMAPINFOHEADER  lpbi;
  530.     PALETTEENTRY        pe;
  531.     int                 n;
  532.     int                 nDibColors;
  533.     int                 nPalColors=0;
  534.     BYTE FAR *          lpBits;
  535.     RGBQUAD FAR *       lpRgb;
  536.     BYTE                xlat[256];
  537.     DWORD               SizeImage;
  538.  
  539.     if (!hpal || !pdib)
  540.         return;
  541.  
  542.     lpbi   = (LPBITMAPINFOHEADER)pdib;
  543.     lpRgb  = DibColors(pdib);
  544.  
  545.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  546.     nDibColors = DibNumColors(pdib);
  547.  
  548.     if ((SizeImage = lpbi->biSizeImage) == 0)
  549.         SizeImage = DibSizeImage(lpbi);
  550.  
  551.     //
  552.     //  build a xlat table. from the current DIB colors to the given
  553.     //  palette.
  554.     //
  555.     for (n=0; n<nDibColors; n++)
  556.         xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  557.  
  558.     lpBits = (LPBYTE)DibPtr(lpbi);
  559.     lpbi->biClrUsed = nPalColors;
  560.  
  561.     //
  562.     // re-size the DIB
  563.     //
  564.     if (nPalColors > nDibColors)
  565.     {
  566.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  567.         hmemmove((BYTE _huge *)DibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
  568.         lpBits = (LPBYTE)DibPtr(lpbi);
  569.     }
  570.     else if (nPalColors < nDibColors)
  571.     {
  572.         hmemcpy(DibPtr(lpbi), lpBits, SizeImage);
  573.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  574.         lpBits = (LPBYTE)DibPtr(lpbi);
  575.     }
  576.  
  577.     //
  578.     // translate the DIB bits
  579.     //
  580.     switch (lpbi->biCompression)
  581.     {
  582.         case BI_RLE8:
  583.             xlatRle8(lpBits, SizeImage, xlat);
  584.             break;
  585.  
  586.         case BI_RLE4:
  587.             xlatRle4(lpBits, SizeImage, xlat);
  588.             break;
  589.  
  590.         case BI_RGB:
  591.             if (lpbi->biBitCount == 8)
  592.                 xlatClut8(lpBits, SizeImage, xlat);
  593.             else
  594.                 xlatClut4(lpBits, SizeImage, xlat);
  595.             break;
  596.     }
  597.  
  598.     //
  599.     //  Now copy the RGBs in the logical palette to the dib color table
  600.     //
  601.     for (n=0; n<nPalColors; n++)
  602.     {
  603.         GetPaletteEntries(hpal,n,1,&pe);
  604.  
  605.         lpRgb[n].rgbRed      = pe.peRed;
  606.         lpRgb[n].rgbGreen    = pe.peGreen;
  607.         lpRgb[n].rgbBlue     = pe.peBlue;
  608.         lpRgb[n].rgbReserved = (BYTE)0;
  609.     }
  610.  
  611.     return;
  612. }
  613.