代码是参考别人的,转化后的图片我用VC++6.0打开可以显示灰度图,但是直接用看图工具打开是全黑的
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<malloc.h>#define WIDTHBYTES(bits) (((bits)+31)/32*4)typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;FILE* pSrcBmpFile;
FILE* pDestBMpFile;/*************************************************/
/*BMP的文件头结构*/
/*************************************************/
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;//文件大小
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;//数据区的起始位置,基点是位图数据区相对文件头部的偏移量。单位为字节
} BITMAPFILEHEADER;/***********************************************/
/*BMP位图信息头结构*/
/***********************************************/
typedef struct tagBItMAPINFOHEADER
{
DWORD biSize;//本结构占用字节数。实际上该结构占用40个字节
LONG biWidth;//位图的高度,单位为像素
LONG biHeight;//位图的宽度,单位为像素
WORD biPlanes;//目标设备的平面数,约定必须为1
WORD biBitCount;//每个像素所需的位数
DWORD biCompression;//位图的压缩类型
DWORD biSizeImage;//位图大小,单位为字节
LONG biXPelsPerMeter;//水平分辨率,设为0
LONG biYPelsPerMeter;//垂直分辨率,设为0
DWORD biClrUsed;//位图实际使用的颜色表中的颜色数,设为0
DWORD biClrImportant;//位图显示过程中重要的颜色数,设为0
} BITMAPINFOHEADER;//该结构占用40个字节/************************************************/
/*彩色表*/
/************************************************/
typedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;void GetBmpHeader(BITMAPFILEHEADER*,BITMAPINFOHEADER*);
void ChangeBmpHeader(BITMAPFILEHEADER*,BITMAPINFOHEADER*);
void SetBmpHeader(const BITMAPFILEHEADER*,const BITMAPINFOHEADER*);
void SetRGBQUAD();
void RgbToGray();int main()
{
BITMAPFILEHEADER* bitHead;
BITMAPINFOHEADER* bitInfoHead;

if((pSrcBmpFile = fopen("apple.bmp","rb")) == NULL)
{
printf("Can't open source image!\n");
return -1;
}
if((pDestBMpFile = fopen("Done.bmp","wb")) == NULL)
{
printf("Can't open destination image!\n");
return -1;
}

bitHead = (BITMAPFILEHEADER* )malloc(sizeof(BITMAPFILEHEADER));
bitInfoHead = (BITMAPINFOHEADER* )malloc(sizeof(BITMAPINFOHEADER));

rewind(pSrcBmpFile);//获取文件头 GetBmpHeader(bitHead,bitInfoHead);

if(bitHead->bfType != 0x4d42)
{
printf("This image is not a bmp file!\n");
fclose(pSrcBmpFile);
fclose(pDestBMpFile);
return -1;
} RgbToGray();

fclose(pSrcBmpFile);
fclose(pDestBMpFile);
}void GetBmpHeader(BITMAPFILEHEADER* bitHead,BITMAPINFOHEADER* bitInfoHead)
{
fread(bitHead,sizeof(BITMAPFILEHEADER)-2,1,pSrcBmpFile);
fread(bitInfoHead,sizeof(BITMAPINFOHEADER),1,pSrcBmpFile);
}void ChangeBmpHeader(BITMAPFILEHEADER* bitHead,BITMAPINFOHEADER* bitInfoHead)
{
bitHead->bfType = 0x4d42;
//bitHead->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) + 640 * 480;
bitHead->bfSize = 4;
bitHead->bfReserved1 = 0;
bitHead->bfReserved2 = 0;
//bitHead->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
bitHead->bfOffBits = 0;
bitInfoHead->biSize = sizeof(BITMAPINFOHEADER);
bitInfoHead->biWidth = 640;
bitInfoHead->biHeight = 480;
bitInfoHead->biPlanes = 1;
bitInfoHead->biBitCount = 8;
bitInfoHead->biCompression = 0;
bitInfoHead->biSizeImage = 0;
bitInfoHead->biXPelsPerMeter = 0;
bitInfoHead->biYPelsPerMeter = 0;
bitInfoHead->biClrUsed = 0;
bitInfoHead->biClrImportant = 0; 
}void SetBmpHeader(const BITMAPFILEHEADER* bitHead,const BITMAPINFOHEADER* bitInfoHead)
{
fwrite(bitHead,sizeof(BITMAPFILEHEADER)-2,1,pDestBMpFile);
fwrite(bitInfoHead,sizeof(BITMAPINFOHEADER),1,pDestBMpFile);
}void SetRGBQUAD()
{
int i;
BYTE k = 0;
RGBQUAD rgbQuad[256];
for(i = 0;i < 256; i++)
{
rgbQuad[i].rgbBlue = k;
rgbQuad[i].rgbGreen = k;
rgbQuad[i].rgbRed = k;
rgbQuad[i].rgbReserved = (BYTE)0;
k++;
} fwrite(rgbQuad,256 * sizeof(RGBQUAD),1,pDestBMpFile);
}void RgbToGray()
{
int w,h,i;
BYTE r,g,b;
BYTE gray;
BYTE count32,count8;
BYTE bmpNull = 0;
BITMAPFILEHEADER* bitHead;
BITMAPINFOHEADER* bitInfoHead;
BITMAPFILEHEADER* bitDHead;
BITMAPINFOHEADER* bitDInfoHead; RGBQUAD* pRgb;
RGBQUAD rgb[256];

bitHead = (BITMAPFILEHEADER* )malloc(sizeof(BITMAPFILEHEADER));
bitInfoHead = (BITMAPINFOHEADER* )malloc(sizeof(BITMAPINFOHEADER));
bitDHead = (BITMAPFILEHEADER* )malloc(sizeof(BITMAPFILEHEADER));
bitDInfoHead = (BITMAPINFOHEADER* )malloc(sizeof(BITMAPINFOHEADER));
pRgb = (RGBQUAD* )malloc(sizeof(RGBQUAD));

rewind(pSrcBmpFile);
rewind(pDestBMpFile);
GetBmpHeader(bitHead,bitInfoHead);
ChangeBmpHeader(bitHead,bitInfoHead);
SetBmpHeader(bitHead,bitInfoHead);
SetRGBQUAD(); count32 = (4 - (bitInfoHead->biWidth * 4) % 4) % 4;
count8 = (4 - (bitInfoHead->biWidth) % 4) % 4;

for(h = bitInfoHead->biHeight - 1;h >= 0;h--)
{
for(w = 0;w < bitInfoHead->biWidth;w++)
{
fread(pRgb,sizeof(RGBQUAD),1,pSrcBmpFile);
if(feof(pSrcBmpFile))
{
break;
}
r = pRgb->rgbRed;
g = pRgb->rgbGreen;
b = pRgb->rgbBlue;
gray = ((BYTE)(r*0.299 + g*0.587 + b*0.114 + 0.5));
fwrite(&gray,sizeof(gray),1,pDestBMpFile);
}
fseek(pSrcBmpFile,count32,SEEK_CUR);
fwrite(&bmpNull,count8,1,pDestBMpFile);
}
}

解决方案 »

  1.   

    我这有个以前自己做的,在VC6.0下测试过
    main.cpp:
    #include <stdio.h>
    #include <windows.h>
    #include "To256Gray.h"int main()
    {
    //测试数据:分别是1、4、8、16、24、32位位图转换为8位灰度图 To256Gray("1_1.bmp","res_1.bmp");//
    To256Gray("1_4.bmp","res_4.bmp");//
    To256Gray("1_8.bmp","res_8.bmp");
    To256Gray("1_24.bmp","res_24.bmp");
    To256Gray("2_16.bmp","res_16.bmp");
    To256Gray("2_32.bmp","res_32.bmp"); return 0;
    }
    To256Gray.h:
    #ifndef _TO256GRAY_HEADER_FILE_
    #define _TO256GRAY_HEADER_FILE_//通用函数,将所有位的位图转换为8位灰度图
    bool To256Gray(const char *strSrc,const char *strDst);//将位数小于等于8的位图转换为8位灰度图
    bool FromLess8ToGray(const char *strSrc,const char *strDst);//将16位位图转换为8位灰度图
    bool From16ToGray(const char *strSrc,const char *strDst);//将24位或32位位图转换为8位灰度图
    bool From24or32ToGray(const char *strSrc,const char *strDst);#endif
      

  2.   

    To256Gray.cpp:
    /*
     *  将1、4、8、16、24、32位位图转换为8位灰度图
     * 如果要使用FromLess8To256Gray、From16ToGray、From24or32ToGray函数
     * 必须确保位图的位数符合函数要求,否则使用To256Gray函数,程序将自动
     * 选择需要转换的函数。
     *
     * 这些函数并不是所有都验证过,对于特殊的情况没有验证,没有验证的
     * 情况是:16位位图和32位位图的位图信息biCompression为BI_BITFIELDS。
     *
     * 还有没有处理的情况:当小于24位位图的压缩格式不是BI_RGB时(即位图
     * 信息参数biCompression的值不是BI_RGB),这些函数将会出错,但是这些
     * 情况很少。当前大部分图像的处理是没有问题的。
     */#include <cstring>
    #include <cstdio>
    #include <windows.h>
    #include "to256gray.h"//GetColorNum:取得颜色表的个数
    //参数:
    //  nBitCount:位图的象素颜色位数
    //  nClrUsed: 位图信息中的biClrUsed参数值
    //返回值:颜色表的个数
    inline int GetColorNum(const WORD nBitCount,const DWORD nClrUsed)
    {
    if (nClrUsed)//颜色表参数不为0
    {
    return nClrUsed;
    }
    if (nBitCount < 16)//如果位图位数小于16且使用的颜色表参数为0
    {
    return 1<<nBitCount;
    }
    return 0;
    }
    //FromLess8To256Gray:将1、4、8位位图转换为256灰度图
    //参数:
    //  strSrc:源图像文件名
    //  strDst:目标图像文件名bool FromLess8To256Gray(const char *strSrc,const char *strDst)
    {
    BITMAPFILEHEADER fileheader;       //文件头信息
    BITMAPINFOHEADER bmpinfo;    //位图信息 FILE *fSrc = fopen(strSrc,"rb");   //打开源文件
    if (!fSrc)
    {
    return false;
    }

    fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fSrc);   //读取文件头信息
    fread(&bmpinfo,sizeof(BITMAPINFOHEADER),1,fSrc);      //读取位图信息 const int nBytePel   = 8/bmpinfo.biBitCount;         //每字节的象素数
    const int nBitCount  = bmpinfo.biBitCount;           //每象素的位数 
    const int nSrcRowLen = ((bmpinfo.biWidth + nBytePel -1)/nBytePel + 3) & (~3);//源图像每行象素字节数
    const int nClrNum    = GetColorNum(bmpinfo.biBitCount,bmpinfo.biClrUsed);    //颜色表个数
    const int nRowLenght = (bmpinfo.biWidth + 3) & (~3); //每行的字节数 fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
    nClrNum * sizeof(RGBQUAD) + bmpinfo.biHeight * nRowLenght;//目标位图文件大小
    fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
    nClrNum * sizeof(RGBQUAD);   //目标位图图素信息偏移量 bmpinfo.biBitCount     = 8;      //目标位图位数
    bmpinfo.biClrImportant = 0;      //所有颜色表都重要
    bmpinfo.biClrUsed      = nClrNum;//共有nClrNum个颜色表
    bmpinfo.biCompression  = 0;      //不压缩
    bmpinfo.biSizeImage    = bmpinfo.biHeight * nRowLenght;//位图图素信息大小 FILE *fDst = fopen(strDst,"wb");   //打开目标文件
    if (!fDst)
    {
    return false;
    }
    fwrite(&fileheader,sizeof(BITMAPFILEHEADER),1,fDst); //写入文件头信息
    fwrite(&bmpinfo,   sizeof(BITMAPINFOHEADER),1,fDst); //写入位图头信息 RGBQUAD  clrSrc,clrDst;    //临时变量:源图像颜色表与目标图像颜色表
    BYTE     byteGray;         //临时变量:存放计算出的灰度图象素颜色信息
    clrDst.rgbReserved = 0;    //保留值改为0

    int i = 0; 
    for (i = 0; i < nClrNum; i++)                        //遍历源图像的颜色表并转换,然后写入目标文件
    {
    fread(&clrSrc,sizeof(RGBQUAD),1,fSrc);           //读取源图像的颜色表信息 byteGray = (BYTE)(0.299*clrSrc.rgbRed + 0.587*clrSrc.rgbGreen + 0.114*clrSrc.rgbBlue);//转换为灰度图像颜色
    clrDst.rgbBlue = clrDst.rgbGreen = clrDst.rgbRed = byteGray; fwrite(&clrDst,sizeof(RGBQUAD),1,fDst);          //将计算后的灰度图像颜色信息写入目标文件
    } BYTE *bufSrc = new BYTE[nSrcRowLen];
    BYTE *bufDst = new BYTE[nRowLenght];
    for (i = 0; i < bmpinfo.biHeight; i++)              //遍历图像的每行,并写入目标文件
    {
    fread(bufSrc,nSrcRowLen,1,fSrc);
    for (int j = 0; j < bmpinfo.biWidth; j++)
    {
    const BYTE *src    = bufSrc + j/nBytePel;
    const int   nShift = 8 - (j % nBytePel +1) * nBitCount;//移动的位数
    bufDst[j] = ( ( ( (1 << nBitCount) - 1) << nShift ) & (*src) ) >> nShift; 
    }
    fwrite(bufDst,nRowLenght,1,fDst);
    } fclose(fSrc);
    fclose(fDst);
    return true;
    }
    //From16ToGray:将16位位图转换为8位灰度图
    //参数:
    //参数:
    //  strSrc:源图像文件名
    //  strDst:目标图像文件名bool From16ToGray(const char *strSrc,const char *strDst)
    {
    BITMAPFILEHEADER fileheader;       //文件头信息
    BITMAPINFOHEADER bmpinfo;    //位图信息

    FILE *fSrc = fopen(strSrc,"rb");   //打开源文件
    if (!fSrc)
    {
    return false;
    }

    fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fSrc);//读取文件头信息
    fread(&bmpinfo,sizeof(BITMAPINFOHEADER),1,fSrc);   //读取位图信息 const int nCompress = (int)bmpinfo.biCompression;//压缩方式 const int nRowLenght = (bmpinfo.biWidth + 3) & (~3);//目标图像每行字节数
    const int nSrcRowLen = (bmpinfo.biWidth + 1) & (~1);//源图像每行 字数 DWORD dwMask[3] = { 0 };
    int   nShift[3] = { 0 };
    if (nCompress == BI_RGB)
    {
    fseek(fSrc,sizeof(RGBQUAD),SEEK_CUR);//跳过颜色表
    }
    else if (nCompress == BI_BITFIELDS)
    {
    fread(dwMask,3 * sizeof(DWORD),1,fSrc); //计算三个屏蔽色的右移位数
    int nTmp = 0;
    int nBit = 0;
    for (int i = 0; i < 3; i++)
    {
    for ( ; (dwMask[i] &  (1 << nShift[i]) ) == 0; nShift[i]++) ;
    }
    }
    else
    {
    return false;
    } fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
    256*sizeof(RGBQUAD) + nRowLenght*bmpinfo.biHeight;                   //目标位图文件大小
    fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);//目标位图象素数据偏移量 bmpinfo.biBitCount     = 8; //目标图像象素位数8
    bmpinfo.biClrUsed      = 0; //目标图像颜色表个数256
    bmpinfo.biClrImportant = 0; //目标图像颜色表中所有颜色都重要
    bmpinfo.biCompression  = 0; //目标图像不压缩
    bmpinfo.biSizeImage    = bmpinfo.biHeight*nRowLenght;//位图的大小 FILE *fDst = fopen(strDst,"wb");//打开目标文件
    if (!fDst)
    {
    return false;
    } fwrite(&fileheader,sizeof(BITMAPFILEHEADER),1,fDst);//写入文件头信息
    fwrite(&bmpinfo,sizeof(BITMAPINFOHEADER),1,fDst);//写入位图信息 RGBQUAD clr;    //临时变量:计算目标文件的颜色表
    memset(&clr,0,sizeof(RGBQUAD));
    int i = 0;
    for (i = 0; i < 256; i++)//写入颜色表信息
    {
    fwrite(&clr,sizeof(RGBQUAD),1,fDst);//将颜色表写入目标文件
    clr.rgbBlue++;
    clr.rgbGreen++;
    clr.rgbRed++;
    }

    WORD *bufSrc = new WORD[nSrcRowLen];     //源文件存放一行象素信息的缓冲区
    BYTE *bufDst = new BYTE[nRowLenght];     //目标文件存放一行象素信息的缓冲区 if (nCompress == BI_RGB)
    {
    for (i = 0; i < bmpinfo.biHeight; i++)   //遍历读取每行的象素信息,计算后存入目标文件
    {
    fread(bufSrc,nSrcRowLen*sizeof(WORD),1,fSrc);     //读取一行源图像的象素信息

    memset(bufDst,0,sizeof(nRowLenght)); //将目标行象素信息缓冲区清空,非必须
    int j = 0;
    int R = 0;
    int G = 0;
    int B = 0;
    for (j = 0; j < bmpinfo.biWidth; j++)//遍历一行的每个象素
    {
    R = (0x007C & bufSrc[j]) >> 2;
    G = ( ( (0xE003 & bufSrc[j]) >> 13 ) + ( (0xE003 & bufSrc[j]) << 3 ) );
    B = (0x1F00 & bufSrc[j]) >> 8; bufDst[j] = (BYTE)(0.114 * B + 0.587 * G + 0.299 * R);//转换为灰度象素值
    }

    fwrite(bufDst,nRowLenght,1,fDst);    //将行象素信息写入目的文件
    }
    }
    else if (nCompress == BI_BITFIELDS)
    {
    // clrSrc.
    for (i = 0; i < bmpinfo.biHeight; i++)   //遍历读取每行的象素信息,计算后存入目标文件
    {
    fread(bufSrc,nSrcRowLen*sizeof(WORD),1,fSrc);     //读取一行源图像的象素信息

    memset(bufDst,0,sizeof(nRowLenght)); //将目标行象素信息缓冲区清空,非必须
    int j = 0;
    int nElement[3] = {0};
    for (j = 0; j < bmpinfo.biWidth; j++)//遍历一行的每个象素
    {
    for (int k = 0; k < 3; k++)
    {
    nElement[k] = (dwMask[k] & bufSrc[j]) >> nShift[k];
    }
    bufDst[j] = (BYTE)(0.299 * nElement[0] + 0.587 * nElement[0] + 0.114 * nElement[0]);
    }

    fwrite(bufDst,nRowLenght,1,fDst);    //将行象素信息写入目的文件
    }
    }
    else 
    {
    //关闭源文件与目标文件
    fclose(fSrc);
    fclose(fDst);

    //释放存放象素信息的缓冲区
    delete[] bufSrc;
    delete[] bufDst; return false;
    }

    //关闭源文件与目标文件
    fclose(fSrc);
    fclose(fDst);

    //释放存放象素信息的缓冲区
    delete[] bufSrc;
    delete[] bufDst; return true;}
      

  3.   


    //From24or32ToGray:将24或32位位图转换为灰度图
    //参数:
    //  strSrc:源图像文件名
    //  strDst:目标图像文件名bool From24or32ToGray(const char *strSrc,const char *strDst)
    {
    BITMAPFILEHEADER fileheader;    //位图文件头信息
    BITMAPINFOHEADER bmpinfo;       //位图信息 FILE *fSrc = fopen(strSrc,"rb");//打开源文件
    if (!fSrc)
    {
    return false;
    }

    fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fSrc);   //读取位图文件头信息
    fread(&bmpinfo,sizeof(BITMAPINFOHEADER),1,fSrc);      //读取位图文件信息 const int nPelBytes = bmpinfo.biBitCount/8;           //每象素的字节数
    const int nCompress = bmpinfo.biCompression;          //压缩格式 DWORD dwMask[3] = { 0 };//如果有屏蔽色,保存(对于32位位图而言)
    int   nShift[3] = { 0 }; if (nCompress == BI_RGB)
    {
    if (nPelBytes == 4 || !bmpinfo.biClrUsed)//如果是32位位图或者颜色表个数为0
    {
    fseek(fSrc,sizeof(RGBQUAD),SEEK_CUR);//跳过颜色表
    }
    else if (bmpinfo.biClrUsed)//颜色表个数不为0
    {
    fseek(fSrc, bmpinfo.biClrUsed * sizeof(RGBQUAD), SEEK_CUR);//跳过信息表
    }
    }
    else if (nCompress == BI_BITFIELDS)
    {
    fread(dwMask,3 * sizeof(DWORD),1,fSrc);

    //计算三个屏蔽色的右移位数
    for (int i = 0; i < 3; i++)
    {
    for ( ; (dwMask[i] & (1 << nShift[i]) ) == 0; nShift[i]++) ;
    }
    }
    else
    {
    return false;
    } const int nRowLenght = (bmpinfo.biWidth + 3) & (~3);  //灰度图每行字节数
    fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
    256 * sizeof(RGBQUAD) + bmpinfo.biHeight*nRowLenght;//灰度图文件的大小
    fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);//图素信息偏移量 bmpinfo.biClrImportant = 0;//所有颜色都重要
    bmpinfo.biClrUsed      = 0;//共有256个颜色表
    bmpinfo.biBitCount     = 8;//每象素8位
    bmpinfo.biCompression  = 0;//不压缩
    bmpinfo.biSizeImage    = bmpinfo.biHeight*nRowLenght;//位图的大小

    FILE *fDst = fopen(strDst,"wb");//目标文件
    if (!fDst)
    {
    return false;
    } fwrite(&fileheader,sizeof(BITMAPFILEHEADER),1,fDst);//写入文件头信息
    fwrite(&bmpinfo,sizeof(BITMAPINFOHEADER),1,fDst);   //写入位图信息 RGBQUAD clr;    //临时变量:计算目标文件的颜色表
    memset(&clr,0,sizeof(RGBQUAD));
    int i = 0;
    for (i = 0; i < 256; i++)//写入颜色表信息
    {
    fwrite(&clr,sizeof(RGBQUAD),1,fDst);//将颜色表写入目标文件
    clr.rgbBlue++;
    clr.rgbGreen++;
    clr.rgbRed++;
    } const int nSrcRowLen = (bmpinfo.biWidth*nPelBytes + 3) & (~3);//源图像每行字节数 BYTE *bufSrc = new BYTE[nSrcRowLen];     //源文件存放一行象素信息的缓冲区
    BYTE *bufDst = new BYTE[nRowLenght];     //目标文件存放一行象素信息的缓冲区 if (nCompress == BI_RGB)
    {
    for (i = 0; i < bmpinfo.biHeight; i++)   //遍历读取每行的象素信息,计算后存入目标文件
    {
    fread(bufSrc,nSrcRowLen,1,fSrc);     //读取一行源图像的象素信息

    memset(bufDst,0,sizeof(nRowLenght)); //将目标行象素信息缓冲区清空,非必须
    int j = 0;
    for (j = 0; j < bmpinfo.biWidth; j++)//遍历一行的每个象素
    {
    bufDst[j] =
    (BYTE)(0.114 * bufSrc[j*nPelBytes] + 
    0.587 * bufSrc[j*nPelBytes+1]      +
    0.299 * bufSrc[j*nPelBytes+2] );//转换为灰度象素值
    }

    fwrite(bufDst,nRowLenght,1,fDst);    //将行象素信息写入目的文件
    }
    }
    else if (nCompress == BI_BITFIELDS)
    {
    for (i = 0; i < bmpinfo.biHeight; i++)   //遍历读取每行的象素信息,计算后存入目标文件
    {
    fread(bufSrc,nSrcRowLen,1,fSrc);     //读取一行源图像的象素信息

    memset(bufDst,0,sizeof(nRowLenght)); //将目标行象素信息缓冲区清空,非必须
    int j = 0;
    for (j = 0; j < bmpinfo.biWidth; j++)//遍历一行的每个象素
    {
    int nElement[3];
    for (int k = 0; k < 3; k++)
    {
    nElement[k] = (dwMask[k] & bufSrc[j]) >> nShift[k];
    }
    bufDst[j] = (BYTE)(0.299 * nElement[0] + 0.587 * nElement[0] + 0.114 * nElement[0]);
    }

    fwrite(bufDst,nRowLenght,1,fDst);    //将行象素信息写入目的文件
    }
    }
    else
    {
    //关闭源文件与目标文件
    fclose(fSrc);
    fclose(fDst);

    //释放存放象素信息的缓冲区
    delete[] bufSrc;
    delete[] bufDst; return false;
    }
    //关闭源文件与目标文件
    fclose(fSrc);
    fclose(fDst); //释放存放象素信息的缓冲区
    delete[] bufSrc;
    delete[] bufDst; return true;
    }
    //To256Gray:将一个图像转换为256色灰度图
    //参数:
    //  strSrc:源图像文件名
    //  strDst:目标图像文件名bool To256Gray(const char *strSrc,const char *strDst)
    {
    if (strcmp(strSrc,strDst) == 0)//如果源文件与目标文件相同,直接退出并返回错误
    {
    return false;
    } BITMAPFILEHEADER fileheader;     //图像文件头信息
    BITMAPINFO       bmpinfo;        //图像信息

    FILE *fSrc = fopen(strSrc,"rb"); //打开源图像信息
    if (!fSrc)                       //如果打开失败,直接返回错误
    {
    return false;
    }

    fread(&fileheader,sizeof(BITMAPFILEHEADER),1,fSrc);//读取文件信息
    if (fileheader.bfType != 0x4D42)//如果不是位图文件
    {
    return false;
    }
    fread(&bmpinfo,sizeof(BITMAPINFO),1,fSrc);//读取图像信息 fclose(fSrc);  //关闭源文件
    switch (bmpinfo.bmiHeader.biBitCount)
    {
    case 1:     //单色图像
    case 4:    
    case 8:
    {
    return FromLess8To256Gray(strSrc,strDst);
    }
    break;
    case 16:
    {
    return From16ToGray(strSrc,strDst);
    }
    break;
    case 24:
    case 32:
    {
    return From24or32ToGray(strSrc,strDst);
    }
    break;
    default:
    return false;
    break;
    } return false;
    }
      

  4.   

    1楼强!!!gray = ((BYTE)(r*0.299 + g*0.587 + b*0.114 + 0.5));
    单步看这个值
      

  5.   

    我试过用opencv转换,然后把opencv转的和我自己转的所有东西都读出来,一样的
      

  6.   

    如果用图像工具打开是黑色的,那么是不是应该把所有的R,G,B全部都弄出来,绘成一幅图(不能只取一个值,三个值都要取,且都相等)。
    或者如果是BMP的图像,你的图像大小变成原图的1/3大小啊。这样应该没问题。
    如果不加文件头的话,你的图片应该可以用PS打开,后缀改成RAW。代码没看,只是分析你的问题应该是这样的,说错了就当没说。哈哈。
      

  7.   

    奇怪,我用这段代码在ubuntu下跑结果全黑的,但是在VC++6.0下跑结果是灰度图,但是只能看到右边三分之二左右
      

  8.   

    1楼的谢谢你的代码,我copy去学习一下,不好意思,到现在才回复你