C++读写tif文件

当初第一次接触tif格式的图像,按照教程读取了一下,程序如下,后来发现opencv就可以读取

imread 参数设置为 IMREAD_UNCHANGED


#include<iostream>
#include <opencv2/opencv.hpp>

#ifndef TIFREADER_H 
#define TIFREADER_H 

#include <stdio.h>
#include <string.h>

#ifndef NULL
#define NULL   0
#endif

#ifndef TRUE
#define TRUE   1
#define FALSE  0
#endif

#define BYTE short

using namespace std;
//using namespace cv;

typedef struct
{
	unsigned short Byte_order;//
	unsigned short Version;//校验文件是否是TIF文件
	unsigned   int OffsetToFirstFID;//相对对文件开始处的偏移量
									// unsigned short wDECount;//多少目录入口
}IFH;

typedef struct
{
	unsigned short tag;//属性的编号
	unsigned short type;//数据类型
	unsigned long length;//数据的数量
	unsigned long valueOffset;//tag标识的属性代表的变量值相对文件开始处的偏移量
}DE;
typedef struct
{
	int width;
	int height;

}Size;
typedef struct
{
	short *data;
}DATA;

typedef struct
{
	DE *pde;
	int wDECount;
}PDE;

bool readTIF(char* path, IFH &ifh, PDE &de, Size &size, DATA &Data)
{
	//unsigned char *data;
	short *data;
	short *dat;
	unsigned short wDECount;//多少目录入口

							

	
	//FILE* fp = NULL;
	//errno_t err = 0;
	//err = fopen_s(&fp, path, "r");
	FILE *fp;
	fp = fopen(path, "r");
	//fp = fopen_s(path, "rb");
	if (fp ==  NULL)
	{
		cout << "open file error" << endl;
		return false;
	}
	if (sizeof(IFH) != fread(&ifh, 1, sizeof(IFH), fp))
	{
		cout << "读TIF文件头失败";
		return FALSE;
	}
	cout << ifh.Version << endl;
	if (0x2a != ifh.Version)  // 42
	{
		cout << "该文件不是TIF格式,读文件失败";
		return FALSE;
	}

	if (0x4949 != ifh.Byte_order) //18761
	{
		cout << "该TIF文件不是IBMPC字节序,读文件失败";
		return FALSE;
	}

	fseek(fp, ifh.OffsetToFirstFID, SEEK_SET);//将文件指针定位到IFD
											  //读文件有多少个目录入口 
	if (2 != fread(&wDECount, 1, sizeof(unsigned short), fp))
	{
		cout << "无法获得TIF文件目录入口数量";
		return FALSE;
	}
	cout << "该TIF文件有" << wDECount << "个目录入口" << endl;
	//创建DE数组,接收信息,数组中有wDECount个元素 
	de.pde = new DE[wDECount];
	DE* pTemp = de.pde;
	de.wDECount = wDECount;
	memset(de.pde, 0, sizeof(DE)*wDECount);
	if (sizeof(DE)*wDECount != fread(de.pde, 1, sizeof(DE)*wDECount, fp))
	{
		cout << "读图象文件目录失败";
		delete[]de.pde;
		return false;
	}
	//把图像的大小和图像数据的容量保存到成员变量中
	int m_size_x;
	int m_size_y;
	int m_size;
	int m_channel;
	int i;
	for (i = 0; i<wDECount; i++)
	{
		pTemp = de.pde + i;
		cout << pTemp->tag << endl;
		if (256 == pTemp->tag) //tag为256的目录入口中的变量标识了图象宽度
		{
			m_size_x = pTemp->valueOffset;
		}
		if (257 == pTemp->tag) //图象高度
		{
			m_size_y = pTemp->valueOffset;
		}
		if (278 == pTemp->tag)
		{
			m_channel = pTemp->valueOffset;

		}
		// For each strip, the byte offset of that strip.
		if (273 == pTemp->tag) //计算图象数据占用字节数
		{
			//m_dwBmSize = pTemp->valueOffset - sizeof(IFH);
			//或者把tag=256的valueOffset乘以tag=257的valueOffset
			m_size = m_size_x * m_size_y;
		}
	}
	m_channel = pTemp->valueOffset;
	//填充所有像素数据, 颠倒图象数据从最后一行开始读起
	int j = 0;
	// int i = 0;
	data = (short*)malloc(m_size * sizeof(BYTE));
	dat = (short*)malloc(m_size * sizeof(BYTE));


	//IFH - 图像数据 - IFD
	fseek(fp, sizeof(IFH), SEEK_SET); //文件开头
	fread(data,  sizeof(BYTE), m_size, fp);

	
	//fread(imagedata, sizeof(struct tagIMAGEDATA) * width, height, fpi);
	//for (i = m_size_y - 1; i >= 0; i--)
	//{
	//	fseek(fp, sizeof(IFH) + i*m_size_x, SEEK_SET); //文件开头
	//	fread((BYTE*)(data + 1) + j*m_size_x, sizeof(BYTE), m_size_x, fp);
	//	j++;
	//}




	//for (i = m_size_y - 1; i >= 0; i--)
	//{
	//	fseek(fp, sizeof(IFH) + i*m_size_x, SEEK_SET); //文件开头
	//	fread((BYTE*)(data + 1) + j*m_size_x, sizeof(BYTE), m_size_x, fp);
	//	j++;
	//}

	cv::Mat tmp;
	tmp.create(m_size_y, m_size_x, CV_16UC1);         //创建Mat
	memcpy(tmp.data, data, m_size * sizeof(short)); //内存拷贝
	fp = nullptr;

	//for (int i = 0; i < m_size_y; i++)
	//{
	//	
	//	for (int j = 0; j < m_size_x; ++j)
	//	{
	//		cout << tmp.at<short>(i, j) << " "; // 
	//	}
	//	cout << endl;
	//}


	//free(data);
	/*cv::namedWindow("1", 1);
	cv::imshow("1", tmp);*/
	cout << "width:" << m_size_x << endl;
	cout << "height:" << m_size_y << endl;
	short * p;
	p = data;
	short *ptr;
	ptr = dat;
	for (i = 0; i<m_size; i++, p++, ptr++)
	{
		*ptr = (short)(*p);
		short  h = *ptr;

		cout<<h<<" ";
	}


	size.width = m_size_x;
	size.height = m_size_y;
	Data.data = dat;
	return TRUE;

}



