从零开始写一个图像处理程序之一(BMP彩色图转灰度图)

2023-05-16

图像二值化可以直接调用opencv的二值化函数去完成处理,但是不利用OpenCV从头手写一个处理图片程序未尝不是一件有意思的事情,就拿BMP图片为例去做一个

BMP图像:

BMP(Bitmap)图像是Windows操作系统的标准文件格式,图像是按从左到右、从下到上的顺序扫描和存储的

灰度图:

灰度图(Gray Scale Image or Grey Scale Image)又称灰阶图。把白色与黑色之间按对数关系分为若干等级级,称为灰度。灰度分为256阶。

BMP图像的格式:

BMP格式的文件从头到尾依次是如下信息:

BMP文件头(bmp file header):共14byte

BMP文件位图信息头(bit information):共40byte

调色版(color palette):可选,由颜色索引决定

位图数据:由图像尺寸决定

BMP文件头: 

在其中:

 bfSize和bfOffBits可以利用windows的库函数读出

	bfhead.bfSize=14+40+sizeof(RGBQUAD)*256+NewLineByte*bihead.biHeight;
	bfhead.bfOffBits=14+40+sizeof(RGBQUAD)*256;

BMP文件位图信息头:

特别注意BMP中的结构对齐:

数据按照像素进行包装,便于读取,但这并不是全部,其中会涉及补零操作(zero-padding)

BMP的“数据4字节对齐”以及像素定位算法的个人探究_qyze的博客-CSDN博客

读取图像的信息: 

将文件指定区域的

	BITMAPFILEHEADER bfhead;
 	BITMAPINFOHEADER bihead;
	FILE *fp=fopen("cat.bmp","rb");//打开文件流
	if(0==fp)
	{
		printf("OpenFilefail!");
		return 0;
	}
	//分别为要存入的存储区域,每个数据块的字节数,读取的块数,文件指针
	fread(&bfhead,14,1,fp);
	fread(&bihead,40,1,fp);
	printf("Width:%d, Height: %d,biBitCount:%d\n",bihead.biWidth,bihead.biHeight,bihead.biBitCount);

将颜色索引变为灰度索引:

	RGBQUAD *pColorTable=new RGBQUAD[256];
	for(int i=0;i<256;i++)
	{
		pColorTable[i].rgbRed = pColorTable[i].rgbGreen = pColorTable[i].rgbBlue = i;//使颜色表中每种颜色的R,G,B分量相等且等于索引值
	}

计算出像素的灰度值:

	unsigned char *pNewBmpBuf=new unsigned char[NewLineByte*bihead.biHeight];		
	for(int i=0;i<bihead.biHeight;i++)
		for(int j=0;j<bihead.biWidth;j++)
		{
			char *pb1,*pb2;
			pb1=pBmpBuf+i*LineByte+j*3;
			int y=*(pb1)*0.299+*(pb1+1)*0.587+*(pb1+2)*0.114;
			pb2=pNewBmpBuf+i*NewLineByte+j;
			*pb2=y;
		}

全部代码:

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

