Skip to content

Instantly share code, notes, and snippets.

@renyuntao
Created May 25, 2017 07:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renyuntao/52eb61adc2c1437644750024bff170fe to your computer and use it in GitHub Desktop.
Save renyuntao/52eb61adc2c1437644750024bff170fe to your computer and use it in GitHub Desktop.
标注杂色
// 一、库文件
#include<stdio.h>
#include<math.h>
int imgoffset;
char bmpheader[54];
int imgwidth;
int imgheight;
int bitperpixel;
int scanwidth;
unsigned char R[300][300],G[300][300],B[300][300];
unsigned char r[300][300],g[300][300],b[300][300];
int NR[300][300],NB[300][300],NG[300][300];
// 二、读BMP文件的程序代码,执行后可读出图像全部RGB值
int Input_24bits_BitMap(char filename[50])
{
int i,j;
FILE* fp;
// 读取二进制文件, 所以fopen的第二个参数为"rb"
// 如果读取失败, fopen函数会返回NULL, 此时输出错误信息并退出程序
if((fp=fopen(filename,"rb"))==NULL)
{
printf("NO %s\n",filename);
return 0;
}
// 移动到距BMP文件起始位置的10个字节处
fseek(fp,10,SEEK_SET);
/* 从BMP文件中读取1个长度为4个字节(`sizeof(int)`表示4个字节)的数据, 并保存到imgoffset变量中
读取的这4个字节的数据的含义表示的时从文件头开始到实际的图像数据之间的字节的偏移量 */
fread(&imgoffset,sizeof(int),1,fp);
// 移动到BMP文件的开始位置
fseek(fp,0,SEEK_SET);
// 从BMP文件中读取imgoffset个数据, 每个数据的长度是一个字节(`sizeof(char)`表示的是一个字节), 并将读取到的数据保存到变量bmpheader中
fread(bmpheader,sizeof(char),imgoffset,fp);
// 移动到距BMP文件起始位置18个字节处
fseek(fp,18,SEEK_SET);
// 从BMP文件中读取一个长度为4个字节的数据并保存到imgwidth中去, 该数据表示BMP图像的宽度
fread(&imgwidth, sizeof(int),1,fp);
// 从BMP文件中读取一个长度为4个字节的数据并保存到imgheight中去, 该数据表示BMP图像的高度
fread(&imgheight,sizeof(int),1,fp);
printf("imgwidth: %d\nimgheight: %d\n", imgwidth, imgheight);
// 从当前位置向前移动两个字节
fseek(fp,2,SEEK_CUR);
// 从BMP文件中读取2个字节的数据(1x2=2)并保存到bitperpixel中去, 该数据表示每个像素所包含的比特数
fread(&bitperpixel,1,2,fp);
// 输出变量bitperpixel的值
printf("bitperpixel= %d\n",bitperpixel);
// 移动到距BMP文件起始位置imgoffset个字节的位置
fseek(fp,imgoffset,SEEK_SET);
// 如果bitperpixel的值是8, 即每个像素占一个字节
if(bitperpixel==8)
{
printf("Input func, it's 8...\n");
// scanwidth - 每行的字节数
//Windows规定一个扫描行所占的字节数必须是4的倍数,不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素、每像素biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下
scanwidth=((imgwidth+3)/4)*4;
printf("scanwidth: %d\nimgwidth: %d\nimgheight:%d\n", scanwidth, imgwidth, imgheight);
// 从BMP文件中读取RGB数据, 读取方式为从BMP图的左下角开始扫描图像, 即从下到上, 从左到右进行扫描
for(i=imgheight-1;i>=0;i--)
{
fread(B[i],sizeof(unsigned char),imgwidth,fp);
// 如果scanwidth不等于imgwidth(即表示有填充部分)
if(scanwidth!=imgwidth)
{
printf("in if()...\n");
// 跳过填充部分
fseek(fp,scanwidth-imgwidth,SEEK_CUR);
}
}
for(i=imgheight-1;i>=0;i--)
{
for(j=0;j<imgwidth;j++)
{
R[i][j]=B[i][j];
G[i][j]=B[i][j];
}
}
}
// 如果bitperpixel的值不是8
else
{
// scanwidth - 每行的字节数
// 按照每个像素3个字节来处理
scanwidth=((imgwidth*3+3)/4)*4;
if(scanwidth==3*imgwidth)
{
// 从BMP文件中读取RGB数据, 并保存到R[][], G[][], B[][]数组中去
// 读取方式为从BMP图的左下角开始扫描图像, 即从下到上, 从左到右进行扫描
for(i=imgheight-1;i>=0;i--)
{
for(j=0;j<imgwidth;j++)
{
fread(&B[i][j],sizeof(unsigned char),1,fp);
fread(&G[i][j],sizeof(unsigned char),1,fp);
fread(&R[i][j],sizeof(unsigned char),1,fp);
}
}
}
else
{
// 从BMP文件中读取RGB数据, 并保存到R[][], G[][], B[][]数组中去
// 读取方式为从BMP图的左下角开始扫描图像, 即从下到上, 从左到右进行扫描
for(i=imgheight-1;i>=0;i--)
{
for(j=0;j<imgwidth;j++)
{
fread(&B[i][j],sizeof(unsigned char),1,fp);
fread(&G[i][j],sizeof(unsigned char),1,fp);
fread(&R[i][j],sizeof(unsigned char),1,fp);
}
// 跳过填充部分
fseek(fp,scanwidth-3*imgwidth,SEEK_CUR);
}
}
}
// 关闭文件
fclose(fp);
return 1;
}
// 三、写图像程序代码,执行可对图像的RGB值进行修改
// 定义TIME就能改变图像的大小,尤其适应用于图像的缩小
int Output_24bits_BitMap(char filename[50])
{
int i,j;
FILE* fp;
unsigned char tch=0;
int time=1;
// 读取二进制文件, 所以fopen的第二个参数为"rb"
// 如果读取失败, fopen函数会返回NULL, 此时输出错误信息并退出程序
if((fp=fopen(filename,"wb"))==NULL)
{
printf("NO %s\n",filename);
return 0;
}
// 从bmpheader中读取imgoffset个长度为1字节的数据, 并将数据写入到fp所关联的文件中
fwrite(bmpheader,sizeof(char),imgoffset,fp);
// 如果bitperpixel的值是8
if(bitperpixel==8)
{
printf("Output func, it's 8...\n");
// scanwidth - 每行的字节数
//Windows规定一个扫描行所占的字节数必须是4的倍数,不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素、每像素biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下
scanwidth=((imgwidth/time+3)/4)*4;
printf("scanwidth: %d\nimgwidth: %d\nimgheight:%d\ntime: %d\n", scanwidth, imgwidth, imgheight, time);
// 将RGB数据写入到与fp关联的文件中
for(i=imgheight/time-1;i>=0;i--)
{
//printf("i: %d\n", i);
fwrite(b[i],sizeof(unsigned char),(imgwidth/time),fp);
if(scanwidth>(imgwidth/time))
{
printf("In if...\n");
// 写入空字符进行填充
for(j=(imgwidth/time);j<scanwidth;j++)
fwrite(&tch,sizeof(unsigned char),1,fp);
}
}
}
// 如果bitperpixel的值不是8
else
{
printf("In here ...\n");
// scanwidth - 每行的字节数
// 按照每个像素占3个字节来处理
scanwidth=((imgwidth/time*3+3)/4)*4;
if(scanwidth==3*(imgwidth/time))
{
// 将RGB数据写入到与fp关联的文件中
for(i=(imgheight/time)-1;i>=0;i--)
{
for(j=0;j<(imgwidth/time);j++)
{
fwrite(&B[i][j],sizeof(unsigned char),1,fp);
fwrite(&G[i][j],sizeof(unsigned char),1,fp);
fwrite(&R[i][j],sizeof(unsigned char),1,fp);
}
}
}
else
{
// 将RGB数据写入到与fp关联的文件中
for(i=(imgheight/time)-1;i>=0;i--)
{
for(j=0;j<(imgwidth/time);j++)
{
fwrite(&B[i][j],sizeof(unsigned char),1,fp);
fwrite(&G[i][j],sizeof(unsigned char),1,fp);
fwrite(&R[i][j],sizeof(unsigned char),1,fp);
}
// 写入空字符进行填充
for(j=3*(imgwidth/time);j<scanwidth;j++)
fwrite(&tch,sizeof(unsigned char),1,fp);
}
}
}
// 关闭文件
fclose(fp);
return 1;
}
int main()
{
Input_24bits_BitMap("yise.bmp");
int rgbSum = 0;
for(int i=0; i<imgheight; ++i)
{
for(int j=0; j < imgwidth; ++j)
{
rgbSum = B[i][j] + G[i][j] + R[i][j];
if(rgbSum < 205)
{
B[i][j] = G[i][j] = 0;
R[i][j] = 255;
}
}
}
Output_24bits_BitMap("result.bmp");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment