PJAImage.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:24k
源码类别:

CA认证

开发平台:

Visual C++

  1. /****************************************************************************
  2. PJAImage.cpp : implementation file for the PJAImage class
  3. written by PJ Arends
  4. pja@telus.net
  5. For updates check http://www3.telus.net/pja/PJAImage.htm
  6. -----------------------------------------------------------------------------
  7. This code is provided as is, with no warranty as to it's suitability or usefulness
  8. in any application in which it may be used. This code has not been tested for
  9. UNICODE builds, nor has it been tested on a network ( with UNC paths ).
  10. This code may be used in any way you desire. This file may be redistributed by any
  11. means as long as it is not sold for profit, and providing that this notice and the
  12. authors name are included.
  13. If any bugs are found and fixed, a note to the author explaining the problem and
  14. fix would be nice.
  15. -----------------------------------------------------------------------------
  16. ****************************************************************************/
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CPJAImage class
  19. #include "stdafx.h"
  20. #include "pjaimage.h"
  21. #define BRUSHWIDTH  8
  22. #define BRUSHHEIGHT 8
  23. /////////////////////////////////////////////////////////////////////////////
  24. //
  25. //  CPJAImage constructor  (public member function)
  26. //    Initializes member variables
  27. //
  28. //  Parameters :
  29. //    None
  30. //
  31. //  Returns :
  32. //    Nothing
  33. //
  34. /////////////////////////////////////////////////////////////////////////////
  35. CPJAImage::CPJAImage()
  36. {
  37.     m_ImageFlags = 0;
  38.     m_DrawFlags = 0;
  39.     m_hImage = NULL;
  40.     m_size.cx = 0;
  41.     m_size.cy = 0;
  42.     m_TransparentColour = CLR_DEFAULT;
  43. }
  44. /////////////////////////////////////////////////////////////////////////////
  45. //
  46. //  CPJAImage destructor  (public member function)
  47. //    frees the memory held by the image handle
  48. //
  49. //  Parameters :
  50. //    None
  51. //
  52. //  Returns :
  53. //    Nothing
  54. //
  55. /////////////////////////////////////////////////////////////////////////////
  56. CPJAImage::~CPJAImage()
  57. {
  58.     if (m_ImageFlags & PJAI_AUTODELETE)
  59.     {
  60.         if (m_ImageFlags & PJAI_ICON)
  61.             DestroyIcon((HICON)m_hImage);
  62.         else
  63.             DeleteObject((HGDIOBJ)m_hImage);
  64.     }
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. //
  68. //  CPJAImage::DitherBlt  (protected member function)
  69. //    Draws the image on the FromDC as a disabled (grayed) image onto the pToDC
  70. //
  71. //  Parameters :
  72. //    pToDC  [in] - pointer to the DC to draw the bitmap onto
  73. //    x      [in] - the left side of the image on the destination DC
  74. //    y      [in] - the top  of the image on the destination DC
  75. //    w      [in] - the width of the image on the destination DC
  76. //    h      [in] - the height of the image on the destination DC
  77. //    FromDC [in] - The DC containing the bitmap to be grayed
  78. //
  79. //  Returns :
  80. //    Nothing
  81. //
  82. //  Note : modified from code found at http://www.codeguru.com/bitmap/dither_blt.shtml
  83. //         original author Jean-Edouard Lachand-Robert (iamwired@geocities.com)
  84. //
  85. /////////////////////////////////////////////////////////////////////////////
  86. void CPJAImage::DitherBlt(CDC *pToDC, int x, int y, int w, int h, CDC *pFromDC)
  87. {
  88.     CDC MonoDC;
  89.     if (MonoDC.CreateCompatibleDC(pToDC))
  90.     {
  91.         struct {
  92.             BITMAPINFOHEADER bmiHeader; 
  93.             RGBQUAD          bmiColors[2]; 
  94.         } RGBBWBITMAPINFO = { { sizeof(BITMAPINFOHEADER),
  95.             w,
  96.             h,
  97.             1,
  98.             1,
  99.             BI_RGB,
  100.             0,
  101.             0,
  102.             0,
  103.             0,
  104.             0},
  105.         { { 0x00, 0x00, 0x00, 0x00 },
  106.         { 0xFF, 0xFF, 0xFF, 0x00 }}};
  107.         VOID *pbitsBW;
  108.         HBITMAP hbmBW = CreateDIBSection(MonoDC.m_hDC,
  109.             (LPBITMAPINFO)&RGBBWBITMAPINFO,
  110.             DIB_RGB_COLORS,
  111.             &pbitsBW,
  112.             NULL,
  113.             0);
  114.         ASSERT(hbmBW);
  115.         if (hbmBW)
  116.         {
  117.             int SavedMonoDC = MonoDC.SaveDC();
  118.             int SavedpToDC = pToDC->SaveDC();
  119.             // Attach the monochrome DIB section to the MonoDC
  120.             MonoDC.SelectObject(hbmBW);
  121.             
  122.             // BitBlt the bitmap into the monochrome DIB section
  123.             MonoDC.BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCCOPY);
  124.             
  125.             // BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT bits in the destination DC
  126.             // The magic ROP comes from the Charles Petzold's book
  127.             HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
  128.             pToDC->SelectObject(hb);
  129.             pToDC->BitBlt(x + 1, y + 1, w, h, &MonoDC, 0, 0, 0x00B8074A);
  130.             
  131.             // BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW bits in the destination DC
  132.             hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
  133.             DeleteObject(pToDC->SelectObject(hb));
  134.             pToDC->BitBlt(x, y, w, h, &MonoDC, 0, 0, 0x00B8074A);
  135.             
  136.             pToDC->RestoreDC(SavedpToDC);
  137.             MonoDC.RestoreDC(SavedMonoDC);
  138.             DeleteObject(hb);
  139.         }
  140.         DeleteObject(hbmBW);
  141.         MonoDC.DeleteDC();
  142.     }
  143. }
  144. /////////////////////////////////////////////////////////////////////////////
  145. //
  146. //  CPJAImage::DrawImage  (public member function)
  147. //    Draws the image (set with the SetImage() function) on the given device 
  148. //    context
  149. //
  150. //  Parameters :
  151. //    pDC       [in] - a pointer to the the device context to draw the image on
  152. //    x         [in] - the left side of the image on the destination DC
  153. //    y         [in] - the top  of the image on the destination DC
  154. //    w         [in] - the width of the image on the destination DC
  155. //    h         [in] - the height of the image on the destination DC
  156. //    DrawFlags [in] - How to draw the image
  157. //
  158. //  Returns :
  159. //    Nothing
  160. //
  161. //  Note :
  162. //    See the PJAImage.h file for a description of the flags used
  163. //
  164. //    If the image is an icon or a transparent bitmap, the brush that is selected
  165. //    into the pDC will be used as the background. The brush can be a pattern
  166. //    or bitmap brush. This code assumes the brush is an 8x8 pixel brush
  167. //    (Set with the BUTTONWIDTH an BUTTONHEIGHT macros).
  168. //
  169. //    The image will be drawn entirely within the rectangle specified by the
  170. //    x, y, w, and h parameters.
  171. //
  172. /////////////////////////////////////////////////////////////////////////////
  173. void CPJAImage::DrawImage(CDC *pDC, int x, int y, int w, int h, DWORD DrawFlags /* = 0 */)
  174. {   // sanity check
  175.     if (!m_hImage)
  176.         return;
  177.     // verify flags
  178. #ifdef _DEBUG
  179.     if (DrawFlags & PJAI_DISABLED)
  180.         ASSERT (!(DrawFlags & PJAI_GRAYSCALE));
  181.     if (DrawFlags & PJAI_CENTERED)
  182.         ASSERT (!(DrawFlags & PJAI_STRETCHED));
  183. #endif
  184.     m_DrawFlags = DrawFlags;
  185.     // Get the background brush for transparent images
  186.     CBrush *BackGround = pDC->GetCurrentBrush();
  187.     BackGround->UnrealizeObject();
  188.     // handle for the grayscale bitmap
  189.     HBITMAP GrayBmp = NULL;
  190.     // set the clip region to the specified rectangle
  191.     CRgn ClipRgn;
  192.     ClipRgn.CreateRectRgn(x, y, x + w, y + h);
  193.     pDC->SelectClipRgn(&ClipRgn);
  194.     ClipRgn.DeleteObject();
  195.     // create memory DC
  196.     CDC memDC;
  197.     memDC.CreateCompatibleDC(pDC);
  198.     int savedmemDC = memDC.SaveDC();
  199.     CBitmap memDCBmp;
  200.     CDC* pOutputDC = &memDC;
  201.     int left = x;
  202.     int top = y;
  203.     int width = m_size.cx;
  204.     int height = m_size.cy;
  205.     if (m_DrawFlags & PJAI_CENTERED)
  206.     {   // center the image on the output rectangle
  207.         left = x + (w / 2) - (m_size.cx / 2);
  208.         top = y + (h / 2) - (m_size.cy / 2);
  209.     }
  210.     // Create a DC and bitmap for the stretched image
  211.     CDC StretchDC;
  212.     int savedStretchDC = 0;
  213.     CBitmap stretchbmp;
  214.     if (m_DrawFlags & PJAI_STRETCHED)
  215.     {   // stretch image to fit output rectangle
  216.         width = w;
  217.         height = h;
  218.     }
  219.     // get the brush origins in case we are using a bitmap or pattern brush
  220.     CPoint BrushOrg;
  221.     CPoint Origin = pDC->GetBrushOrg();
  222.     BrushOrg.x = (BRUSHWIDTH - (left - Origin.x) % BRUSHWIDTH);
  223.     BrushOrg.y = (BRUSHHEIGHT - (top - Origin.y) % BRUSHHEIGHT);
  224.     // Create a DC and bitmap for the transparent image
  225.     CDC TransparentDC;
  226.     int savedTransparentDC = 0;
  227.     CBitmap Transparentbmp;
  228.     if (m_ImageFlags & PJAI_ICON)
  229.     {   // draw the icon onto the memory DC
  230.         HICON TheIcon = (HICON)m_hImage;
  231.         if (m_DrawFlags & PJAI_GRAYSCALE)
  232.         {   // convert the colour icon to grayscale
  233.             ICONINFO iconinfo;
  234.             GetIconInfo(TheIcon, &iconinfo);
  235.             if (iconinfo.hbmColor)
  236.             {
  237.                 HBITMAP grayscale = GrayScale(pDC, iconinfo.hbmColor);
  238.                 ::DeleteObject(iconinfo.hbmColor);
  239.                 iconinfo.hbmColor = grayscale;
  240.                 TheIcon = ::CreateIconIndirect(&iconinfo);
  241.                 ::DeleteObject(iconinfo.hbmColor);
  242.                 ::DeleteObject(iconinfo.hbmMask);
  243.             }
  244.         }
  245.         memDCBmp.CreateCompatibleBitmap(pDC, width, height);
  246.         memDC.SelectObject(&memDCBmp);
  247.         memDC.SetBrushOrg(BrushOrg);
  248.         memDC.SelectObject(BackGround);
  249.         memDC.FillRect(CRect(0, 0, width + 1, height + 1), BackGround);
  250.         ::DrawIconEx(memDC.m_hDC, 0, 0, TheIcon, width, height, 0, NULL, DI_NORMAL);
  251.         
  252.         if (TheIcon != m_hImage)
  253.             ::DestroyIcon(TheIcon);
  254.     }
  255.     else if (m_ImageFlags & PJAI_BITMAP)
  256.     {   // place bitmap image into the memory DC
  257.         memDC.SelectObject((HBITMAP)m_hImage);
  258.         if (m_TransparentColour == CLR_DEFAULT)
  259.             m_TransparentColour = memDC.GetPixel(0, 0);
  260.         if (m_DrawFlags & PJAI_STRETCHED)
  261.         {   // stretch the image
  262.             StretchDC.CreateCompatibleDC(pDC);
  263.             savedStretchDC = StretchDC.SaveDC();
  264.             stretchbmp.CreateCompatibleBitmap(pDC, w, h);
  265.             StretchDC.SelectObject(stretchbmp);
  266.             StretchDC.SetStretchBltMode(COLORONCOLOR);
  267.             StretchDC.StretchBlt(0, 0, width, height, &memDC, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
  268.             pOutputDC = &StretchDC;
  269.         }
  270.         if (m_DrawFlags & PJAI_TRANSPARENT)
  271.         {   // draw the image transparently
  272.             TransparentDC.CreateCompatibleDC(pDC);
  273.             savedTransparentDC = TransparentDC.SaveDC();
  274.             Transparentbmp.CreateCompatibleBitmap(pDC, width, height);
  275.             TransparentDC.SelectObject(&Transparentbmp);
  276.             TransparentDC.SetBrushOrg(BrushOrg);
  277.             TransparentDC.SelectObject(BackGround);
  278.             TransparentDC.FillRect(CRect(0, 0, width + 1, height + 1), BackGround);
  279.             DrawTransparent(&TransparentDC, width, height, pOutputDC);
  280.             pOutputDC = &TransparentDC;
  281.         }
  282.         else if (m_DrawFlags & PJAI_GRAYSCALE)
  283.         {   // convert the image to grayscale
  284.             GrayBmp = GrayScale(pDC, *pOutputDC->GetCurrentBitmap());
  285.             pOutputDC->SelectObject(GrayBmp);
  286.         }
  287.     }
  288.     else
  289.     {
  290.         ASSERT (FALSE);  // m_Flags improperly set (should never get here)
  291.     }
  292.     if (m_DrawFlags & PJAI_DISABLED)  // draw the image disabled
  293.         DitherBlt(pDC, left, top, width, height, pOutputDC);
  294.     else   // draw the image
  295.         pDC->BitBlt(left, top, width, height, pOutputDC, 0, 0, SRCCOPY);
  296.     // clean up after ourselves
  297.     if (savedTransparentDC)
  298.     {
  299.         TransparentDC.RestoreDC(savedTransparentDC);
  300.         TransparentDC.DeleteDC();
  301.     }
  302.     if (savedStretchDC)
  303.     {
  304.         StretchDC.RestoreDC(savedStretchDC);
  305.         StretchDC.DeleteDC();
  306.     }
  307.     memDC.RestoreDC(savedmemDC);
  308.     memDC.DeleteDC();
  309.     if (GrayBmp)
  310.         ::DeleteObject(GrayBmp);
  311. }
  312. /////////////////////////////////////////////////////////////////////////////
  313. //
  314. //  CPJAImage::DrawTransparent  (protected member function)
  315. //    transparently draws the image in the source device context onto the 
  316. //    destination device context 
  317. //
  318. //  Parameters :
  319. //    pToDC         [in] - pointer to the destination device context
  320. //    w             [in] - the width of the image
  321. //    h             [in] - the height of the image
  322. //    pFromDC       [in] - pointer to the source DC containing the bitmap to be drawn
  323. //
  324. //  Returns :
  325. //    Nothing
  326. //
  327. //  Note :
  328. //    Uses the 'True Mask' method
  329. //    Modified from code found at http://www.codeguru.com/bitmap/CISBitmap.shtml
  330. //    original author Paul Reynolds (Paul.Reynolds@cmgroup.co.uk)
  331. // 
  332. /////////////////////////////////////////////////////////////////////////////
  333. void CPJAImage::DrawTransparent(CDC *pToDC, int w, int h, CDC *pFromDC)
  334. {
  335.     // handle for the grayscale image
  336.     HBITMAP Gray = NULL;
  337.     CDC MonoDC;
  338.     MonoDC.CreateCompatibleDC(pToDC);
  339.     int savedToDC = pToDC->SaveDC();
  340.     int savedFromDC = pFromDC->SaveDC();
  341.     int savedMonoDC = MonoDC.SaveDC();
  342.     pToDC->SetBkColor(RGB(255, 255, 255));
  343.     pToDC->SetTextColor(RGB(0, 0, 0));
  344.     pFromDC->SetBkColor(m_TransparentColour);
  345.     // Create the mask
  346.     CBitmap MonoDCbmp;
  347.     MonoDCbmp.CreateBitmap(w, h, 1, 1, NULL);
  348.     MonoDC.SelectObject(&MonoDCbmp);
  349.     MonoDC.BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCCOPY);
  350.     if (m_DrawFlags & PJAI_GRAYSCALE)
  351.     {   // convert the image to grayscale. We do this here just
  352.         // in case the bitmap has a grayscale colour as the 
  353.         // transparent colour
  354.         Gray = GrayScale(pFromDC, *pFromDC->GetCurrentBitmap());
  355.         pFromDC->SelectObject(Gray);
  356.     }
  357.     // draw the transparent bitmap
  358.     pToDC->BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCINVERT);
  359.     pToDC->BitBlt(0, 0, w, h, &MonoDC, 0, 0, SRCAND);
  360.     pToDC->BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCINVERT);
  361.     MonoDC.RestoreDC(savedMonoDC);
  362.     pFromDC->RestoreDC(savedFromDC);
  363.     pToDC->RestoreDC(savedToDC);
  364.     MonoDC.DeleteDC();
  365.     if (Gray)
  366.         ::DeleteObject(Gray);
  367. }
  368. /////////////////////////////////////////////////////////////////////////////
  369. //
  370. //  CPJAImage::GetSize  (public member function)
  371. //    Gets the size of the image in pixels
  372. //
  373. //  Parameters :
  374. //    None
  375. //
  376. //  Returns :
  377. //    a CSize containing the size of the image
  378. //
  379. /////////////////////////////////////////////////////////////////////////////
  380. CSize CPJAImage::GetSize()
  381. {
  382.     return m_size;
  383. }
  384. /////////////////////////////////////////////////////////////////////////////
  385. //
  386. //  CPJAImage::Gray   (protected member function)
  387. //    Gets the grayscale value of the given colour
  388. //
  389. //  Parameters :
  390. //    r [in] - the red colour
  391. //    g [in] - the green colour
  392. //    b [in] - the blue colour
  393. //
  394. //  Returns :
  395. //    the grayscale value
  396. //
  397. /////////////////////////////////////////////////////////////////////////////
  398. int CPJAImage::Gray(int r, int g, int b)
  399. {
  400.     return (b * 11 + g * 59 + r * 30) / 100;
  401. }
  402. /////////////////////////////////////////////////////////////////////////////
  403. //
  404. //  CPJAImage::GrayScale   (protected member function)
  405. //    Creates a DIBSection that is the grayscale equivalant of the given bitmap
  406. //
  407. //  Parameters :
  408. //    pDC     [in] - a pointer to a DC used to build the colour table
  409. //    hBitmap [in] - the bitmap to turn grayscale
  410. //
  411. //  Returns :
  412. //    the HBITMAP of the new grayscale DIBSection
  413. //
  414. //  Note :
  415. //    when you are finished with the HBITMAP returned by this function
  416. //    you have to delete it with a call to ::DeleteObject()
  417. //
  418. //    This function does not change the transparent colour to grayscale.
  419. //
  420. /////////////////////////////////////////////////////////////////////////////
  421. HBITMAP CPJAImage::GrayScale(CDC *pDC, HBITMAP hBitmap)
  422. {
  423.     // get the bitmap's size and colour information
  424.     BITMAP bm;
  425.     ::GetObject(hBitmap, sizeof(BITMAP), &bm);
  426.     // create a DIBSection copy of the original bitmap
  427.     HBITMAP hDib = (HBITMAP)::CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG | LR_CREATEDIBSECTION);
  428.     
  429.     if (bm.bmBitsPixel < 16)
  430.     {   // bitmap has a colour table, so we modify the colour table
  431.         CDC memDC;
  432.         memDC.CreateCompatibleDC(pDC);
  433.         int SavedMemDC = memDC.SaveDC();
  434.         memDC.SelectObject(hDib);
  435.         int nColours = 1 << bm.bmBitsPixel;
  436.         RGBQUAD pal[256];
  437.         // Get the colour table
  438.         ::GetDIBColorTable(memDC.m_hDC, 0, nColours, pal);
  439.         // modify the colour table
  440.         for (int x = 0; x < nColours; x++)
  441.         {
  442.             if (!IsTransparent(pal[x].rgbRed, pal[x].rgbGreen, pal[x].rgbBlue))
  443.             {
  444.                 BYTE nGray = (BYTE)Gray(pal[x].rgbRed, pal[x].rgbGreen, pal[x].rgbBlue);
  445.                 pal[x].rgbRed = nGray;
  446.                 pal[x].rgbGreen = nGray;
  447.                 pal[x].rgbBlue = nGray;
  448.             }
  449.         }
  450.         // set the modified colour tab to the DIBSection bitmap
  451.         ::SetDIBColorTable(memDC.m_hDC, 0, nColours, pal);
  452.         
  453.         memDC.RestoreDC(SavedMemDC);
  454.         memDC.DeleteDC();
  455.         return hDib;
  456.     }
  457.     else
  458.     {   // the bitmap does not have a colour table, so we modify the bitmap bits directly
  459.         int Size = bm.bmHeight * bm.bmWidth;
  460.         
  461.         BITMAPINFO bmi;
  462.         bmi.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
  463.         bmi.bmiHeader.biHeight        = bm.bmHeight;
  464.         bmi.bmiHeader.biWidth         = bm.bmWidth;
  465.         bmi.bmiHeader.biPlanes        = 1;
  466.         bmi.bmiHeader.biBitCount      = bm.bmBitsPixel;
  467.         bmi.bmiHeader.biCompression   = BI_RGB;
  468.         bmi.bmiHeader.biSizeImage     = ((bm.bmWidth * bm.bmBitsPixel + 31) & (~31)) / 8 * bm.bmHeight;
  469.         bmi.bmiHeader.biXPelsPerMeter = 0;
  470.         bmi.bmiHeader.biYPelsPerMeter = 0;
  471.         bmi.bmiHeader.biClrUsed       = 0;
  472.         bmi.bmiHeader.biClrImportant  = 0;
  473.         
  474.         // Get the bitmaps data bits
  475.         BYTE *pBits = new BYTE[bmi.bmiHeader.biSizeImage];
  476.         VERIFY (::GetDIBits(pDC->m_hDC, hDib, 0, bm.bmHeight, pBits, &bmi, DIB_RGB_COLORS));
  477.         if (bm.bmBitsPixel == 32)
  478.         {
  479.             DWORD *dst=(DWORD *)pBits;
  480.             
  481.             while (Size--)
  482.             {
  483.                 if (!IsTransparent(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst)))
  484.                 {
  485.                     int nGray = Gray(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst));
  486.                     *dst = (DWORD)RGB(nGray, nGray, nGray);
  487.                 }
  488.                 dst++;
  489.            }
  490.         }
  491.         
  492.         else if (bm.bmBitsPixel == 24)
  493.         {
  494.             BYTE *dst=(BYTE*)pBits;
  495.             for (int dh = 0; dh < bm.bmHeight; dh++)
  496.             {
  497.                 for (int dw = 0; dw < bm.bmWidth; dw++)
  498.                 {
  499.                     if (!IsTransparent(dst[2], dst[1], dst[0]))
  500.                     {
  501.                         int nGray = Gray(dst[2], dst[1], dst[0]);
  502.                     
  503.                         dst[0]=(BYTE)nGray;
  504.                         dst[1]=(BYTE)nGray;
  505.                         dst[2]=(BYTE)nGray;
  506.                     }
  507.                     dst += 3;
  508.                 }
  509.                 // each row is DWORD aligned, so when we reach the end of a row, we
  510.                 // have to realign the pointer to point to the start of the next row
  511.                 int pos = (int)dst - (int)pBits;
  512.                 int rem = pos % 4;
  513.                 if (rem)
  514.                     dst += 4 - rem;
  515.             }
  516.         }
  517.         else if (bm.bmBitsPixel == 16)
  518.         {
  519.             WORD *dst=(WORD*)pBits;
  520.             
  521.             while (Size--)
  522.             {
  523.                 BYTE b = (BYTE)((*dst)&(0x1F));
  524.                 BYTE g = (BYTE)(((*dst)>>5)&(0x1F));
  525.                 BYTE r = (BYTE)(((*dst)>>10)&(0x1F));
  526.                 
  527.                 if (!IsTransparent(r, g, b))
  528.                 {
  529.                     int nGray = Gray(r, g, b);
  530.                     *dst = ((WORD)(((BYTE)(nGray)|((WORD)((BYTE)(nGray))<<5))|(((DWORD)(BYTE)(nGray))<<10)));
  531.                 }
  532.                 dst++;
  533.             }
  534.         }
  535.         // set the modified bitmap data bits to the DIBSection
  536.         ::SetDIBits(pDC->m_hDC, hDib, 0, bm.bmHeight, pBits, &bmi, DIB_RGB_COLORS);
  537.         delete[] pBits;
  538.         return hDib;
  539.     }
  540. }
  541. /////////////////////////////////////////////////////////////////////////////
  542. //
  543. //  CPJAImage::IsTransparent  (protected member function)
  544. //    checks if the given colour values make up the transparent colour for the bitmap
  545. //
  546. //  Parameters :
  547. //    r [in] - the red colour
  548. //    g [in] - the green colour
  549. //    b [in] - the blue colour
  550. //
  551. //  Returns :
  552. //    TRUE if the colour is the transparent colour
  553. //    FALSE if not
  554. //
  555. /////////////////////////////////////////////////////////////////////////////
  556. BOOL CPJAImage::IsTransparent(int r, int g, int b)
  557. {
  558.     if (!(m_DrawFlags & PJAI_TRANSPARENT))
  559.         return FALSE;
  560.     return  (RGB(r, g, b) == m_TransparentColour);
  561. }
  562. /////////////////////////////////////////////////////////////////////////////
  563. //
  564. //  CPJAImage::SetImage  (public member function)
  565. //    Sets the image and image flags
  566. //
  567. //  Parameters :
  568. //    Image [in] - a HANDLE of the image to set (either a HBITMAP or a HICON)
  569. //    Flags [in] - the flags that specify the type of image and how it is drawn
  570. //
  571. //  Returns :
  572. //    TRUE on success
  573. //    FALSE on failure
  574. //
  575. //  Note :
  576. //    See the PJAImage.h file for a description of the flags used
  577. //
  578. /////////////////////////////////////////////////////////////////////////////
  579. BOOL CPJAImage::SetImage(HANDLE Image, DWORD Flags)
  580. {
  581.     if (Image)
  582.     {   // verify flags
  583.         if (!((Flags & PJAI_BITMAP ? 1 : 0) ^ (Flags & PJAI_ICON ? 1 : 0)))
  584.         {
  585.             TRACE (_T("PJAI_Image::SetImage() : Must specify either PJAI_BITMAP or PJAI_ICON"));
  586.             ASSERT (FALSE);
  587.             return FALSE;
  588.         }
  589.     }
  590.     if (m_hImage && m_hImage != Image)
  591.     {
  592.         if (m_ImageFlags & PJAI_AUTODELETE)
  593.         {   // remove the old image
  594.             if (m_ImageFlags & PJAI_ICON)
  595.                 DestroyIcon((HICON)m_hImage);
  596.             else
  597.                 DeleteObject((HGDIOBJ)m_hImage);
  598.         }
  599.         m_hImage = NULL;
  600.         m_size.cx = 0;
  601.         m_size.cy = 0;
  602.         m_TransparentColour = CLR_DEFAULT;
  603.     }
  604.     if (Image)
  605.     {   // get the image dimensions
  606.         if (Flags & PJAI_BITMAP)
  607.         {
  608.             BITMAP bmp;
  609.             if (GetObject((HBITMAP)Image, sizeof(BITMAP), &bmp))
  610.             {
  611.                 m_size.cx = bmp.bmWidth;
  612.                 m_size.cy = bmp.bmHeight;
  613.             }
  614.         }
  615.         else if (Flags & PJAI_ICON)
  616.         {
  617.             ICONINFO iconinfo;
  618.             GetIconInfo((HICON)Image, &iconinfo);
  619.             BITMAP bmp;
  620.             if (GetObject(iconinfo.hbmMask, sizeof(BITMAP), &bmp))
  621.             {
  622.                 m_size.cx = bmp.bmWidth;
  623.                 m_size.cy = iconinfo.hbmColor ? bmp.bmHeight : bmp.bmHeight / 2;
  624.             }
  625.             // prevent a resource leak
  626.             DeleteObject(iconinfo.hbmColor);
  627.             DeleteObject(iconinfo.hbmMask);
  628.         }
  629.     }
  630.     m_hImage = Image;
  631.     m_ImageFlags = Flags;
  632.     return TRUE;
  633. }
  634. /////////////////////////////////////////////////////////////////////////////
  635. //
  636. //  CPJAImage::SetTransparentColour  (public member function)
  637. //    Set the colour to be used as the transparent colour 
  638. //
  639. //  Parameters :
  640. //    clr [in] - the colour to be used as the transparent colour
  641. //
  642. //  Returns :
  643. //    the old transparent colour
  644. //
  645. //  Note :
  646. //    If the colour is CLR_DEFAULT (the default), the colour of the
  647. //    top left pixel (0,0) is used as the transparent colour.
  648. //
  649. /////////////////////////////////////////////////////////////////////////////
  650. COLORREF CPJAImage::SetTransparentColour(COLORREF clr /*= CLR_DEFAULT*/)
  651. {
  652.     COLORREF oldclr = m_TransparentColour;
  653.     m_TransparentColour = clr;
  654.     return oldclr;
  655. }