int main()
{
	BITMAPFILEHEADER bfhead;
 	BITMAPINFOHEADER bihead;
	FILE *fp=fopen("cat.bmp","rb");//打开文件流
	if(0==fp)
	{
		printf("OpenFilefail!");
		return 0;
	}
	//分别为要存入的存储区域,每个数据块的字节数,读取的块数,文件指针
	fread(&bfhead,14,1,fp);
	fread(&bihead,40,1,fp);
	printf("Width:%d, Height: %d,biBitCount:%d\n",bihead.biWidth,bihead.biHeight,bihead.biBitCount);
	
	int LineByte=(bihead.biWidth*24/8+3)/4*4;
	//分配内存去存储图像数据
	unsigned char *pBmpBuf=new unsigned char[LineByte*bihead.biHeight];
	fread(pBmpBuf,LineByte*bihead.biHeight,1,fp);       //将bmp数据区读入内存
	fclose(fp);//关闭文件流
	//输出图像的长宽和高
	FILE *newfp=fopen("newcat.bmp","wb");
	if(0==newfp)
	{
		printf("CreatFilefail!");
		return 0;
	}
	
	int NewLineByte=(bihead.biWidth*8/8+3)/4*4;  //由于灰度化后每像素位数变为8,所以每行字节数发生改变,但仍要求为4的整数倍
	
	//图片的大小
	bfhead.bfSize=14+40+sizeof(RGBQUAD)*256+NewLineByte*bihead.biHeight;
	bfhead.bfOffBits=14+40+sizeof(RGBQUAD)*256;
	//将bmpfilehead写入
	fwrite(&bfhead,14,1,newfp);
	//	将bmpbithead写入
	bihead.biBitCount=8;    //更改每像素位数
	bihead.biSizeImage=NewLineByte*bihead.biHeight;
	fwrite(&bihead,40,1,newfp);
	//灰度为1的rgb值分别为1,1,1,所以将256位颜色的颜色表分别置为相同的灰度值
	RGBQUAD *pColorTable=new RGBQUAD[256];
	for(int i=0;i<256;i++)
	{
		pColorTable[i].rgbRed = pColorTable[i].rgbGreen = pColorTable[i].rgbBlue = i;//使颜色表中每种颜色的R,G,B分量相等且等于索引值
	}
	fwrite(pColorTable,sizeof(RGBQUAD),256,newfp);

	
	unsigned char *pNewBmpBuf=new unsigned char[NewLineByte*bihead.biHeight];		
	for(int i=0;i<bihead.biHeight;i++)
		for(int j=0;j<bihead.biWidth;j++)
		{
			unsigned char *pb1,*pb2;
			pb1=pBmpBuf+i*LineByte+j*3;
			int y=*(pb1)*0.299+*(pb1+1)*0.587+*(pb1+2)*0.114;
			pb2=pNewBmpBuf+i*NewLineByte+j;
			*pb2=y;
		}

 fwrite(pNewBmpBuf,NewLineByte*bihead.biHeight,1,newfp);
 fclose(newfp);
 

 return 0;
}

cat.bmp:

newcat.bmp:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从零开始写一个图像处理程序之一(BMP彩色图转灰度图) 的相关文章

