C++实现binary文件读取(可对‘bil‘,‘bsq‘ float32,double,unchar,unit16,unit8等格式进行读取)

5 篇文章 0 订阅
2 篇文章 0 订阅

C++实现binary文件读取(可对’bil’,‘bsq’ float32,double,unchar,unit16,unit8等格式进行读取)

#pragma once
#include<windows.h>
#include<iostream>
#include<string>
#include<sstream>
#include<fstream>
#include <vector>
#include"image.h"
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class Binary
{
	int binaryWidth;//图像的宽
	int binaryHeight;//图像的高
	int bands;//波段
	string interleave;//数据存储格式(bil,bsq)
	string datatype;//数据类型(int,double,float)
	int Datatype;//头文件中data type表数据类型的数字(1,2,3)
	int headeroffset;//文件头所占字节
	typedef struct tagBINARYINFO//文件头中的信息
	{
		WORD Width;//图像的宽
		WORD Height;//图像的高
		WORD Bands;//图像波段
		WORD Year;//年
		WORD Month;//月
		WORD Day;//日
	}tagBINARYINFO;
	typedef struct tagBINARYHEAD
	{
		char sensor[6];//传感器类型
	}tagBINARYHEAD;
	//读取binary文件头,获取相关参数
	bool readbinaryhead(char* binaryname);
	template<typename T>
	bool readbinary(T* pbinaryBuf, char* readpath, T** band);//读取文件
	/*vector<string> strsplit(const string& s, const string& seperator);*/
public:
	Binary()
	{
		binaryWidth = 0;
		binaryHeight = 0;
		bands = 0;
		Datatype = 0;
		headeroffset = 0;
	}
	int  read(char*);//测试程序
	template<typename T>
	T* readBand(T* imgBuf, const char* data_type, int);//分波段读取数据
};
//读取头文件
bool Binary::readbinaryhead(char* Binaryname)

