代码是参考别人的,转化后的图片我用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);
}
}
#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);
}
}
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
/*
* 将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;}
//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;
}
单步看这个值
或者如果是BMP的图像,你的图像大小变成原图的1/3大小啊。这样应该没问题。
如果不加文件头的话,你的图片应该可以用PS打开,后缀改成RAW。代码没看,只是分析你的问题应该是这样的,说错了就当没说。哈哈。