【数字图像处理】——BMP文件的简单操作_hxlbmpfile.h-程序员宅基地

技术标签: c++  笔记  可视化  计算机视觉  

1、在 VC 环境下 – 建立动态库工程,录入 HXLBMPFILE 类,建立相应动态库,将整个类作为动态库输出。

输出 HXLBMPFILE.dll/lib 。可参考动态库如何建立
录入 hxlbmpfile.h 文件,包含 HXLBMPFILE 类 的定义

#pragma once

#include"stdio.h"
#include"math.h"
#include"windows.h"
#include<iostream>
using namespace std;

#ifndef HXLBMPFILEH
#define HXLBMPFILEH

class _declspec(dllexport) HXLBMPFILE 
{
    
	BYTE *Imagedata;//位图数据域
public:
	int imagew;//图片的宽度
	int imageh;//图片的高度
	int iYRGBnum;//1:灰度,3:彩色

	RGBQUAD palette[256];//调色板

	 BYTE *pDataAt(int h, int Y0R0G1B2 = 0);//指向图像第h行的位置,Y0R0G1B2表示:灰度(Y)=0,R=0,G=1,B=2
	 BOOL AllocateMem();//为图像分配内存

	 BOOL LoadBMPFILE(const char *fname);
	 BOOL SaveBMPFILE(const char *fname);

	 HXLBMPFILE();
	 ~HXLBMPFILE();
};
#endif

录入 hxlbmpfile.cpp 文件,包含 HXLBMPFILE 类的实现

#include "stdafx.h"
#include "HXLBMPFILE.h"
//#define _CRT_SECURE_NO_WARNINGS
//#define _CRT_SECURE_NO_DEPRECATE
#pragma warning(disable:4996);

HXLBMPFILE::HXLBMPFILE() {
    
	Imagedata = NULL;
	for (int i = 0; i < 256; i++) {
    
		palette[i].rgbBlue = i;
		palette[i].rgbGreen = i;
		palette[i].rgbRed = i;
		palette[i].rgbReserved = 0;
	};
	iYRGBnum = 0;
	imagew = imageh = 0;

};


HXLBMPFILE::~HXLBMPFILE() {
    
	if (Imagedata)delete[]Imagedata;
};

BYTE  *HXLBMPFILE::pDataAt(int h, int Y0R0G1B2) {
    
	if (iYRGBnum <= Y0R0G1B2)return NULL;
	int w = imagew * h + Y0R0G1B2 * imagew*imageh;
	return Imagedata + w;
};

BOOL HXLBMPFILE::AllocateMem() {
    
	int w = imagew * imageh*iYRGBnum;
	if (Imagedata) {
    
		delete[] Imagedata;
		Imagedata = NULL;
	};
	Imagedata = new BYTE[w];
	if (Imagedata) memset(Imagedata, 0, w);
	return (Imagedata != NULL);
};

BOOL HXLBMPFILE::LoadBMPFILE(const char *cFilename) {
    
	FILE *f;
	if (strlen(cFilename) < 1) return FALSE;

	f = fopen(cFilename, "r+b");
	if (f == NULL)return FALSE;

	BITMAPFILEHEADER fh;
	BITMAPINFOHEADER ih;

	fread(&fh, sizeof(BITMAPFILEHEADER), 1, f);
	if (fh.bfType != 0x4d42) {
    
		fclose(f);
		return FALSE;
	};

	fread(&ih, sizeof(BITMAPINFOHEADER), 1, f);
	if ((ih.biBitCount != 8) && (ih.biBitCount != 24)) {
    
		fclose(f);
		return FALSE;
	};

	iYRGBnum = ih.biBitCount / 8;
	imagew = ih.biWidth;
	imageh = ih.biHeight;

	if (!AllocateMem()) {
    
		fclose(f);
		return FALSE;
	};
	if (iYRGBnum == 1) {
    
		fread(palette, sizeof(RGBQUAD), 256, f);
	};
	fseek(f, fh.bfOffBits, SEEK_SET);
	int w4b = (imagew*iYRGBnum + 3) / 4 * 4, i, j;
	BYTE *ptr;

	ptr = new BYTE[w4b];
	if (ptr == NULL) {
    
		fclose(f);
		return FALSE;
	};
	if (iYRGBnum == 1) {
    
		for (i = imageh - 1; i >= 0; i--) {
    
			fread(ptr, w4b, 1, f);
			memmove(pDataAt(i), ptr, imagew);
		}
	}
	if (iYRGBnum == 3) {
    
		for (i = imageh - 1; i >= 0; i--)
		{
    
			fread(ptr, w4b, 1, f);
			for (j = 0; j < imagew; j++)	
			{
    
				*(pDataAt(i, 0) + j) = *(ptr + j * 3 + 2);
				*(pDataAt(i, 1) + j) = *(ptr + j * 3 + 1);
				*(pDataAt(i, 2) + j) = *(ptr + j * 3 + 0);
			}
		}
	}
	delete[]ptr;
	fclose(f);
	return TRUE;
};