{
	char* binaryname;
	binaryname = new char[strlen(Binaryname)];
	strcpy(binaryname, Binaryname);//创建副本,保留原指针
	int t = strlen(binaryname);
	if (binaryname[strlen(binaryname) - 4] == '.')//查找文件头文件
	{
		binaryname[strlen(binaryname) - 3] = 'h';
		binaryname[strlen(binaryname) - 2] = 'd';
		binaryname[strlen(binaryname) - 1] = 'r';
	}
	ifstream inf;
	inf.open(binaryname);
	if (!inf.is_open())
	{
		cout << "头文件打开失败!" << endl;
		return 0;
	}
	string sline;//每一行
	string out;
	string s1, s2, s3, s4;
	while (getline(inf, sline))
	{
		istringstream sin(sline);
		sin >> s1 >> s2 >> s3 >> s4;
		if (s1 == "samples")
			binaryWidth = atoi(s3.c_str());
		if (s1 == "lines")
			binaryHeight = atoi(s3.c_str());
		if (s1 == "bands")
			bands = atoi(s3.c_str());
		if (s1 == "header" && s2 == "offset")
			headeroffset = atoi(s4.c_str());
		if (s1 == "data" && s2 == "type")
			Datatype = atoi(s4.c_str());
		if (s1 == "interleave")
			interleave = s3.c_str();
	}
	switch (Datatype)
	{
	case 1:
		datatype = "uint8";// 灰度范围0 - 255
		break;
	case 2:
		datatype = "int16"; // 16位整数
		break;
	case 3:
		datatype = "int32"; // 32位整数
		break;
	case 4:
		datatype = "float32"; // 32位浮点数
		break;
	case 5:
		datatype = "double"; // 64位浮点数
		break;
	case 6:
		datatype = "uint16";//灰度范围0 - 2 ^ 16
		break;
	case 7:
		datatype = "uint32";// 灰度范围0 - 2 ^ 32
		break;
	case 8:
		datatype = "uint64";// 灰度范围0 - 2 ^ 64
		break;
	case 12:
		datatype = "uint16";// 灰度范围0 - 2 ^ 16
		break;
	case 13:
		datatype = "uint32";// 灰度范围0 - 2 ^ 32
		break;
	}
	return 1;
}
template<typename T>
T* Binary::readBand(T* imgBuf, const char* type, int k)//k指波段数
{
	int widthstep = double(binaryWidth) * sizeof(T);
	T* image = new T[binaryWidth * binaryHeight];
	if (strcmp(type, "bil") == 0)
	{
		for (int i = 0; i < binaryHeight; i++)
		{
			for (int j = 0; j < binaryWidth; j++)
			{
				image[i * binaryWidth + j] = imgBuf[binaryWidth * bands * i + binaryWidth * (k - 1) + j];
			}
		}
	}
	if (strcmp(type, "bsq") == 0)
	{
		for (int i = 0; i < binaryHeight; i++)
		{
			for (int j = 0; j < binaryWidth; j++)
			{
				image[i * binaryWidth + j] = imgBuf[(k - 1) * binaryWidth * binaryHeight + i * binaryWidth + j];
			}
		}
	}
	return image;
}
template<typename T>
bool Binary::readbinary(T* pbinaryBuf, char* readpath, T** band)//
{
	FILE* fp; errno_t err;
	err = fopen_s(&fp, readpath, "rb");
	if (err != 0)
	{
		cout << "The file" << readpath << "was not opend" << endl;
		return 0;
	}
	fseek(fp, headeroffset, 0);//跳过头文件所占字节
	double widthstep = double(binaryWidth) * sizeof(T);//计算宽度
	fread(pbinaryBuf, sizeof(T), widthstep * binaryHeight * bands, fp);//读取文件到指针
	fclose(fp);//关闭文件
	if (!pbinaryBuf)
	{
		cout << "输入文件错误!";
		return 0;
	};
	for (int i = 0; i < bands; i++)//为指针申请空间
	{
		band[i] = new T[double(binaryWidth) * binaryHeight];
	}
	for (int i = 0; i < bands; i++)//按波段读取数据
	{
		band[i] = readBand(pbinaryBuf, interleave.c_str(), i + 1);
	}
	return 1;
}
int Binary::read(char* Path)
{
	readbinaryhead(Path);
	switch (Datatype)
	{
	case 1:
	{
		double widthstep = double(binaryWidth) * sizeof(unsigned char);//计算宽度
		unsigned char* pbinaryBuf = new unsigned char[widthstep * binaryHeight * bands];//申请指针所占内存
		unsigned char** band = new unsigned char* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg(binaryHeight, binaryWidth, CV_8UC3);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				myimg.at<Vec3b>(row, col) = Vec3b(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);
			}
		}
		imshow("读取影像", myimg);
		cv::waitKey(0);
	}break;
	case 2:
	{
		double widthstep = double(binaryWidth) * sizeof(short int);//计算宽度
		short int* pbinaryBuf = new short int[widthstep * binaryHeight * bands];//申请指针所占内存
		short int** band = new short int* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg(binaryHeight, binaryWidth, CV_16UC3);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				myimg.at<Vec3s>(row, col) = Vec3s(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);
			}
		}
		imshow("读取影像", myimg * 10);
		cv::waitKey(0);
	}break;
	case 3:
	{
		double widthstep = double(binaryWidth) * sizeof(int);//计算宽度
		int* pbinaryBuf = new int[widthstep * binaryHeight * bands];//申请指针所占内存
		int** band = new int* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg(binaryHeight, binaryWidth, CV_32SC3);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				myimg.at<Vec3s>(row, col) = Vec3s(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);
			}
		}
		imshow("读取影像", myimg * 100);
		cv::waitKey(0);
	}break;
	case 4:
	{
		double widthstep = double(binaryWidth) * sizeof(float);//计算宽度
		float* pbinaryBuf = new float[widthstep * binaryHeight * bands];//申请指针所占内存
		float** band = new float* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg(binaryHeight, binaryWidth, CV_32FC3);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				myimg.at<Vec3f>(row, col) = Vec3f(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);
			}
		}
		imshow("读取影像", myimg / 2047);
		cv::waitKey(0);
	}break;
	case 5:
	{
		double widthstep = double(binaryWidth) * sizeof(double);//计算宽度
		double* pbinaryBuf = new double[widthstep * binaryHeight * bands];//申请指针所占内存
		double** band = new double* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg(binaryHeight, binaryWidth, CV_64FC3);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				myimg.at<Vec3d>(row, col) = Vec3d(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);
			}
		}
		imshow("读取影像", myimg / 2047);
		cv::waitKey(0);
	}break;
	case 12:
	{
		double widthstep = double(binaryWidth) * sizeof(unsigned int);//计算宽度
		unsigned int* pbinaryBuf = new unsigned int[widthstep * binaryHeight * bands];//申请指针所占内存
		unsigned int** band = new unsigned int* [bands];
		readbinary(pbinaryBuf, Path, band);
		Mat myimg;
		if (bands >= 3)
			myimg.create(binaryHeight, binaryWidth, CV_16UC3);
		else
			myimg.create(binaryHeight, binaryWidth, CV_16UC1);
		for (int row = 0; row < binaryHeight; row++)
		{
			for (int col = 0; col < binaryWidth; col++)
			{
				if (bands >= 3)

					myimg.at<Vec3s>(row, col) = Vec3s(band[0][row * binaryWidth + col], band[1][row * binaryWidth + col], band[2][row * binaryWidth + col]);

			}
		}
		
		imshow("读取影像", myimg);
		cv::waitKey(0);
	}break;
	}
	cout << "运行结束!" << endl;
	return 1;
}

总结:
读取文件成功,但是显示图像的时候出现条状混乱线条可能是:
headoffset出错,读取方式bil或者bsq出错,行列数出错;
调用imshow时乘的数字是为了让图像得以显示,后续可以写拉伸程序实现
多波段可以读取成功,单波段暂时不能读取。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.癮.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值