int main()
{
	IFH ifh;
	PDE de;
	Size size;
	DATA Data;
	char * path = "16.tif";
	//cv::Mat test2 = cv::imread("16.tif", CV_LOAD_IMAGE_ANYDEPTH);

	//cout << " " << test2.depth() << endl;

	//for (int i = 0; i < test2.rows; i++)
	//{
	//	for (int j = 0; j < test2.cols; j++)
	//	{
	//		cout << test2.at<unsigned short>(i, j) << endl;

	//	}

	//}

	//cout << test2.at<unsigned short>(0, 0) << endl;
	bool b = readTIF(path, ifh, de, size, Data);
	cout << Data.data << endl;
	cout << b << endl;
	cv::waitKey(0);
	system("pause");
	return 0;
}



bool saveTIF(char* path, IFH ifh, PDE de, Size size, DATA Data)
{
	unsigned char *data;
	//    unsigned short wDECount;//多少目录入口

	//	ZeroMemory(&ifh, sizeof(IFH));
	//	ZeroMemory(&de, sizeof(DE));

	FILE *fp;
	fp = fopen(path, "wb");
	if (fp == NULL)
	{
		cout << "open file error" << endl;
		return false;
	}
	if (sizeof(IFH) != fwrite(&ifh, 1, sizeof(IFH), fp))
	{
		cout << "写TIF文件头失败";
		return FALSE;
	}
	fseek(fp, ifh.OffsetToFirstFID, SEEK_SET);//将文件指针定位到IFD
											  //读文件有多少个目录入口 
	if (2 != fwrite(&de.wDECount, 1, sizeof(unsigned short), fp))
	{
		cout << "无法获得TIF文件目录入口数量";
		return FALSE;
	}
	//创建DE数组,接收信息,数组中有wDECount个元素 

	if (sizeof(DE)*de.wDECount != fwrite(de.pde, 1, sizeof(DE)*de.wDECount, fp))
	{
		cout << "读图象文件目录失败";
		return false;
	}
	//填充所有像素数据, 颠倒图象数据从最后一行开始读起
	int j = 0;
	int i = 0;
	data = (unsigned char*)malloc(size.width*size.height * sizeof(BYTE));
	short *ptr = Data.data;

	unsigned char* p;
	p = data;
	for (i = 0; i<size.width*size.height; i++, p++, ptr++)
	{
		*p = (unsigned char)(*ptr);
		// int  h= *ptr;
		// cout<<h<<" ";
	}
	for (i = size.height - 1; i >= 0; i--)
	{
		fseek(fp, sizeof(IFH) + i*size.width, SEEK_SET);
		fwrite((BYTE*)(data + 1) + j*size.width, sizeof(BYTE), size.width, fp);
		j++;
	}

	return TRUE;

}
#endif
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值