user-0 提问: C语言提取BMP像素点的一些问题

回复:
user: user-1
content: 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

user: user-0
content: #include<stdio.h> #include<malloc.h> #include<math.h> #pragma pack(2) #define N 40000 //像素个数，200*200就是40000 typedef unsigned short WORD; typedef unsigned long LWORD; typedef struct TagBmpHeader { 	WORD bType; /* 文件标识符 ,BMP文件必须为'BM'*/ 	LWORD bSize; /* 文件的大小 */ 	WORD bReserved1; /* 保留值,必须设置为0 */ 	WORD bReserved2; /* 保留值,必须设置为0 */ 	LWORD bOffset; /* 文件头的最后到图像数据位开始的偏移量 */ }BmpHeader;  typedef struct TagBmpHeaderInfo { 	LWORD bInfoSize; /* 信息头的大小 */ 	LWORD bWidth; /* 图像的宽度 */ 	LWORD bHeight; /* 图像的高度 */ 	WORD bPlanes; /* 图像的位面数 */ 	WORD bBitCount; /* 每个像素的位数 */ 	LWORD bCompression; /* 压缩类型 */ 	LWORD bmpImageSize; /* 图像的大小,以字节为单位 */ 	LWORD bXPelsPerMeter; /* 水平分辨率 */ 	LWORD bYPelsPerMeter; /* 垂直分辨率 */ 	LWORD bClrUsed; /* 使用的色彩数 */ 	LWORD bClrImportant; /* 重要的颜色数 */ }BmpInf; typedef struct RGBCOLOR { 	WORD rgbBlue; /* 蓝色强度 */ 	WORD rgbGreen; /* 绿色强度 */ 	WORD rgbRed; /* 红色强度 */ 	WORD rgbReversed; /* 保留值 */ }RGB;  int main() { 	BmpHeader bmpheader; 	BmpInf bmpinf; 	FILE *fp; 	fp = fopen("d://a.bmp", "r"); 	if (fp == NULL) 	{ 		printf("无法找到该文件\n"); 		return 0; 	} 	else{ 		printf("成功打开\n"); 	} 	long offset, bmpImageSize, width, height, size, bitCount; 	WORD ch; 	fseek(fp, 0, 0);//重新定位文件内部指针 	fread(&bmpheader, sizeof(bmpheader), 1, fp); 	fread(&bmpinf, sizeof(bmpinf), 1, fp); 	width = abs(bmpinf.bWidth); 	height = abs(bmpinf.bHeight); 	 	int i = 0, j = 0, k = 0, max = 0; 	float min = 100; 	  	int *s1; 	s1 =(int*)malloc(width*height*4*sizeof(int)); 	//动态分配。存储ARGB  	int *s2; 	s2 = (int*)malloc(height*width*sizeof(int)); 	//动态分配。使用RGB计算出灰度,数组长度为像素宽，高。  	int *s4; 	s4 = (int*)malloc(sqrt(width*width + height*height)*sizeof(int)); 	 	float *s3; 	s3 = (float*)malloc(height*width*sizeof(double)); 	//点到直线距离数组  	int sum = 0;//计数器  	float down = sqrt(width*width + height*height); 	//点到直线距离公式的分母 	float up; 	//点到直线距离公式的分子 	ch = fgetc(fp); 	while (!feof(fp)) 	{ 		ch = fgetc(fp); 		s1[sum] = ch; 		sum++;//计数器 	} 	printf("共有:%d个像素点（应为%d个）\n宽：%d 高：%d\n", sum,(width*height*4),width,height); 	//存入到S1数组中是由左到右由下到上 	rewind(fp); 	sum = 0; 	for (i = 0; i <height*width; i++) 	{ 		sum++; 		s2[i] = s1[i*4] * 0.299 + s1[4*i + 1] * 0.587 + s1[4*i + 2] * 0.114; 		 	}//灰度值计算之后是由左到右由下到上 	 	i = 0; 	for (j = 1; j <= height * 2 - 1; j += 2) 	{ 		for (k = 1; k <= width * 2 - 1; k += 2) 		{ 			up = abs( k*(-height)+j*width ); 			s3[i] = up / down; 			i++; 		} 	} 	//s3数组中存储的是像素中心点距离对角线的距离 	  	int temp = 0; 	int flag = 0; 	for (i = 0; i < (int)down; i++) 	{ 		for (j = 0; j < height*width; j++) 		{ 			if (s3[j] < min) 			{	 				min = s3[j]; 				flag = j; 			} 		}//所有距离遍历，找出最短，赋值给min。同时下标赋值给flag 		 		min = 999;//第二遍遍历时min初始值设置大一些 		s3[flag] =min;//防止第二次遍历时将第一遍的再次比较 		s4[i] = flag;//s4存储下标 		flag = 0;//下标初始化 	} 	s3[0] = 0; 	printf("对角线像素个数：%d\n", i);//输出  对角线像素点个数。 	//s4数组中存储的是距离像素中心点最短的点的位置下标，排序后输出即可 	  	for (i = 0; i < (int)down; i++) 	{ 		for (j = (int)down; j >i; j--) 		{ 			if (s4[j-1]>s4[j ]) 			{ 				temp = s4[j]; 				s4[j] = s4[j - 1]; 				s4[j - 1] = temp; 			} 		} 	} 	//将s4数组排序，下标小的在前。  	FILE *tp; 	tp = fopen("d://txt.txt", "wt+"); 	 	 	for (i = 1; i <= (int)down; i++) 	{ 		fprintf(tp,"%d, ", s2[s4[i]]); 	} 	 	fclose(fp); 	fclose(tp); 	free(s1); 	printf("文档储存在d盘目录下名为txt\n"); 	 	 } 这是我搞的代码，80%情况下是可以打开BMP输出对角线灰度值的，但是有20%情况下，不行，-842150451。好像是动态数组的问题，有人帮我看一下吗~顶个

user: user-2
content: 如果通过openCV相关的命令读取图像文件和进行操作就会方便点，你不需要考虑bmp文件的格式及读取问题。

user: user-0
content: 引用 4 楼 shdust 的回复:如果通过openCV相关的命令读取图像文件和进行操作就会方便点，你不需要考虑bmp文件的格式及读取问题。 不行啊，就规定不让使用其他的

user: user-1
content: 搜“RGB转灰度”

user: user-0
content: 对对…就是这个顺序是啥？…

user: user-3
content: 这个首先搞清楚argb的排列次序，按道理灰度应该rgb都是相同的吧？

user: user-4
content: 说下我的理解: 首先BMP图有一个头，有一千多个字节，接着就是图像的数据了，BMP图显示是从下向上，从左向右的，你要提取像素灰度值就计算出需要读取的位置，然后直接读BMP对应位置的值就好了  PS:个人观点，不喜勿喷