BOOL HXLBMPFILE::SaveBMPFILE(const char *cFilename) {
    
	if (!Imagedata)return FALSE;
	FILE *f;
	if (strlen(cFilename) < 1)return FALSE;
	f = fopen(cFilename, "w+b");
	if (f == NULL)return FALSE;

	BITMAPFILEHEADER fh;
	BITMAPINFOHEADER ih;
	memset(&ih, 0, sizeof(BITMAPINFOHEADER));

	fh.bfType = 0x4d42;
	fh.bfReserved1 = fh.bfReserved2 = 0;
	fh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + ((iYRGBnum == 1) ? 256 * sizeof(RGBQUAD) : 0);
	ih.biSize = 40;
	ih.biPlanes = 1;
	ih.biWidth = imagew;
	ih.biHeight = imageh;
	ih.biBitCount = 8 * iYRGBnum;//iRGBnum

	int w4b = (imagew*iYRGBnum + 3) / 4 * 4;//iRGBnum
	ih.biSizeImage = ih.biHeight*w4b;
	fh.bfSize = fh.bfOffBits + ih.biSizeImage;

	fwrite(&fh, sizeof(BITMAPFILEHEADER), 1, f);
	fwrite(&ih, sizeof(BITMAPINFOHEADER), 1, f);
	if (iYRGBnum == 1)fwrite(palette, sizeof(RGBQUAD), 256, f);//iRGBnum

	BYTE* ptr;
	int i, j;
	ptr = new BYTE[w4b];
	if (ptr == NULL) {
    
		fclose(f);
		return FALSE;
	}
	memset(ptr, 0, w4b);
	if (iYRGBnum == 1) {
    
		for (i = ih.biHeight - 1; i >= 0; i--) {
    
			memmove(ptr, pDataAt(i), ih.biWidth);
			fwrite(ptr, w4b, 1, f);
		}
	}
	if (iYRGBnum == 3) {
    
		for (i = ih.biHeight - 1; i >= 0; i--) {
    
			for (j = 0; j < ih.biWidth; j++) {
    
				*(ptr + j * 3 + 0) = *(pDataAt(i, 2) + j);
				*(ptr + j * 3 + 1) = *(pDataAt(i, 1) + j);
				*(ptr + j * 3 + 2) = *(pDataAt(i, 0) + j);
			}
			fwrite(ptr, w4b, 1, f);
		}
	}
	delete[]ptr;
	fclose(f);
	return TRUE;
}

2、录入主函数(根据需要注释某段代码段)
int main()
{
    
	HXLBMPFILE bmpfile;
	if (!bmpfile.LoadBMPFILE("1.bmp")) return 1;
	cout << "bmpfile.iYRGBnum=" << bmpfile.iYRGBnum << endl;

	HXLBMPFILE bf;
	bf.imagew = bmpfile.imagew;
	bf.imageh = bmpfile.imageh;
	bf.iYRGBnum =bmpfile.iYRGBnum;//toGrey函数需将此值替换为1
	if (!bf.AllocateMem())return 1;
//ReverseWhite(bf, bmpfile);//反白函数
//bf.SaveBMPFILE("ReverseWhite.bmp");//反白图的存储

//Pallette(bmpfile);//改变调色板函数
//bmpfile.SaveBMPFILE("Pallette.bmp");//改变调色板后图的存储

//toGrey(bf, bmpfile);//彩色变灰度图像函数
//bf.SaveBMPFILE("toGrey.bmp");//新的灰度图像的存储

//	toTxt(bmpfile);//将图像数据转为txt文件


	cout << "program ends! " << endl;
	return 0;
   
}

3、反白函数
//反白函数
void ReverseWhite(HXLBMPFILE &bf, HXLBMPFILE &bmpfile) //bf反白后的图像,bmpfile原图像
{
    
	cout << "这是反白函数" << endl;
	//cout << "bmpfile.iYRGBnum=" << bmpfile.iYRGBnum << endl;
	if (bmpfile.iYRGBnum == 1) {
    
		for (int i = 0; i < bmpfile.imageh; i++) {
    
				for (int j = 0; j < bmpfile.imagew; j++) {
    
					bf.pDataAt(i)[j] = 255 - bmpfile.pDataAt(i)[j];
				}
			}
	}
	else {
    
		for (int i = 0; i < bmpfile.imageh; i++) {
    
			for (int j = 0; j < bmpfile.imagew; j++)
						{
    
							bf.pDataAt(i, 0)[j] = 255 - bmpfile.pDataAt(i, 0)[j];
							bf.pDataAt(i, 1)[j] = 255 - bmpfile.pDataAt(i, 1)[j];
							bf.pDataAt(i, 2)[j] = 255 - bmpfile.pDataAt(i, 2)[j];
						}
		}
			
	}
	
}
4、改变调色板的颜色值,看对图像的影响
//改变调色板函数
void Pallette(HXLBMPFILE &bmpfile) {
    
	cout << "这是改变调色板的函数" << endl;
	for (int i = 0; i < 256; i++) {
    
			bmpfile.palette[i].rgbRed = i;//此值可随意改变
			bmpfile.palette[i].rgbGreen = 10*i;
			bmpfile.palette[i].rgbBlue = 2*i;
	}
}
5、将彩色图像变为灰度图象
将彩色图像变为灰度图像
void toGrey(HXLBMPFILE &bf, HXLBMPFILE &bmpfile) {
    
	cout << "这是将彩色图像变为灰度图像的函数" << endl;
	cout << "bmpfile.iYRGBnum=" <<bmpfile.iYRGBnum << endl;
	int i, j;
		for (i = 0; i < bmpfile.imageh; i++) {
    
			for (j = 0; j < bmpfile.imagew; j++)
			{
    
            	//bf.pDataAt(i)[j] = bmpfile.pDataAt(i, 0)[j] * 0.299 + bmpfile.pDataAt(i, 1)[j] * 0.587 + (float)bmpfile.pDataAt(i, 2)[j] * 0.114;
				//上下两种格式都可
                bf.pDataAt(i)[j] = int((float)bmpfile.pDataAt(i, 0)[j] * 0.299 + (float)bmpfile.pDataAt(i, 1)[j] * 0.587 + (float)bmpfile.pDataAt(i, 2)[j] * 0.114);         
			}
		}
}
6、在 excel 中可视化图像数据

编程实现:将一灰度图像数据变成文本格式存 储到 bmp.txt 中,txt 文件的一行对应图像的一 行,按图像显示的顺序存储。将 bmp.txt 调入到 excel 中。 用excel的至少3种可视化工具(如曲线显示等)将 bmp.txt 图形化显示。

