当初第一次接触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