本帖最后由 yiqitoudonggua 于 2013-05-08 20:53:38 编辑

解决方案 »

  1.   

    现在的问题是因为用的类中指向数据的指针是LPBYTE* m_lpData,而看的资料上都是LPBYTE* m_lpData这 
      

  2.   

    资料上写的都是LPBYTE m_lpData,很窝心现在
      

  3.   

    用图像开源库一个函数就能实现,如OpenCV,CxImage等
      

  4.   

    是的
    OpenCV一个函数就搞定
      

  5.   

    先看这个是GDI+做的,待会发个一般的,不用GDI+给你看看。。http://blog.csdn.net/hemmingway/article/details/8904820
      

  6.   

    这里假设用GDI+ =读取的24为彩色,图像,然后把它转为8bpp的灰度图像,bmp文件格式
    http://blog.csdn.net/hemmingway/article/details/8909662
    // BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
    // 功能:保存图片为8位的灰度图像
    // 参数: pszPath要保存的文件名
    BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
    {
    Bitmap *ima = this->m_pBitmap; // GDIPlusImage的Bitmap对象 if (!ima || !pszPath || !*pszPath)
    {
    return FALSE;
    } int width = m_pBitmap->GetWidth();
    int height = m_pBitmap->GetHeight();
    int bitcount = 8; //1, 4, 8, 24, 32 //////////////////////////////////////////////////////////////////////////
    //Build bitmap header
    BITMAPFILEHEADER bitmapFileHeader; 
    BITMAPINFOHEADER bitmapInfoHeader; 
    BYTE  rgbquad[4]; // RGBQUAD
    int  index = 0; DWORD stride = ((bitcount*width + 31)/32)*4; //每行都是4的倍数,或者说是DWORD大小的倍数 switch(bitcount) { 
    case 1: 
    index = 2; 
    bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4); 
    break; 
    case 4: 
    index = 16; 
    bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4); 
    break; 
    case 8: 
    index = 256; 
    bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)); 
    break; 
    case 24: 
    case 32: 
    index = 0; 
    bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); 
    break; 
    default:
    break;
    }  //构造Bitmap文件头BITMAPFILEHEADER 
    bitmapFileHeader.bfType = 0x4d42;    // 很重要的标志位  BM 标识
    bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * stride); //bmp文件长度  
    bitmapFileHeader.bfReserved1 = 0; 
    bitmapFileHeader.bfReserved2 = 0;  //构造Bitmap文件信息头BITMAPINFOHEADER 
    bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bitmapInfoHeader.biWidth = width; 
    bitmapInfoHeader.biHeight = height; 
    bitmapInfoHeader.biPlanes = 1; 
    bitmapInfoHeader.biBitCount = bitcount;
    bitmapInfoHeader.biCompression = BI_RGB; // 未压缩
    bitmapInfoHeader.biSizeImage = height * stride; 
    bitmapInfoHeader.biXPelsPerMeter = 3780; 
    bitmapInfoHeader.biYPelsPerMeter = 3780; 
    bitmapInfoHeader.biClrUsed = 0; 
    bitmapInfoHeader.biClrImportant = 0;  //创建BMP内存映像,写入位图头部
    BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize]; // 我的位图pMyBmp
    BYTE *curr = pMyBmp; // curr指针指示pMyBmp的位置
    memset(curr, 0, bitmapFileHeader.bfSize);  //写入头信息 
    memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));
    curr = pMyBmp + sizeof(BITMAPFILEHEADER); 
    memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); 
    curr += sizeof(BITMAPINFOHEADER); //构造调色板 
    if(8 == bitcount) 
    {
    rgbquad[3] = 0; //rgbReserved
    for(int i = 0; i < 256; i++) 

    rgbquad[0] = rgbquad[1] = rgbquad[2] = i; 
    memcpy(curr, rgbquad, sizeof(RGBQUAD)); 
    curr += sizeof(RGBQUAD); 

    }else if (4 == bitcount)
    {
    rgbquad[3] = 0;
    for (int i = 0; i < 16; i++)
    {
    rgbquad[0] = rgbquad[1] = rgbquad[2] = i; 
    memcpy(curr, rgbquad, sizeof(RGBQUAD)); 
    curr += sizeof(RGBQUAD); 
    }
    }
    else if(1 == bitcount) 

    rgbquad[3] = 0; //rgbReserved
    for(int i = 0; i < 2; i++) 

    rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256; 
    memcpy(curr, rgbquad, sizeof(RGBQUAD)); 
    curr += sizeof(RGBQUAD); 

    } //用GDI+加载数据源,也可以是其他的,写入文件数据
    Rect rect(0,0,width,height); // Gdiplus+
    BitmapData bmData;
    Status iSucess = ima->LockBits(
    &rect,
    ImageLockModeRead,
    ima->GetPixelFormat() ,
    &bmData); BYTE *_pixels = (BYTE*)bmData.Scan0; //原图rect区域内存位置的起始指针,以BYTE作为单元类型
    BYTE *_pColEnd, *_pRow;
    int _strideoff8 = stride - width; //前面计算的索引图像的stride
    BYTE _grey; // build pixles, GDI+ 有个很操蛋的毛病,自定义存放数据需要水平加垂直镜像,要从数据的末尾读取数据
    switch(ima->GetPixelFormat())
    {
    case PixelFormat24bppRGB:
    {
    //  灰度化
    for (int i=height; i > 0; i--)
    {
    _pRow = _pixels + i*bmData.Stride; // 当前的行
    _pColEnd = _pRow + 3*width; // width是像素单位,而一个像素占三个字节,所以要乘以3
    for (int j=width; j > 0; j--)
    {
    BYTE* _pixels_b; //b
    BYTE* _pixels_g; //g
    BYTE* _pixels_r; //r

    _pixels_b = _pColEnd--;  //blue
    _pixels_g = _pColEnd--;  //green
    _pixels_r = _pColEnd--;  //red _grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b);  *curr = _grey;    //根据红绿蓝求出此像素的灰度值
    curr++;
    }
    curr += _strideoff8;
    }
    }
    break; case PixelFormat32bppARGB:
    {
    //  灰度化
    for (int i=height;i>0;i--)
    {
    _pRow = _pixels + i*bmData.Stride;
    _pColEnd = _pRow + 4*width; // 跳到当前行的末尾去
    for (int j=width;j>0;j--)
    {
    BYTE* _pixels_b;
    BYTE* _pixels_g;
    BYTE* _pixels_r; _pixels_b = _pColEnd--;  //blue
    _pixels_g = _pColEnd--;  //green
    _pixels_r = _pColEnd--;  //red
    _pColEnd--; _grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b);  *curr = _grey;
    curr++;
    }
    curr += _strideoff8;
    }
    }
    break;
    case PixelFormat8bppIndexed:  // Gdi+只能保存成24位真彩色的图像
    {
    // 不能直接用memcpy复制,需要水平镜像,memcpy(curr, _pixels, height * stride);
    for (int i=height; i > 0; i--)
    {
    _pRow = _pixels + i*stride; // width是像素单位,而一个像素占三个字节,所以要乘以3
    _pColEnd = _pRow + width;
    for (int j=width;j > 0;j--)
    {
    _grey = *_pColEnd--; 
    *curr = _grey;    //根据红绿蓝求出此像素的灰度值
    curr++;
    }
    curr += _strideoff8;
    }
    }
    break;
    default:
    break;
    } // 保存图像 pMyBmp 到文件
    try
    {
    CFile f(pszPath, CFile::modeCreate | CFile::modeWrite );
    f.Write(pMyBmp, bitmapFileHeader.bfSize);
    f.Close();
    }
    catch( CFileException* e )
    {
    TCHAR szCause[255];
    e->GetErrorMessage(szCause, 255); CString msg;
    msg.Format(_T("file error: %s, m_cause:%d\n"),szCause, e->m_cause); TRACE1("%s",msg);
    AfxMessageBox(msg);
    e->Delete();
    } //clean:
    ima->UnlockBits(&bmData);
    delete[] pMyBmp; return FALSE;
    }
      

  7.   

    1. 首先说明一下。LPBYTE* m_lpData与LPBYTE m_lpData的差别。你也知道图像数据是有长和高的。如果你要把长,高分别开来,你就定义一个二维数组,char data[height][width*3].那么这个定义就是LPBYTE *m_lpData的定义方式。如果不加区分,就是 char data[height*width*3].那么data就是 LPBYTE m_lpData.的定义方式。这里假定图像是采用24为的RGB的格式。2. 24位真彩图变成灰度图,数据量少了3倍。新图像的数据区就为char data[height][width]/或者char data[height*width].3. 我记得8位灰度是没有调色板的。因为八位都能表示0~255了。只有低于8位才需要。比如只有一位,你就得弄个调色板0表示灰度0,1表示灰度255.(这一点不是很能确定了,因为2年多没有搞了)4. 数据存放的顺序。如果你都是按标准做的话,最后一行的数据在数据区的最前面,依次类推,第一行在最后。每一行的最左边在前面,右边在后面。位图显示信息有一个字段指示显示方式的。