代码写的很水,把灰度化 二值化 亮度调整 算法全部注释掉了 ,根据自己的需要去掉相关注释就可以,快捷注释键ctrl+k+c 快捷取注释键ctrl+k+u;如果输入的位图文件不是24位的,在相关循环下面添加相应的算法即可 下面是自己写的代码:
#include<malloc.h>
#include<stdlib.h>
#include<memory.h>
#include<time.h>
#include <stdio.h>
/*!
* \the bitmap struct
* \author whtr01
* \date SEP 2016
*/
#define WORD unsigned short
#define DWORD unsigned long
#define BYTE unsigned char
#define WIDTHBYTES(bits) (((bits)+31)/32*4) //用于使图像宽度所占字节数为4的整数倍
#define BM 19778 // 位图的标志
#pragma pack(2) //两字节对齐,否则bmp_fileheader会占16Byte
typedef struct //12byte,位图文件头
{
WORD bfType; //BM标志
DWORD bfSize; //文件大小
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffset; //偏移量 起始位置距离数据区
}BitMapFileHeader;
typedef struct //40字节 位图信息头
{
DWORD biSize;//信息头大小
DWORD biWidth;//图像宽度,以像素为单位
DWORD biHeight;//图像高度,以像素为单位
WORD biPlanes;//位平面数,为1;
WORD biBitCount;//每像素位数,1,4,8,24
DWORD biCompression;//压缩类型,0为非压缩
DWORD biSizeImage;//压缩图像大小
DWORD biXpelspermeter;//水平分辨率
DWORD biYpelspermeter;//垂直分辨率
DWORD biClrUsed;//使用的色彩数
DWORD biClrImportant;//重要色彩数
}BitMapInforHeader;
typedef struct //位图颜色表
{
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
} RGBQuad;
BYTE * ImgData;
//为二维数组申请内存
int **getArray(int row, int line)//行 列
{
int **p = NULL;
p = (int**)malloc(sizeof(int*)*row);
int i = 0;
for (; i < row; i++)
p[i] = (int*)malloc(sizeof(int)*line);
return p;
}
//释放数组内存
void freeArray(int row, int**p)
{
for (int i = 0; i < row; i++)
{
free(p[i]);
}
free(p);
}
//位图文件是否能打开
FILE *IsOpen(char* srcFile)
{
FILE* pFile = fopen(srcFile, "rb");
if (pFile == NULL)
{
printf("打开位图失败\n");
exit(-1);
}
return pFile;
}
//判断是否是位图,在0-1字节
int IsBitMap(char *srcFile)
{
FILE *fp = fopen(srcFile, "rb");
WORD s;
fread(&s, 1, 2, fp);
if (s != BM)
{
return -1;
}
return 0;
}
//获得图片的宽度,在18-21字节
long getWidth(FILE *fp)
{
long width;
fseek(fp, 18, SEEK_SET);
fread(&width, 1, 4, fp);
return width;
}
//获得图片的高度 ,在22-25字节
long getHeight(FILE *fp)
{
long height;
fseek(fp, 22, SEEK_SET);
fread(&height, 1, 4, fp);
return height;
}
//获得每个像素的位数,在28-29字节
WORD getBit(char *srcFile)
{
IsBitMap(srcFile);
FILE *pFile = IsOpen(srcFile);
WORD bit;
fseek(pFile, 28, SEEK_SET);
fread(&bit, 1, 2, pFile);
return bit;
}
//获得数据的起始位置
DWORD getOffSet(char *srcFile)
{
DWORD OffSet;
FILE *pFile = IsOpen(srcFile);
fseek(pFile, 10L, SEEK_SET);
fread(&OffSet, 4, 1, pFile);
return OffSet;
}
void ToGray(char* srcFile, char* destFile)
{
BitMapFileHeader fileHeader;// 位图头文件
BitMapInforHeader infoHeader;// 位图信息头
IsBitMap(srcFile);
// 读取头信息
FILE *pFile=IsOpen(srcFile);
// 读取头信息
fread(&fileHeader, sizeof(BitMapFileHeader), 1, pFile);
fread(&infoHeader, sizeof(BitMapInforHeader), 1, pFile);
WORD bitCount = infoHeader.biBitCount;//取表示色彩的位数
if (bitCount == 16)
{
exit(-1);
}
int nColorUsed = 0;
int i = 0, j = 0;
RGBQuad *quad = NULL;
if (bitCount < 16)
{
// 读取使用的调色板颜色数量,biClrUsed为0时,代表位数默认的调色板值
nColorUsed = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
if (nColorUsed > 256)
nColorUsed = 0;
}
// 读取调色板
if (nColorUsed > 0)//排除24位和32位没有调色板的
{
quad = (RGBQuad*)malloc(sizeof(RGBQuad)*nColorUsed);
fread(quad, sizeof(RGBQuad)*nColorUsed, 1, pFile);
for (i = 0; i < nColorUsed; i++)
{
quad[i].rgbRed = quad[i].rgbBlue = quad[i].rgbGreen =
(BYTE)(0.3 * quad[i].rgbRed + 0.59 * quad[i].rgbGreen + 0.11 * quad[i].rgbBlue);//灰度化
}
}
DWORD srcW = infoHeader.biWidth;
DWORD srcH = infoHeader.biHeight;
//图像数据区域
int BufSize = (((srcW * bitCount + 31) & ~31) >> 3)*srcH;
BYTE* Buf = (BYTE*)malloc(BufSize);
int LineSize = (((srcW * bitCount + 31) & ~31) >> 3);
fread(Buf, BufSize, 1, pFile);
if (nColorUsed == 0) //图像处理可通过操作这部分数据加以实现,可将下面的示例修改为中值滤波等各种图像处理模块
// //在嵌入式开发环境下,大多数情况下已经得到图像数据区,是故将下面部分代码稍作修改就可以移植到嵌入式端
//
// /*******************图像处理部分******************/
// /*******************示例,将图像亮度减半******************/
{
for (i = 0; i < srcH; i++)//行
{
if (bitCount == 24)
{
for (j = 0; j < srcW * 3; j = j + 3)// 列,因为每个像素占3个字节
{
int n = i*LineSize + j;
/************************************************************************/
/* 图像灰度化 */
/************************************************************************/
Buf[n] = Buf[n + 1] = Buf[n + 2] = (BYTE)(0.3*Buf[n] + 0.59*Buf[n + 1] + 0.11*Buf[n + 2]);//灰度化
/************************************************************************/
/* 改变图像亮度强弱部分 */
/************************************************************************/
/*Buf[n] = (BYTE)Buf[n] * 0.5;
Buf[n + 1] = (BYTE)Buf[n + 1] * 0.5;
Buf[n + 2] = (BYTE)Buf[n + 2] * 0.5;*/
/************************************************************************/
/* 图像二值化 */
/************************************************************************/
//Buf[n] = Buf[n + 1] = Buf[n + 2] = (BYTE)(0.3*Buf[n] + 0.59*Buf[n + 1] + 0.11*Buf[n + 2]);//灰度化
//Buf[n] > 128 ? Buf[n] = 0 : Buf[n] = 255; // 此处设置阀值 即为此处的64 可根据需要改变64的值 eg:128 。。
//Buf[n+1] > 128 ? Buf[n+1] = 0 : Buf[n+1] = 255;
//Buf[n+2] > 128 ? Buf[n+2] = 0 : Buf[n+2] = 255;
}
}
else
{
for (j = 0; j < srcW * 4; j = j + 4)// 列
{
int n = i*LineSize + j;
//Buf[n] = Buf[n + 1] = Buf[n + 2] = 0.11*Buf[n] + 0.59*Buf[n + 1] + 0.3*Buf[n + 2];
Buf[n] = (BYTE)Buf[n] * 2;
Buf[n + 1] = (BYTE)Buf[n + 1] * 2;
Buf[n + 2] = (BYTE)Buf[n + 2] * 2;
}
}
}
}
/*******************图像写入部分******************/
// /*******************无需再更改******************/
//创建目标文件
FILE* pDfile = fopen(destFile, "wb");
//写入数据 写入文件头
fwrite(&fileHeader, sizeof(BitMapFileHeader), 1, pDfile);
//写入Bitmap头信息
fwrite(&infoHeader, sizeof(BitMapInforHeader), 1, pDfile);
if (quad)
{
fwrite(quad, sizeof(RGBQuad)* nColorUsed, 1, pDfile);
}
//写入图像数据
fwrite(Buf, BufSize, 1, pDfile);
fclose(pDfile);
if (quad)
{
free(quad);
quad = NULL;
}
if (Buf)
{
free(Buf);
Buf = NULL;
}
}
int main()
{
ToGray("F:\\Mypicture\\bmp\\Tulips.bmp", "F:\\Mypicture\\Test\\GrayTulips.bmp");
//ReadData("F:\\Mypicture\\gray\\a4.bmp");
system("pause");
return 0;
}
效果图: