多种格式图像打开与显示

由于图像格式的差异,为了解决图像格式的问题,结合opencv、hdr库写一个能打开、保存多种图像的类。功能如下:
1.打开、保存raw数据
2.打开、保存bmp、jpg、png图像
3.打开、保存tif格式图像
4.打开、保存hdr格式图像

头文件

//#pragma once
#ifndef _CIMAGEFILEOPEN_H
#define _CIMAGEFILEOPEN_H
#include
#include
#include
#include
using namespace cv;
class CImageFileOpen
{
public:
	CImageFileOpen();
	~CImageFileOpen();
public://function
	int MallocData();
	int OpenRawFile(const char* filename, int rows, int cols);
	int ReadHdrFile(const char* filename);
	int ReadBmp(const char* filename);
	int ReadJTP(const char* filename);

	int ImWriteRaw(const char* filename, Mat src);
	int ImWriteBJTP(const char* filename, Mat src);
	int ImWriteHDR(const char* filename, Mat src);
public://data
	/*
	0:表示没有打开图片
	1:Raw数据
	2:hdr图像
	3:bmp
	4:jpg、tif、png
	*/
	size_t m_iFileType;
	size_t m_iRows;
	size_t m_iCols;
	unsigned short* m_pRawData;
	Mat m_mImage;
	std::string m_sFileName;
};
#endif // !_CIMAGEFILEOPEN_H

.cpp文件

#include "ImageFileOpen.h"
#include "hdrloader.h"
typedef  struct  tagBITMAPFILEHEADER
{
	unsigned short int  bfType;       //位图文件的类型,必须为BM 
	unsigned long       bfSize;       //文件大小,以字节为单位
	unsigned short int  bfReserverd1; //位图文件保留字,必须为0 
	unsigned short int  bfReserverd2; //位图文件保留字,必须为0 
	unsigned long       bfbfOffBits;  //位图文件头到数据的偏移量,以字节为单位
}BITMAPFILEHEADER;
typedef  struct  tagBITMAPINFOHEADER
{
	long biSize;                        //该结构大小,字节为单位
	long  biWidth;                     //图形宽度以象素为单位
	long  biHeight;                     //图形高度以象素为单位
	short int  biPlanes;               //目标设备的级别,必须为1 
	short int  biBitcount;             //颜色深度,每个象素所需要的位数
	long  biCompression;             //位图的压缩类型
	long  biSizeImage;              //位图的大小,以字节为单位
	long  biXPelsPermeter;       //位图水平分辨率,每米像素数
	long  biYPelsPermeter;       //位图垂直分辨率,每米像素数
	long  biClrUsed;            //位图实际使用的颜色表中的颜色数
	long  biClrImportant;       //位图显示过程中重要的颜色数
}BITMAPINFOHEADER;

CImageFileOpen::CImageFileOpen():
	m_iFileType(0)
	, m_iRows(1024)
	, m_iCols(1024)
	, m_pRawData(nullptr)
	, m_sFileName("")
{
}

CImageFileOpen::~CImageFileOpen()
{
	if (m_pRawData)
	{
		delete[] m_pRawData;
		m_pRawData = NULL;
	}
}
int CImageFileOpen::MallocData()
{
	if (m_iCols == 0 || m_iRows == 0)
		return 0;//内存分配不合理
	if (m_pRawData)
	{
		delete[] m_pRawData;
		m_pRawData = nullptr;
	}
	size_t size = m_iCols*m_iRows;
	m_pRawData = new unsigned short[size];
	if (m_pRawData)
	{
		memset(m_pRawData, 0, size << 1);
		return 1;
	}
	return 0;//分配失败
}
int CImageFileOpen::OpenRawFile(const char* filename, int rows, int cols)
{
	if (filename == nullptr || rows == 0 || cols == 0)
		return -1;//文件参数有错
	m_sFileName = filename;
	m_iCols = cols;
	m_iRows = rows;
	int tret = MallocData();
	if (!tret)
		return -3;//内存分配失败
	FILE* tFile;
	if (!fopen_s(&tFile, filename, "rb+"))
	{//文件打开成功返回 0      离开时请务必保证图像已经关闭
		fseek(tFile, 0, SEEK_END);     //定位到文件末
		int fileLength = ftell(tFile);
		size_t nSize = (m_iCols*m_iRows);
		if (fileLength < (nSize << 1))
		{
			fclose(tFile);
			return -1;//文件打开成功,但是图像参数设置有误
		}
		else
		{
			fseek(tFile, 0, SEEK_SET);
			if (m_pRawData == NULL)
			{
				fclose(tFile);
				return -2;//文件打开成功,但是图像保存参数设置有误
			}
			//fread_s参数解析 https://docs.microsoft.com/zh-cn/previous-versions/hh977173(v=vs.110)
			fread_s(m_pRawData, nSize << 1, sizeof(unsigned short), nSize, tFile);//bufferSize 目标缓冲区的大小(以字节为单位) 
			fclose(tFile);//关闭文件
			m_mImage = Mat(rows, cols, CV_16UC1);
			memcpy(m_mImage.data, m_pRawData, nSize << 1);
			m_iFileType = 1;//raw 数据
			return 1;//读取文件成功
		}
	}
	else
		return 0;//文件打开失败
}
int CImageFileOpen::ReadHdrFile(const char* filename)
{
	HDRLoaderResult result;
	bool ret = HDRLoader::load(filename, result);
	if (!ret)
		return -1;
	m_iRows = result.height;
	m_iCols = result.width;
	m_mImage = Mat(result.height, result.width, CV_32FC3);
	memcpy(m_mImage.data, result.cols, sizeof(float) * 3 * m_iRows*m_iCols);
	m_sFileName = filename;
	m_iFileType = 2;//hdr 文件
	return 1;//读取文件成功
}
int CImageFileOpen::ReadBmp(const char* filename)
{
	if (filename == nullptr)
		return -1;//文件名为空
	int flags;
	FILE* tFile;
	if (!fopen_s(&tFile, filename, "rb+"))
	{//文件打开成功 请保证离开时关闭文件
	 //跳过位图文件头结构BITMAPFILEHEADER
		fseek(tFile, sizeof(BITMAPFILEHEADER), 0);
		//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
		BITMAPINFOHEADER head;
		fread(&head, sizeof(BITMAPINFOHEADER), 1, tFile);
		int biBitCount = head.biBitcount;//bmp图像的位数  可分8位与24位
		flags = biBitCount == 8 ? 0 : 1;
		flags = biBitCount == 24 ? 1 : 0;
		fclose(tFile);
	}
	else
		return -1;//文件打开失败
	m_mImage = cv::imread(filename, flags);
	m_iFileType = 3;
	m_sFileName = filename;
	return 1;//获取图像成功
}
int CImageFileOpen::ReadJTP(const char* filename)
{
	if (filename == nullptr)
		return -1;//文件名为空
	m_mImage = cv::imread(filename);
	m_iFileType = 4;
	m_sFileName = filename;
	return 1;//获取图像成功
}


int CImageFileOpen::ImWriteRaw(const char* filename, Mat src)
{
	if (filename == nullptr || src.empty())
		return -1;
	Mat tsrc = src.clone();
	int rows = tsrc.rows;
	int cols = tsrc.cols;
	int size = rows*cols;
	if (src.channels() != 1)
		cvtColor(src, tsrc, CV_BGR2GRAY);
	Mat mStore;
	if (tsrc.depth() != 2)
	{
		double dMin, dMax;
		minMaxIdx(tsrc, &dMin, &dMax);
		Mat fsrc;
		tsrc.convertTo(fsrc, CV_32FC1);
		double ddevi = dMax - dMin + DBL_EPSILON;
		for (int i = 0; i < rows; i++)
		{
			float* psrc = fsrc.ptr(i);
			for (int j = 0; j < cols; j++)
			{
				psrc[j] = static_cast((psrc[j] - dMin) / ddevi);
			}
		}
		fsrc.convertTo(mStore, CV_16UC1, 65535);
	}
	FILE* tFile;
	unsigned short *tdata = new unsigned short[size];
	memcpy(tdata, mStore.data, size << 1);
	if (!fopen_s(&tFile, filename, "wb+"))
	{
		fwrite(tdata, sizeof(unsigned short), size, tFile);
		fclose(tFile);
	}
	if (tdata)
	{
		delete[] tdata;
		tdata = nullptr;
	}
	return 1;
}

int CImageFileOpen::ImWriteBJTP(const char* filename, Mat src)
{
	if (filename == nullptr || src.empty())
		return -1;
	std::string tfilename = filename;
	if (tfilename.find(".tif") != std::string::npos)
		imwrite(filename, src);
	int nchannel = src.channels();
	if(src.depth()==1)
		imwrite(filename, src);
	if (nchannel & 2)
	{
		Mat tStore;
		src.convertTo(tStore, CV_32FC3);
		int rows = tStore.rows;
		int cols = tStore.cols;
		Mat ncS[3];
		split(tStore, ncS);
		double dMin, dMax, dMin1, dMax1, dMin2, dMax2;
		minMaxIdx(ncS[0], &dMin, &dMax);
		minMaxIdx(ncS[1], &dMin1, &dMax1);
		minMaxIdx(ncS[2], &dMin2, &dMax2);
		double ddevi = dMax - dMin + DBL_EPSILON;
		double ddevi1 = dMax1 - dMin1 + DBL_EPSILON;
		double ddevi2 = dMax2 - dMin2 + DBL_EPSILON;
		for (int i = 0; i < rows; i++)
		{
			float* psrc = ncS[0].ptr(i);
			float* psrc1 = ncS[1].ptr(i);
			float* psrc2 = ncS[2].ptr(i);
			for (int j = 0; j < cols; j++)
			{
				psrc[j] = static_cast((psrc[j] - dMin) / ddevi);
				psrc1[j] = static_cast((psrc1[j] - dMin) / ddevi1);
				psrc2[j] = static_cast((psrc2[j] - dMin) / ddevi2);
			}
		}
		merge(ncS, 3, tStore);
		Mat store;
		tStore.convertTo(store, CV_8UC3, 255);
		imwrite(filename, store);
		return 1;
	}
	else
	{
		Mat tStore;
		src.convertTo(tStore, CV_32FC1);
		int rows = tStore.rows;
		int cols = tStore.cols;
		double dMin, dMax;
		minMaxIdx(tStore, &dMin, &dMax);
		double ddevi = dMax - dMin + DBL_EPSILON;
		for (int i = 0; i < rows; i++)
		{
			float* psrc = tStore.ptr(i);
			for (int j = 0; j < cols; j++)
			{
				psrc[j] = static_cast((psrc[j] - dMin) / ddevi);
			}
		}
		Mat store;
		tStore.convertTo(store, CV_8UC1, 255);
		imwrite(filename, store);
		return 1;
	}
}

int CImageFileOpen::ImWriteHDR(const char* filename, Mat src)
{
	if (filename == nullptr || src.empty())
		return -1;
	int nchannel = src.channels();
	Mat tStore;
	if (nchannel & 2)
	{
		src.convertTo(tStore, CV_32FC3);
		int rows = tStore.rows;
		int cols = tStore.cols;
		Mat ncS[3];
		split(tStore, ncS);
		double dMin, dMax, dMin1, dMax1, dMin2, dMax2;
		minMaxIdx(ncS[0], &dMin, &dMax);
		minMaxIdx(ncS[1], &dMin1, &dMax1);
		minMaxIdx(ncS[2], &dMin2, &dMax2);
		double ddevi = dMax - dMin + DBL_EPSILON;
		double ddevi1 = dMax1 - dMin1 + DBL_EPSILON;
		double ddevi2 = dMax2 - dMin2 + DBL_EPSILON;
		for (int i = 0; i < rows; i++)
		{
			float* psrc = ncS[0].ptr(i);
			float* psrc1 = ncS[1].ptr(i);
			float* psrc2 = ncS[2].ptr(i);
			for (int j = 0; j < cols; j++)
			{
				psrc[j] = static_cast((psrc[j] - dMin) / ddevi);
				psrc1[j] = static_cast((psrc1[j] - dMin) / ddevi1);
				psrc2[j] = static_cast((psrc2[j] - dMin) / ddevi2);
			}
		}
		merge(ncS, 3, tStore);
	}
	else
	{
		src.convertTo(tStore, CV_32FC1);
		int rows = tStore.rows;
		int cols = tStore.cols;
		double dmin, dmax;
		minMaxIdx(tStore, &dmin, &dmax);
		double dSub = dmax - dmin + DBL_EPSILON;
		for (int i = 0; i < rows; i++)
		{
			float* psrc = tStore.ptr(i);
			for (int j = 0; j < cols; j++)
			{
				psrc[j] = static_cast((psrc[j] - dmin) / dSub);
			}
		}
		Mat ncS[3];
		tStore.copyTo(ncS[0]);
		tStore.copyTo(ncS[1]);
		tStore.copyTo(ncS[2]);
		merge(ncS, 3, tStore);
	}
	FILE* tStoref;
	if (!fopen_s(&tStoref, filename, "wb+"))
	{
		int width = tStore.cols;
		int height = tStore.rows;
		int size = width*height;
		rgbe_header_info info;
		memset(&info, 0, sizeof(rgbe_header_info));
		info.valid = 1;
		strcpy_s(info.programtype, "RADIANCE");
		RGBE_WriteHeader(tStoref, width, height, &info);
		float* wdata = new float[size * 3];
		if (wdata == NULL)
		{
			fclose(tStoref);
			return -1;
		}
		memset(wdata, 0, size * 3 * sizeof(float));
		size_t position = 0;
		int nc = width * tStore.channels();
		for (int i = 0; i < height; i++)
		{
			float* data = tStore.ptr(i);
			for (int j = 0; j < nc; j++)
			{
				wdata[position + j] = data[j];
			}
			position += nc;
		}
		RGBE_WritePixels(tStoref, wdata, size);
		fclose(tStoref);
		if (wdata)
		{
			delete[] wdata;
			wdata = NULL;
		}
		return 1;
	}
	else
		return 0;	
}

测试程序

#include
#include"ImageFileOpen.h"
using namespace std;
int main()
{
	CImageFileOpen tem;
//	const char* fileName = "D:\\41.raw";
//	tem.OpenRawFile(fileName, 1024, 1024);
	const char* fileName = "D:\\hdrPic\\belgium.hdr";
	tem.ReadHdrFile(fileName);
	
	imshow("src", tem.m_mImage);
	waitKey(0);
	return 0;
}

不当之处,欢迎指正。

你可能感兴趣的:(数字图像)