随机推荐

  • Linux创建普通用户并设置目录权限

    文章目录 前言 使用步骤 1 创建普通用户 2 创建docker用户组 3 测试 4 扩展 前言 实际工作中 通常为什么不直接使用root账户而要使用普通账户呢 因为root的权限太大了 一旦用户 特别是小白用户直接使用root账户的话 那
  • Error response from daemon: unauthorized: unauthorized to access repository:xxx

    问题描述 Jenkins构建项目异常 xff1a Unable to span class token function find span image span class token string 39 xxx latest 39 sp
  • 宝塔Linux面板phpMyAdmin无法打开/打开404完美解决方案

    文章目录 问题描述解决方案1 宝塔放行端口2 放行安全组端口3 解决开启防火墙方案3 1 方案一 xff1a 放行防火墙端口3 2 方案二 xff1a 关闭防火墙 问题描述 宝塔面板安装phpMyAdmin后打不开 xff0c 无响应 解决
  • Ubuntu18.04配置PX4编译环境

    最近尝试使用Ubuntu18 04重新配置了一下PX4编译环境 http dev px4 io master en setup dev env linux ubuntu html 跟着官网走 非常简单 1 运行ubuntu sim ros
  • Windows高精度时钟

    封装几个代码 xff0c 方便以后查询和使用 Windows高精度时钟 精度 xff1a lt 1us 微秒 1 1Function 1统计一段代码的CPU时间 LARGE INTEGER freq span class token pun
  • LAMP平台配置

    Apache安装 安装httpd 96 yum y install httpd 96 启动apache服务 xff1a service httpd start验证apache的端口是否开放 xff1a ss antpl grep 80建立a
  • ROS实战篇(二)如何创建自定义的msg文件以及自己编写launch文件?

    一 如何创建自定义的msg文件 xff1f msg文件介绍 xff1a 1 msg文件是用来描述ROS中自定义的消息类型的 xff0c 可以被不同语言调用 2 msg文件以 msg 结尾 xff0c 必须存放在软件包的msg文件夹下 3 m
  • 十五、Linux驱动之USB鼠标驱动

    1 如何编写USB鼠标驱动 结合十四 Linux驱动之USB驱动分析中的分析 xff0c 我们开始写一个USB鼠标驱动 USB的驱动可以分为3类 xff1a SoC的USB控制器的驱动 xff0c 主机端USB设备的驱动 xff0c 设备上
  • kazam录制视频转码

    Ubuntu安装kazam录制视频转码问题 录制转码 录制 在ubuntu下录制视频发现录制mp4视频在windows中大部分无法打开播放只有potplayer可以 xff0c 主要是两边视频格式不支持 xff0c 为此需要进行转码 转码
  • layui实现文件分片上传

    html代码 lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 utf 8 34 gt lt title gt layui lt title gt lt meta
  • C++ day42 C++的其他类库(除STL外)

    STL已经提供了一个非常好的可重用代码源 xff0c STL工具可以被用来解决很多编程问题了 xff0c 但是C 43 43 还是觉得不够 xff0c 在STL之外 xff0c 也提供了一些模板类 xff0c 这些模板类基本都是用来做一件很
  • python爬虫beautifulsoup详细教程

    BeautifulSoup4是爬虫必学的技能 BeautifulSoup最主要的功能是从网页抓取数据 xff0c Beautiful Soup自动将输入文档转换为Unicode编码 xff0c 输出文档转换为utf 8编码 Beautifu
  • pandas用法详解

    一 生成数据表 1 首先导入pandas库 xff0c 一般都会用到numpy库 xff0c 所以我们先导入备用 xff1a import numpy as np import pandas as pd 2 导入CSV或者xlsx文件 xf
  • 程序员读书顺序!

    程序猿的读书历程 xff1a xx语言入门 gt xx语言应用实践 gt xxx语言高阶编程 gt xxx语言的科学与艺术 gt 编程之美 gt 编程之道 gt 编程之禅 gt 颈椎病康复指南
  • 基于STM32的倾斜仪设计(二)—— 硬件设计(2)

    2 4控制电路 本实验中选用的控制核心是STM32系列单片机 xff0c 具体型号为STM32F103R8T6 STM32F103R8T6是一款嵌入式 微控制器集成电路 xff0c 是ST旗下的一款常用的增强型系列微控制器 此芯片工作电压为
  • win32多媒体定时器

    win32多媒体定时器 因为编程需要以1ms为周期调用一个函数 xff0c 故在Windows平台上测试了一些定时器 xff0c 并进行比较 xff0c 最终选用timeSetEvent作为最终选项 几个拉跨的定时器精度 select选择模
  • 树莓派005_L298N电机控制板

    硬件接口 ENA IN1 IN2 控制左边的电机A xff0c ENB IN3 IN4控制右边的电机B 以上六个全部接GPIO口 xff0c 可通过pwm控制ENA ENB实现调速 43 12V为外接电源正极接入口 GND为外接电源负极接入
  • Vue实现Enter键查询

    单个条件 xff1a 64 keyup span class token punctuation span enter span class token punctuation span native span class token op
  • 图文详解教你在线换系统(无须U盘)

    1 先去msdn下载需要安装的系统 建议不要下载到系统盘 系统下载传送门 2 系统下载后 xff0c 双击打开找到setup xff0c 然后以管理员权限打开 3 打开windows安装界面后 xff0c 选择更改windows安装程序下载
  • 从零开始写一个图像处理程序之一(BMP彩色图转灰度图)

    图像二值化可以直接调用opencv的二值化函数去完成处理 xff0c 但是不利用OpenCV从头手写一个处理图片程序未尝不是一件有意思的事情 xff0c 就拿BMP图片为例去做一个 BMP图像 xff1a BMP xff08 Bitmap