碰到这个问题后,四处找资料,终于在codeproject上找到一个例子,http://www.codeproject.com/bitmap/RplColor.asp,但它的例子下不下来,且它的实现实在不好用,所有自己写了一个,可能不对,请大家修改:用法: 先在设备DC上画好图,再将设备DC传入pDC, 确定rc, rcOld, rcNew就可以了。
疑问:我先实现的思路是先在函数外部将图画在一个 memDC上,再传入 memDC处理好图,再用真正的DC画memDC.但这样不行,大家可以试一下,不知道为何,是不是memDC有什么局限。void CImageView::ReplaceColor(CDC *pDC, CRect rc, COLORREF crOld, COLORREF crNew)
{
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bmpMem, * pbmpMem; // 初始化BITMAPINFO信息,以便使用CreateDIBSection
    BITMAPINFO RGB32BitsBITMAPINFO; 
    ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
    RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    RGB32BitsBITMAPINFO.bmiHeader.biWidth= rc.Width();
    RGB32BitsBITMAPINFO.bmiHeader.biHeight= rc.Height();
    RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
    RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;
    UINT * ptPixels;        HBITMAP DirectBitmap = CreateDIBSection(memDC,
                                  (BITMAPINFO *)&RGB32BitsBITMAPINFO, 
                                  DIB_RGB_COLORS,(void **)&ptPixels, NULL, 0);
    if (DirectBitmap)
    {
bmpMem.Attach(DirectBitmap);
pbmpMem = memDC.SelectObject(&bmpMem);
memDC.BitBlt(0, 0, rc.Width(), rc.Height(), pDC, rc.left, rc.top, SRCCOPY);
        // 转换 COLORREF 为 RGB
        COLORREF cOldColor=COLORREF2RGB(crOld);
        COLORREF cNewColor=COLORREF2RGB(crNew);        // 替换颜色
        for (int i=((rc.Width() * rc.Height() ) -1 );i>=0;i--)
        {
            if (ptPixels[i]==cOldColor) ptPixels[i]=cNewColor;
        }
        
pDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memDC, 0, 0, SRCCOPY);
    } memDC.SelectObject(pbmpMem);
}

