版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzw_ice/article/details/78643240
- 话不多说,直接上代码
- 全彩转灰度公式和灰度转伪彩色对应关系均可在代码里找到,有详细注释
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{
unsigned short bfType;//文件格式
unsigned long bfSize;//文件大小
unsigned short bfReserved1;//保留
unsigned short bfReserved2;
unsigned long bfOffBits; //DIB数据在文件中的偏移量
}fileHeader;
#pragma pack()
/*
位图数据信息结构
*/
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize;//该结构的大小
long biWidth;//文件宽度
long biHeight;//文件高度
unsigned short biPlanes;//平面数
unsigned short biBitCount;//颜色位数
unsigned long biCompression;//压缩类型
unsigned long biSizeImage;//DIB数据区大小
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;//多少颜色索引表
unsigned long biClrImporant;//多少重要颜色
}fileInfo;
#pragma pack()
/*
调色板结构
*/
#pragma pack(1)
typedef struct tagRGBQUAD
{
unsigned char rgbBlue; //蓝色分量亮度
unsigned char rgbGreen;//绿色分量亮度
unsigned char rgbRed;//红色分量亮度
unsigned char rgbReserved;
}rgbq;
#pragma pack()
//其他数据
typedef struct OtherData
{
unsigned char extradata;
struct OtherData *next;
}OtherData;
int colorToGray(FILE* fp1,FILE* fp2)
{
fileHeader * fh;
fileInfo * fi;
fh = (fileHeader *)malloc(sizeof(fileHeader));
fi = (fileInfo *)malloc(sizeof(fileInfo));
//读取位图头结构和信息头
fread(fh, sizeof(fileHeader), 1, fp1);
fread(fi, sizeof(fileInfo), 1, fp1);
//修改信息头
fi->biBitCount = 8;
//fi->biSizeImage = ((fi->biWidth * 3 + 3) / 4) * 4 * fi->biHeight;
fi->biSizeImage = fi->biHeight*fi->biWidth;
//修改文件头
fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
fh->bfSize = fh->bfOffBits + fi->biSizeImage;
//创建调色板
int i,j,k=0;
rgbq *fq = (rgbq *)malloc(256 * sizeof(rgbq));
for (i = 0; i<256; i++)
{
fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
}
//写入文件头、信息头、调色板
fwrite(fh, sizeof(fileHeader), 1, fp2);
fwrite(fi, sizeof(fileInfo), 1, fp2);
fwrite(fq, sizeof(rgbq), 256, fp2);
//将位图信息转为灰度
//存储bmp一行的像素点
unsigned char ImgData[3000][3];
//将灰度图像存到一维数组中
unsigned char ImgData2[3000];
//公式
for (i = 0; i<fi->biHeight; i++)
{
for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
{
for (k = 0; k<3; k++)
fread(&ImgData[j][k], 1, 1, fp1);
}
for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
{
ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
(float)ImgData[j][1] * 0.587 +
(float)ImgData[j][2] * 0.299);
}
//将灰度图信息写入
fwrite(ImgData2, j, 1, fp2);
}
free(fh);
free(fi);
free(fq);
fclose(fp1);
fclose(fp2);
return 1;
}
int grayToColor(FILE* fp1,FILE* fp2)
{
unsigned char * * ImgData;//二维数组
unsigned int j, k,i;
fileHeader fh;
fileInfo fi;
rgbq *IpRGBQuad;
OtherData *Otherdata, *temp,*SavePreCursor;
/*图像的读取顺序是从下到上,从左到右*/
IpRGBQuad = (rgbq *)malloc(256*sizeof(rgbq));//灰度图为8位的调色板数据为256个结构,1024个字节
Otherdata = (OtherData*)malloc(sizeof(OtherData));
SavePreCursor = Otherdata;//保存当前指针游标,目的就是保存链表头结点
Otherdata->extradata = NULL;
Otherdata->next = NULL;
//拥有1024个调色板数据
fread(&fh, sizeof(fileHeader), 1, fp1);
if (fh.bfType == 0x4D42)
{
//读取位图信息头
fread(&fi, sizeof(fileInfo), 1, fp1);
//读取调色板数据
fread(IpRGBQuad, sizeof(rgbq), 256, fp1);
fi.biBitCount = 24;
fi.biSizeImage = fi.biHeight*fi.biWidth;
fh.bfOffBits = sizeof(fileHeader)+sizeof(fileInfo)+256*sizeof(rgbq);
fh.bfSize = fh.bfOffBits + fi.biSizeImage;
fwrite(&fh, sizeof(fileHeader), 1, fp2);
fwrite(&fi, sizeof(fileInfo), 1, fp2);
fwrite(IpRGBQuad, sizeof(rgbq), 256, fp2);
//读取像素数据
fi.biHeight++;
fi.biWidth += 2;
ImgData = new unsigned char *[fi.biHeight];
for (j = 0; j < fi.biHeight; j++)
{
ImgData[j] = new unsigned char [fi.biWidth];//定义像素数组ImgData[InfoHeader.biHeight][InfoHeader.biWidth]
}
for ( j = 0; j < fi.biHeight; j++)
{
for ( k = 0; k < fi.biWidth; k++)
{
fread(&ImgData[j][k], sizeof(unsigned char), 1, fp1);
//fwrite(&ImgData[j][k], sizeof(unsigned char), 1, fp2);
}
}
unsigned char ImgData2[3000][3];//伪彩色数据
for (i = 0; i<fi.biHeight; i++)
{
for (j = 0; j<fi.biWidth; j++)
{
//蓝色
if(ImgData[i][j] >=0 && ImgData[i][j]<=31)
{
ImgData2[j][2] = 0;
ImgData2[j][1] = 0;
ImgData2[j][0] = 255;
}
//绿色
if(ImgData[i][j] >=32 && ImgData[i][j]<=63)
{
ImgData2[j][2] = 0;
ImgData2[j][1] = 255;
ImgData2[j][0] = 0;
}
//淡蓝色
if(ImgData[i][j] >=64 && ImgData[i][j]<=95)
{
ImgData2[j][2] = 173;
ImgData2[j][1] = 216;
ImgData2[j][0] = 230;
}
//紫色
if(ImgData[i][j] >=96 && ImgData[i][j]<=127)
{
ImgData2[j][2] = 155;
ImgData2[j][1] = 48;
ImgData2[j][0] = 255;
}
//红色
if(ImgData[i][j] >=128 && ImgData[i][j]<=159)
{
ImgData2[j][2] = 255;
ImgData2[j][1] = 0;
ImgData2[j][0] = 0;
}
//橙色
if(ImgData[i][j] >=160 && ImgData[i][j]<=191)
{
ImgData2[j][2] = 255;
ImgData2[j][1] = 165;
ImgData2[j][0] = 0;
}
//黄色
if(ImgData[i][j] >=192 && ImgData[i][j]<=223)
{
ImgData2[j][2] = 255;
ImgData2[j][1] = 255;
ImgData2[j][0] = 0;
}
//淡黄色
if(ImgData[i][j] >=224 && ImgData[i][j]<=255)
{
ImgData2[j][2] = 255;
ImgData2[j][1] = 255;
ImgData2[j][0] = 254;
}
}
fwrite(ImgData2, sizeof(unsigned char)*3, j, fp2);
}
//读取其他数据
temp = (OtherData*)malloc(sizeof(OtherData));
while (!feof(fp1))
{
temp = (OtherData*)malloc(sizeof(OtherData));
fread(&temp->extradata, sizeof(unsigned char), 1, fp1);
fwrite(&temp->extradata, sizeof(unsigned char), 1, fp2);
Otherdata->next = temp;
Otherdata = Otherdata->next;
}
Otherdata->next = NULL;//置末尾为空,判断条件
Otherdata = SavePreCursor;//使Otherdata重新指向头部
}
fclose(fp1);
fclose(fp2);
return 1;
}
int main(){
int colorToGray(FILE* fp1,FILE* fp2);
int grayToColor(FILE* fp1,FILE* fp2);
int n;
char inPath[100],outPath[100];
printf("功能:\n");
printf("1 : 彩色转灰色\n");
printf("2 : 灰色转伪彩色\n");
printf("输入功能编号:\n");
scanf("%d",&n);
printf("输入源文件绝对地址(含文件名):\n");
scanf("%s",inPath);
printf("输入目标文件绝对地址(含文件名):\n");
scanf("%s",outPath);
FILE *fp1 = fopen(inPath, "rb+");
if (fp1 == NULL)
{
printf("打开文件fp1失败");
return 0;
}
FILE *fp2 = fopen(outPath, "wb");
if (fp1 == NULL)
{
printf("打开文件fp2失败");
return 0;
}
switch(n)
{
case 1:
{
if(colorToGray(fp1,fp2) == 1)
{
printf("success\n");
}
break;
};
case 2:
{
if(grayToColor(fp1,fp2) == 1)
{
printf("success\n");
}
break;
}
default: break;
}
}
- 测试结果