首先呢,这是昨天到今天晚上的学习,总结下。
发现我自己的问题
1.c语言还是有问题,原因做的东西太少,理论知识不能结合实际,比如unsigned char 存储 一个字节和char存储一个字节的差别。
2.数学很重要啊。
3.学一个东西,一定要把这个东西学的屎出来了,再换。要么和没学没啥区别。
想要灰度化首先干什么呢?对了就是找图片。
这个是我在人人网注册栏找到的。
第二步呢?图片存储格式。
根据linux的哲学“一切皆文件”,所以这个图片一定可以用c语言的文件操作函数打开,我用的是c语言,当然用到文件操作这一节,复习复习。
第三部呢?
既然图片是文件,那就要读出来,文件操作就那么几个函数,都是字节或者二进制,然后读出来放在哪里呢?怎么操作这些数据呢?这个就先要查查图片编程方面的东西,百度“图片编程”会出现很多东西的,其中你会知道jpg和bmp两种格式的图片。
我发现,jpg是一种压缩后的图片(为了减轻网络传送数据的压力),bmp等等的图片太大了。大家写过哈夫曼的都知道,一个文件压缩后,它是直接显示不出来的,必须解压,解压后才是原始文件(jpg文件在网上传输的是压缩的文件,打开时候是对其解压),如果你直接对jpg操作就是大错特错(你懂得)。
下来就是要将jpg(网上的图片一般都是jpg)转换成bmp。linux下有个好东东
对于上面的东西,直接sudo就行。
现在的问题就明了了,是对bmp图片进行操作。
百度bmp。立马看到它的结构。
接着上面的问题,我们现在就知道从文件读出的数据放在哪里了。就是那几个结构体中。
现在就上代码吧。
#include <stdio.h>
#include <stdlib.h>
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned int LONG;
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 位图文件的类型,必须为BM(1-2字节)
DWORD bfSize; // 位图文件的大小,以字节为单位(3-6字节)
WORD bfReserved1; // 位图文件保留字,必须为0(7-8字节)
WORD bfReserved2; // 位图文件保留字,必须为0(9-10字节)
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图(11-14字节)
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数(15-18字节)
LONG biWidth; // 位图的宽度,以像素为单位(19-22字节)
LONG biHeight; // 位图的高度,以像素为单位(23-26字节)
WORD biPlanes; // 目标设备的级别,必须为1(27-28字节)
WORD biBitCount;// 每个像素所需的位数,必须是1(双色),(29-30字节)
// 4(16色),8(256色)16(高彩色)或24(真彩色)之一
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),(31-34字节)
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; // 位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(39-42字节)
LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(43-46字节)
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(47-50字节)
DWORD biClrImportant;// 位图显示过程中重要的颜色数(51-54字节)
} BITMAPINFOHEADER;
typedef struct{
unsigned char b;
unsigned char g;
unsigned char r;
}RGB;
/*
typedef struct tagRGBQUAD {
BYTE rgbBlue;// 蓝色的亮度(值范围为0-255)
BYTE rgbGreen; // 绿色的亮度(值范围为0-255)
BYTE rgbRed; // 红色的亮度(值范围为0-255)
BYTE rgbReserved;// 保留,必须为0
} RGBQUAD;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;
*/
void grey()
{
FILE *fp;
FILE *fp1;
char a[30];
BITMAPFILEHEADER head;
BITMAPINFOHEADER head1;
int trueWidth;
int i;
int j;
int k = 0;
unsigned char f = 0;
printf("please input filename:");
scanf("%s", a);
if((fp = fopen(a, "rb")) == NULL)
{
printf("file start error seek\n");
exit(1);
}
if((fp1 = fopen("11.bmp", "wb")) == NULL)
{
printf("file start error\n");
exit(1);
}
fread(&head, 14, 1, fp);
fread(&head1, 40, 1, fp);
printf("width:%d\n", head1.biWidth);
printf("biHeigth:%d\n", head1.biHeight);
printf("biBitCount:%d\n", head1.biBitCount);
trueWidth = (head1.biWidth * head1.biBitCount/8 +3)/4*4;
int p = trueWidth - trueWidth/3 * 3;
RGB rgb[head1.biHeight][head1.biWidth];
unsigned char b[head1.biHeight][head1.biWidth];
for(j = 0; j < head1.biHeight; j++ )
{
for(i = 0; i < head1.biWidth; i++)
{
fread(&rgb[j][i], 3, 1, fp);
k++;
}
fseek(fp, p, SEEK_CUR);
}
for(i = 0; i < head1.biHeight; i++)
for(j = 0; j < head1.biWidth; j++)
{
b[i][j] = (rgb[i][j].b + rgb[i][j].g + rgb[i][j].r)/3;
}
fwrite(&head, 14, 1, fp1);
fwrite(&head1, 40, 1, fp1);
for(i = 0; i < head1.biHeight; i++)
{
for(j = 0; j < head1.biWidth; j++)
{
fwrite(&b[i][j], 1, 3, fp1);
}
fwrite(&f, 1, p,fp1);
}
fclose(fp1);
fclose(fp);
}
int main()
{
grey();
}
然后看看效果。