bool toTxt(HXLBMPFILE &bmpfile)	//将bmp数据存入txt
{
    

	FILE *file;
	if ((file = fopen("bmp.txt", "w+")) == NULL)//新建一个文本文件,已存在的文件将内容清空,允许读写
	{
    
		return false;
	}
	for (int i = 0; i < bmpfile.imageh; i++)	
	{
    
		for (int j = 0; j < bmpfile.imagew; j++)
		{
    
			fprintf(file, "%4d", bmpfile.pDataAt(i)[j]);//写入整型数值,宽度为4
		}
		fprintf(file, "\n");//按行写入,换行
	}
	fclose(file);
	return true;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43668040/article/details/105673309

智能推荐

python bokeh_使用 Bokeh 为你的 Python 绘图添加交互性-程序员宅基地

文章浏览阅读145次。本文字数:5051,阅读时长大约:6分钟导读:在 Bokeh 中绘图比其他一些绘图库要复杂一些,但付出额外的努力是有回报的。https://linux.cn/article-12329-1.html作者:Shaun Taylor-morgan译者:Xingyu.Wang在这一系列文章中,我通过在每个 Python 绘图库中制作相同的多条形绘图,来研究不同 Python 绘图库的特性。这次我重点介绍..._bokeh 交互性

CentOS6.7+Mysql5.5.54的rpm安装步骤_mysql-5.5.54-1.linux2.6.x86_64.rpm-bundle.tar-程序员宅基地

文章浏览阅读954次。本次安装Mysql使用的是rpm安装包,可在官网下载。 mysql: MySQL-5.5.54-1.linux2.6.x86_64 linux:CentOS6.7 虚拟机:VMWare12 切换到root用户下 1、首先运行一下两行代码安装必要的依赖,我第一次没有这样做,后续安装会提示缺少perl的依赖等信息yum -y install gcc gcc-c++_mysql-5.5.54-1.linux2.6.x86_64.rpm-bundle.tar

ArcGIS提取影像边界-程序员宅基地

文章浏览阅读1w次,点赞3次,收藏61次。ArcGIS提取影像边界方法1ArcToolbox → 3D Analyst Tools → 转换 → 由栅格转出 → 栅格范围方法2ArcToolbox → 转换工具 → 由栅格转出 → 栅格转面 (这个方法转的面是:栅格中相同值的区域转一个面)方法3利用镶嵌数据集Footprint图层的方法来获取step 1:新建文件型地理数据库test.gdbstep 2:在test.gdb中创建镶嵌数据集Mosaic Datasetstep 3:向镶嵌数据集中添加栅格影像.

【元壤教育AI提示工程系列】『KeepChatGPT教程』轻松解决ChatGPT网络报错,畅享无忧沟通!_! something went wrong. if this issue persists ple-程序员宅基地

文章浏览阅读4.2k次,点赞2次,收藏9次。我们使用ChatGPT时,总是因为网络魔法不力的原因导致页面总是报错,如下图所示:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8QeslNn-1682088798331)(https://file.liyuechun.com/%E6%8F%92%E4%BB%B6.gif)]享受免费的,它代表着你的AI体验发生了骤变:喜欢暗调的朋友可以鼠标移到选择修改为:step one:step two:**step four:**Tampermonkey 搜索,并将 Tamperm_! something went wrong. if this issue persists please contact us through our

3万字智慧交通数字化建设方案_智慧交通中心数字化建设技术方案-程序员宅基地

文章浏览阅读422次。目 &nbsp;&nbsp;录第一章 系统架构 31.1短信系统 41.2数据交换系统 51.3地理信息基础支撑平台 51.4身份及权限管理系统 6第二章 综合管理平台 72.1综合运输监管系统 72.2行业监督管理系统 122.3安全生产监管系统 162.4固定资产管理系统 182.5电子监察系统 192.6行政执法系统 22第三章 公众服务平台 233.1智能手机交通信息服务 233.2出行服务系统 243.3在线呼叫系统 253.4联网售票系统 273.5停车场诱导系统 283.6物流_智慧交通中心数字化建设技术方案

计算机课程教学辅助系统小程序 免费赠送项目完整源码,可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C++、python、数据可视化、大数据、全套文案等-程序员宅基地

文章浏览阅读92次。计算机课程教学辅助系统小程序的设计主要是对系统所要实现的功能进行详细考虑,确定所要实现的功能后进行界面的设计,在这中间还要考虑如何可以更好的将功能及页面进行很好的结合,方便用户可以很容易明了的找到自己所需要的信息,还有系统平台后期的可操作性,通过对信息内容的详细了解进行技术的开发。

随便推点

代理内网穿透-Lcx.exe-venom-proxychains-程序员宅基地

该文章介绍了代理内网穿透的相关知识,包括代理的本质是socks协议,代理的分类,Lcx.exe内网端口转发的步骤,以及venom内网穿透的方法和命令。

【图文详细 】Kafka消息队列——kafka 集群部署_kafka集群入口-程序员宅基地

文章浏览阅读414次。5.1、Kafka 初体验 单机 Kafka 试玩 官网网址:http://kafka.apache.org/quickstart中文官网:http://kafka.apachecn.org/quickstart.html 5.2、集群部署的基本流程总结 1、下载安装包2、解压安装包到对应的目录3、修改配置文件4、分发安装包5、启动集群,进行验证 5.3、集群部..._kafka集群入口

golang动态限制并发数量_golang 限制最大并发-程序员宅基地

文章浏览阅读2.2k次。golang动态控制并发数量_golang 限制最大并发

线段树的基本知识-程序员宅基地

文章浏览阅读175次。好的博客:笨蛋花的小窝qwq一、什么是线段树- 线段树是表示区间及线段的树什么是区间,什么又是线段呢?这里有图- 这样的一棵树,可以解决区间的覆盖问题。例题- 输入m条线段,问这m条线段被覆盖的面积有多大。Sample Input1 23 41 72 13Sample Output13那么这道题怎么做呢?方法一:模拟(容易爆)方法二:首先,由于1-13这个区间跨...

IOS 键盘的显示与关闭-程序员宅基地

文章浏览阅读170次。为什么80%的码农都做不了架构师?>>> ..._双击显示键盘 ios

Neo4j数据导入的几种方式总结_neo4j导入数据-程序员宅基地

文章浏览阅读8k次。1. 通过Cypher语法直接创建该方法适合于数据量小的情况下:例如:create(n:ability {name:"沟通"})create(m:train {name:"培训"})create(n)-[r0:has]-&gt;(a:method {name:"交流"})create(n)-[r1:has]-&gt;(b:method {name:"会议"})create(n)-..._neo4j导入数据

推荐文章

热门文章

相关标签