请问一下一个BMP格式的二值图像的像素是用一个字节表示的还是用一个位表示的呀?如果用一个位表示一个像素,那怎么访问像素呢?

解决方案 »

  1.   

    参考
    /*参数说明:
    *strSrc——源文件(8位bmp灰度图)
    *strDst——目标文件(1位bmp二值图) // 一字节 8个 点
    *threshold——阈值
    */
    BOOL GraytoBinary(const char *strSrc, const char *strDst, const int threshold) 
    {
    BITMAPFILEHEADER fileheader; //文件头
    BITMAPINFOHEADER bmpinfo;    //信息头
    FILE *fSrc;  //源文件(灰度图)
    fSrc=fopen(strSrc,"rb");
    if( !fSrc )
    {
    return false;
    }
    fread(&fileheader, sizeof(BITMAPFILEHEADER), 1, fSrc); //读取源文件的文件头
    fread(&bmpinfo, sizeof(BITMAPINFOHEADER), 1, fSrc);    //读取源文件的信息头
    // const int SecBPP = 8 / bmpinfo.biBitCount; //源文件每字节的像素数
    const int SrcBitCount = bmpinfo.biBitCount;    //源文件的位深
    const int SrcRowLen = (((bmpinfo.biWidth * bmpinfo.biBitCount + 31)/8)/4)*4; // 520 源文件每行字节数
    const int SrcClrNum = bmpinfo.biClrUsed ? bmpinfo.biClrUsed : 256 ;  //原图像颜色表个数(8位256色)
    // read src colors !
    // RGBQUAD SrcClr[256];
    // fread(SrcClr,sizeof(RGBQUAD),SrcClrNum,fSrc);
    // or seek to data
    fseek(fSrc,sizeof(RGBQUAD)*SrcClrNum,SEEK_CUR);
    //修改文件信息为:目标文件信息
    bmpinfo.biBitCount = 1;  //二值图的位深
    bmpinfo.biClrImportant = 0; //所有颜色都很重要
    bmpinfo.biClrUsed = 2;   //有2个颜色表
    bmpinfo.biCompression = 0; //不压缩
    const int DstBPP = 8;  //二值图每字节的像素数
    const int DstRowLen = (((bmpinfo.biWidth * bmpinfo.biBitCount + 31)/8)/4)*4;// 68 二值图每行字节数
    fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
    2*sizeof(RGBQUAD) + bmpinfo.biHeight*DstRowLen; //二值图的文件大小
    fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
    2*sizeof(RGBQUAD);  //二值图的位图数据偏移量
    bmpinfo.biSizeImage = bmpinfo.biHeight * DstRowLen; //二值图的图像数据大小
    //创建目标文件
    FILE *fDst;
    fDst=fopen(strDst,"wb");
    if( !fDst )
    {
    return false;
    }
    fwrite(&fileheader, sizeof(BITMAPFILEHEADER), 1, fDst); // 写入二值图文件头
    fwrite(&bmpinfo, sizeof(BITMAPINFOHEADER), 1, fDst); // 写入二值图信息头

    RGBQUAD clrDst[2]; //临时变量:原图像(8位)颜色表 与 目标图像(1位)颜色表
    //clrDst[2]数组存储具体的颜色信息,二值图数据部分存储的是数组下标
    clrDst[0].rgbBlue = 0;
    clrDst[0].rgbGreen = 0;
    clrDst[0].rgbRed = 0;
    clrDst[0].rgbReserved = 0; // 0 表示 黑色
    clrDst[1].rgbBlue = 255;
    clrDst[1].rgbGreen = 255; 
    clrDst[1].rgbRed = 255; 
    clrDst[1].rgbReserved = 0; // 1 表示 白色
    for(int ii = 0; ii < 2; ii++)
    {
    fwrite(&clrDst[ii],sizeof(RGBQUAD),1,fDst); //将颜色表写入目标文件
    }

    BYTE *bufSrc = new BYTE[SrcRowLen]; //源文件(灰度图)存放一行像素的缓冲区
    BYTE *bufDst = new BYTE[DstRowLen]; //目标文件(二值图)存放一行像素的缓冲区

    for(int i = 0; i < bmpinfo.biHeight; i++)
    {
    fread(bufSrc,SrcRowLen,1,fSrc); //读取源文件(8位位图)第i行数据
    memset(bufDst,0,DstRowLen); //将目标文件(二值图)第i行数据清零
    for(int j = 0; j < bmpinfo.biWidth; j++)
    {
    int index = j / DstBPP; //从源文件每读8字节,目标文件增加一字节
    int nShift = 8 - (j % DstBPP + 1 ) * bmpinfo.biBitCount; //moved bit
    // nShift = 7 6 5 4 3 2 1 
    if(bufSrc[j] < threshold)
    bufDst[index] &= ~(1 << nShift);// =0
    else
    bufDst[index] |=  (1 << nShift);// =1
    }
    fwrite(bufDst, DstRowLen, 1, fDst); // write this row
    }
    //
    fclose(fSrc);
    fclose(fDst);
    //
    delete []bufSrc;
    delete []bufDst;
    return true;
    }// GraytoBinary("Girl8.bmp", "Girl2.bmp",28);//