DIB(设备无关位图)编程系列(二)——24位真彩图转256阶(8位)灰度图

news/2024/7/21 5:32:30 标签: 编程, matrix, mfc, file, 图像处理, delete

上一篇介绍过了位图的基本概念,相信大家对bmp格式的图片存储结构已经了解了,下面就以一个win32控制台程序来实现真彩图(也就是24位位图)转为为256级灰度图,这在图像处理上非常重要。

为什么用控制台程序而不是MFC等窗口程序呢,是因为这程序更能说明算法实现的过程,而不拘泥于MFC的框架下。

程序如下:(注释很好,不用过多解释)

#include <stdio.h>  
#include <windows.h>

#define WIDTHBYTES(i) ( ( (i+31)/32 )*4) //使每一行的宽度是4个字节的倍数
#define IMAGETYPE 0x4d42				 //表示字符BM

int main(int argc,char* argv)
{
	BITMAPFILEHEADER bmpfileheader;     //文件头
	BITMAPINFOHEADER bmpinfoheader;     //信息头
    
	unsigned char *matrix;              //像素矩阵,用unsigned char是因为它的范围刚好为0—255
	FILE *finput;                       //读取操作流
	FILE *foutput;                      //出操作流
	DWORD imageSize = 0;				//图像像素数据部分大小

	//打开文件
	finput=fopen("picture.bmp","r+b");
	if (finput == NULL) 
	{  
		printf("Open failed\n");
		return EXIT_FAILURE;  
	} 
	else  
	{
		printf("Open Successsfully\n");
	}

	fread(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,finput);//读取文件头
	fread(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,finput);//读取信息头

	//判断是否为24位真彩图
	if ( bmpfileheader.bfType!=IMAGETYPE || bmpinfoheader.biBitCount != 24)
	{
		printf("The error picture!");
		return EXIT_FAILURE;
	}
	//计算位图像素部分的大小,也可以是bmpinfoheader.biSizeImage 但它有时候是0,不可靠。
	imageSize = WIDTHBYTES(bmpinfoheader.biWidth*bmpinfoheader.biBitCount) * bmpinfoheader.biHeight;

	matrix = new unsigned char[imageSize];
	memset(matrix,0,imageSize);
 
	//读取象素矩阵
	fread(matrix,1,imageSize,finput);
	fclose(finput);
	

	//每个像素点转化为灰度值,用的公式是:Gray = R*0.299 + G*0.587 + B*0.114
	for(unsigned long k=0;k<imageSize;k=k+3)
	{
		*(matrix+k)=*(matrix+k+1)=*(matrix+k+2)=(*(matrix+k)*0.299+*(matrix+k+1)*0.587+*(matrix+k+2)*0.114);
	}
 
	//创建新的灰度图
 	foutput=fopen("test.bmp","w+b");
	fwrite(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,foutput);
	fwrite(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,foutput);

	fwrite(matrix,1,imageSize,foutput);
	fclose(foutput);

	delete []matrix;
	printf("转化成功\n");
	return EXIT_SUCCESS;
}

实现结果:把一张bmp格式的真彩图放在工程目录下,运行程序生成一个灰度图。






http://www.niftyadmin.cn/n/1332069.html

相关文章

插入排序(一)—直接插入排序

最近复习《数据结构》&#xff0c;复习到了内部排序&#xff0c;就把书上的算法用代码实现了。课本用的是严慧敏老师主编的那本。插入排序算法算法思想很简单&#xff0c;就是从第二个元素开始把每个元素逐个插入到前面已排好序的有序表中&#xff0c;渐增的实现排序。下面用一…

Github-Readme-Stats 简明教程

注&#xff1a;本篇文章首发于 博客园sarexpine 为保持阅读的舒适性&#xff0c;可以选择移步至 博客园sarexpine 阅读&#xff0c;日后的文章将首发于 博客园sarexpine 平台&#xff0c;谢谢&#xff01; 1. 更新 Readme 文件 在你想要放置 Readme-WakaTime 的位置中放置以下…

工作 4 年,从阿里巴巴辞职到了国企

点击上方 果汁简历 &#xff0c;选择“置顶公众号”优质文章&#xff0c;第一时间送达lz本硕985&#xff0c;毕业的时候去了杭州某互联网大厂&#xff0c;后来又跳槽去了北京某互联网大厂。简单的谈一下互联网的感受吧&#xff0c;工作压力大&#xff0c;节奏快&#xff0c;但是…

插入排序(二)— 表插入排序

上篇文章已经提到直接插入排序中&#xff0c;时间消耗在了元素间的比较次数和移动这两方面。折半插入排序可以减小比较次数&#xff0c;而表插入排序则可以避免元素移动。但它需要建立数据结构&#xff0c;并且需要额外的空间&#xff08;省时一般都耗空间&#xff0c;这个在算…

网络协议,我明明学过的呀?

十个人程序员里面&#xff0c;有十个都会说自己学过网络协议&#xff0c;九个人都会说自己懂网络协议。但是面试的时候&#xff0c;问几个问题&#xff0c;能回答的可能只有两三个。不信&#xff1f;来&#xff0c;我问你几道。1、TCP协议跟UDP协议有什么区别&#xff1f;你说这…

(转)OpenGL开发库的介绍

本博客计算机图形学系列文章索引&#xff1a; 地址&#xff1a;《计算机图形学系列相关文章索引&#xff08;持续更新&#xff09;》 开发基于 OpenGL的应用程序&#xff0c;必须先了解 OpenGL的库函数。它采用 C语言风格&#xff0c;提供大量的函数来进行图形的处理和显示。 …

第一次听说因为写了一段 JavaScript 代码入狱了

背景几行代码让他增粉 100W 最后入狱&#xff0c;他就是著名 Samy 蠕虫病毒的作者 Samy Kamkar&#xff0c;通过 Samy 蠕虫成功为自己新增 100W 粉丝最后入狱。这也是一个里程碑&#xff0c;世界上第一只 “Web 蠕虫”诞生。那么我们今天要聊的就是如何从技术的角度理解他是如何…

面试前端岗位接连碰壁,企业到底需要哪种前端工程师?

提到前端工程师&#xff0c;很多人的第一反应都是&#xff1a;那个工资高&#xff0c;门槛低的职业。没错&#xff0c;也正因如此&#xff0c;越来越多的人开始投入前端岗位。可是有些人似乎不太了解前端岗位为何如此高薪&#xff0c;认为自己看了些教程&#xff0c;读了几本书…