24位Bitmap 转成 灰度? 怎么写?  请各位帮忙。 bitmapgdi+灰度

解决方案 »

  1.   

    把RGB三色, 按亮度公式,即可转换成灰度图.  转换后的图可保存为8位位图, 也可以保存成24位图, 只是RGB三个都保存前面计算的亮度值. 如亮度值计算结果为 128, 则有 R=128, G=128,B=128, 这样填充回位图中, 即可变成灰度图了.
      

  2.   

    给你一段GDI代码:// Show “Gray.bmp”
    void CImageProcessingDoc::OnGrayRight() 
    {
    // TODO: Add your command handler code here
    #ifndef USE_FILE
    MakeGrayFromLeft();
    #else
    // Load the BitMap
    if(m_hBmpRight)
    {
    DeleteObject(m_hBmpRight);
    m_hBmpRight=0;//LR_CREATEDIBSECTION | 
    }
    m_hBmpRight=(HBITMAP)LoadImage(AfxGetInstanceHandle(),"Gray.bmp",IMAGE_BITMAP,0,0,
    LR_DEFAULTSIZE | LR_LOADFROMFILE);
    #endif
    if(m_hBmpRight==0) return;
    //
    BITMAP  bmp;
    ::GetObject(m_hBmpRight,sizeof(BITMAP),&bmp);
    // tell left view to show this bitmap
    CImageProcessingView *pRight=((CMainFrame*)AfxGetMainWnd())->GetRightPane(); // left  ScrollView
    SIZE sizeTotal;
    sizeTotal.cx=bmp.bmWidth+10;//gap
    sizeTotal.cy=bmp.bmHeight+10;
    pRight->SetScrollSizes(MM_TEXT,sizeTotal);
    pRight->Invalidate();
    pRight->UpdateWindow();

    }
      

  3.   

    sorry, 复制错了://
    BOOL CImageProcessingDoc::MakeGrayFromLeft()
    {
    DIBSECTION ds;
    //
    int dsSize=GetObject(m_hBmpLeft, sizeof(DIBSECTION), &ds);//0x54
    if ((dsSize == sizeof(ds)) && ds.dsBm.bmBits)
    {//
    OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    if (GetVersionEx(&osvi))
    {
    if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
    {
    ds.dsBm.bmWidthBytes = (ds.dsBm.bmWidthBytes + 3) & ~3;
    }
    }
    }
    //
    int BytesPerPixel = ds.dsBm.bmBitsPixel/8;
    int padding=ds.dsBm.bmWidthBytes - ds.dsBm.bmWidth*BytesPerPixel;//=2
    if  (BytesPerPixel < 3) return FALSE;
    //
    int DibSize=ds.dsBm.bmHeight * ds.dsBm.bmWidthBytes;
    BYTE  *pDibBuffer=(BYTE *)new BYTE[DibSize];
    BYTE  *pTmp=pDibBuffer;// for moving
    BYTE  *pEnd=pTmp+DibSize;
    BYTE  *pPix=(BYTE*)(ds.dsBm.bmBits);
    //
    BYTE  grey;
    while(pTmp<pEnd)
    {// 
    for(int jj=0; jj < ds.dsBm.bmWidth; jj++)
    {//  An excellent greyscale calculation is: normal 3 bytes
     // grey =(30 * (*(pPix+2)) + 59 * (*(pPix+1)) + 11 * (*pPix)) / 100;
     // This is a bit too slow so a faster calculation is:
    grey = ( pPix[2] + pPix[1] ) / 2;// (red + green) / 2;
    *pTmp++ = grey;
    *pTmp++ = grey;
    *pTmp++ = grey;
    pPix   += BytesPerPixel;//=3
    }
    for(int pp=0;pp<padding;pp++)
    {// has padding such as "Protell.bmp"
    *pTmp++ =0;
    pPix ++;
    }
    }
    // make bmp 
    if(m_hBmpRight)
    {
    DeleteObject(m_hBmpRight);
    m_hBmpRight=0;
    }
    BITMAPINFO bmi;
    ZeroMemory(&bmi,sizeof(bmi));
    CopyMemory(&bmi.bmiHeader,&ds.dsBmih, sizeof(BITMAPINFOHEADER));
    // must 
    HDC dc=GetWindowDC(0);
    m_hBmpRight=::CreateDIBitmap(dc, &ds.dsBmih, CBM_INIT, pDibBuffer,&bmi, DIB_RGB_COLORS);
    ReleaseDC(0,dc);
    //
    if(pDibBuffer)  delete []pDibBuffer;
    if(m_hBmpRight) return TRUE;
    else return FALSE;

    关键:
    grey = ( pPix[2] + pPix[1] ) / 2;// (red + green) / 2;
      

  4.   

    http://blog.csdn.net/mydreamremindme/article/details/9909141
      

  5.   

    用gdi+的graphics.drawimage画一个新的bmp
    灰度用color矩阵变换
      

  6.   

    贴一个控制台的图像转灰度并保存的完整代码。
    其中转换部分的代码简单,但速度不快,适用1次性转换。
    实时窗口中绘图如需要高速的情况下,用lockbit一个个算,然后bitblt。
    //24bit-jpeg转成24bit-灰度jpeg
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <windows.h>
    #include <gdiplus.h>
    #pragma comment(lib, "gdiplus.lib")using namespace std;
    using namespace Gdiplus;int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);int wmain()
    {
    GdiplusStartupInput gdiplusstartupinput;
    ULONG_PTR gdiplustoken;
    GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, nullptr);

    wstring infilename(L"1.jpg");
    wstring outfilename(L"2.jpg");
    //读图片
    Bitmap* srcbmp = new Bitmap(infilename.c_str());
    UINT cheight = srcbmp->GetHeight();
    UINT cwidth = srcbmp->GetWidth();

    //建立一张bitmap
    Bitmap* destbmp = new Bitmap(cwidth, cheight, srcbmp->GetPixelFormat());

    //建立新bitmap的graphics对象
    Graphics* pgs = new Graphics(destbmp);

    //颜色转灰度的矩阵
    //亮度公式 gray = G * 0.299 + G * 0.587 + B * 0.144
    ColorMatrix colormatrix = 
    {
    0.299f, 0.299f, 0.299f, 0.0f, 0.0f,
    0.587f, 0.587f, 0.587f, 0.0f, 0.0f,
    0.144f, 0.144f, 0.144f, 0.0f, 0.0f,
    0.000f, 0.000f, 0.000f, 1.0f, 0.0f,
    0.000f, 0.000f, 0.000f, 0.0f, 1.0f
    };

    ImageAttributes* pimageattributes = new ImageAttributes;
    pimageattributes->SetColorMatrix(&colormatrix, 
                                     ColorMatrixFlagsDefault, 
     ColorAdjustTypeBitmap);

    //转换成灰度并绘制在新的bmp上
    pgs->DrawImage(srcbmp, 
       Rect(0, 0, cwidth, cheight), 
       0, 0, cwidth, cheight,
       UnitPixel,
       pimageattributes);

    //获取编码器的类标识符
    CLSID encoderclsid;
    GetEncoderClsid(L"image/jpeg", &encoderclsid);

    //保存jpeg需要设置的参数
    ULONG quality(100);  //设置jpg压缩等级,100是最小压缩, 0最大压缩。
    EncoderParameters encoderparameters;
    encoderparameters.Count = 1;
    encoderparameters.Parameter[0].Guid = EncoderQuality;
    encoderparameters.Parameter[0].Type = EncoderParameterValueTypeLong;
    encoderparameters.Parameter[0].NumberOfValues = 1;
    encoderparameters.Parameter[0].Value = &quality;

    //保存图像到文件
    Status stat = destbmp->Save(outfilename.c_str(), 
    &encoderclsid, 
    &encoderparameters); if (stat == Ok)
    wcout << outfilename << L" saved successfully.\n";
    else
    wcout << outfilename << L" save failed with error " << GetLastError() << endl;

    delete pimageattributes;
    delete pgs;
    delete destbmp;
    delete srcbmp;
    GdiplusShutdown(gdiplustoken);
    return 0;
    }int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
       UINT  num = 0;          // number of image encoders
       UINT  size = 0;         // size of the image encoder array in bytes   ImageCodecInfo* pImageCodecInfo = NULL;   GetImageEncodersSize(&num, &size);
       if(size == 0)
          return -1;  // Failure   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
       if(pImageCodecInfo == NULL)
          return -1;  // Failure   GetImageEncoders(num, size, pImageCodecInfo);   for(UINT j = 0; j < num; ++j)
       {
          if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
          {
             *pClsid = pImageCodecInfo[j].Clsid;
             free(pImageCodecInfo);
             return j;  // Success
          }    
       }   free(pImageCodecInfo);
       return -1;  // Failure
    }