解决方案 »

  1.   

    把它的rgb读出来
    改个值不就行了
      

  2.   

    你试一下 :)http://expert.csdn.net/Expert/topic/1388/1388007.xml?temp=.4502222
      

  3.   

    //THIS NEEDS TO BE TESTED
    BYTE* pData = (BYTE*)lpDibBits + (m_nHeight-1-y)*m_nScanWidth + x*3;
      

  4.   

    // 这是我在知道Alpha 之前写的透明绘图代码,
    //  后来发现不如Alpha 窗体快,这段代码就没用,
    //  但其中计算像素点的算法可以参考 :-)
    // Panr 2003-01-24 19:51
    #define FULL_POINT_OF_TRANSPARENT    (100)#define FULL_PRECENT_BINARY          (256)
    #define FULL_PRECENT_BINARY_DIGIT    (8)
    #define WIDTHBYTES(bits)             (((bits) + 31) / 32 * 4)#include "math.h"
    BOOL MixBitmap (BITMAP *pDC, CRect rcDC, BITMAP *pSc, CPoint ptLTSc, int nPrecent)
    {
      BYTE      *lpDC,  *lpSc;
      int        nDCX,  nDCY;
      int        nScX,  nScY;  if (nPrecent<0  ||  nPrecent>FULL_POINT_OF_TRANSPARENT)
        return false;  if (!pDC->bmBits  ||  !pSc->bmBits)
        return false;  CRect  rcTemp;
      rcTemp.SetRect (-1,-1, pDC->bmWidth+1, pDC->bmHeight+1);
      if (  !rcTemp.PtInRect (rcDC.TopLeft ())
        ||  !rcTemp.PtInRect (rcDC.BottomRight ()))
      {
        return false;
      }  rcTemp.SetRect (-1,-1, pSc->bmWidth+1, pSc->bmHeight+1);
      if (  !rcTemp.PtInRect (ptLTSc)
        ||  !rcTemp.PtInRect (ptLTSc + rcDC.Size ()))
      {
        return false;
      }  if (nPrecent == 0  ||  rcDC.IsRectEmpty ())
        return true;  if (nPrecent == FULL_POINT_OF_TRANSPARENT)
      {
        // BitBlt with more convenience.
        // it's needn't to pruduct
        //  BITMAP struct from target dc.
        ASSERT (false);    // call some other routing. 
        return true;
      }  ASSERT (FULL_PRECENT_BINARY  ==  pow(2, FULL_PRECENT_BINARY_DIGIT));
      nPrecent  = ::MulDiv (nPrecent, FULL_PRECENT_BINARY, 100);  const int  nBytePerPixelDC  = pDC->bmBitsPixel / 8;
      const int  nBytePerPixelSc  = pSc->bmBitsPixel / 8;
      const int  nBytePerScanDC   = WIDTHBYTES (pDC->bmWidth * pDC->bmBitsPixel);
      const int  nBytePerScanSc   = WIDTHBYTES (pSc->bmWidth * pSc->bmBitsPixel);
      // the mix loop. 
      nDCY    = rcDC.top;
      nScY    = ptLTSc.y;
      for (; nDCY<rcDC.bottom; nDCY++, nScY++)
      {
        nDCX  = rcDC.left;
        nScX  = ptLTSc.x;    lpDC  = ((BYTE*)pDC->bmBits) + nDCY * nBytePerScanDC + nDCX * nBytePerPixelDC;
        lpSc  = ((BYTE*)pSc->bmBits) + nScY * nBytePerScanSc + nScX * nBytePerPixelSc;
        for (; nDCX<rcDC.right; nDCX++, nScX++)
        {
          {
            // contents in *pDC and *pSc, besides the bit pointer, do not be verified. 
            lpDC[0] += ((lpSc[0]-lpDC[0]) * nPrecent) >> FULL_PRECENT_BINARY_DIGIT;
            lpDC[1] += ((lpSc[1]-lpDC[2]) * nPrecent) >> FULL_PRECENT_BINARY_DIGIT;
            lpDC[2] += ((lpSc[2]-lpDC[2]) * nPrecent) >> FULL_PRECENT_BINARY_DIGIT;
          }      lpDC  += nBytePerPixelDC;
          lpSc  += nBytePerPixelSc;
        }
      }  return true;
    }
      

  5.   

    To  Panr(光荣)
       你的BITMAP结构怎么得到的。如果用GetBitmap()得到的话,好像bmBits指向空。所以不可能直接改写位图数据。只能再创建一个位图,用CreateDIBSection()创建,可以直接修改数据。
      

  6.   

    代码好像有点问题,没有考虑 4bytes 对齐的情况,可能在处理有些图像的时候效果不对
      

  7.   

    to oiq(oiq):
    如果用CBitmap 加载进来的话,可以用CBitmap::GetBitmapBits 获得数据to gboy(★)(★):
    BYTE* pData = (BYTE*)lpDibBits + (m_nHeight-1-y)*m_nScanWidth + x*3;
    该算法是我在CodeProject 上的一处代码中发现的,我的确没看过专门的介绍BytePerPixel 算法的文章,你可以介绍个例子或文章么,先谢了
    我们接触的程序都是RGB24bit 来处理像素的,我觉得不太有人会把bitmap 的image 做成32 bit对齐,那不是白白浪费1/3 的空间么,而图片的体积本来就是很大的
      

  8.   

    to oiq(oiq):
    我是用内存DC 的,一加载后就把图片数据保持在那里,处理时也直接对数据操作
    OnPaint 时只是copy 到窗体上用数据结构而不是CBitmap 保存数据,是为了避免多线程间传递时出问题
      

  9.   

    TO Panr:
        你可以先将源图画到一个24位的图上面,用我上面的方法就可以,我上面的方法是画到了一个32位上,所以计算时用UINT,
        用GetBitmapBits()函数我也想过,使用它得先取得当前设备的位数,所以干脆就先将它画到一个32位上,这样处理更方便。
      

  10.   

    ...../' \\   //\\ 
         \\  // `\ 
          \\ //           祝楼主:
         .-'^'-. 
        .' a___a `.           春节愉快 合家欢乐!
        == (___) == 
        '. ._I_. .'           心想事成 红包拿来!
      ____/.`-----'.\____ 
      [###(__)####
      

  11.   

    to Panr(光荣) 4bytes 对齐和算法无关,
    dib 图像的每行的所占的内存不一定是 width*BytesPerPixel。
    行所占内存大小应该是一个 4 的倍数.比如一个 24bit 图像,宽度是 10 每行所占内存应该是 3*10+2=32, 而不是 3*10.
      

  12.   

    to gboy(★)(★):
    你可以看我的代码呀,我计算行时的大小时没有直接乘啊,是用WIDTHBYTES 的嘛