图像处理, 首先,需要在网上下载一个查看文件十六进制的软件(FlexHEX),根据软件打开对应的图文件,如下图所示为打开tiff深度图的结果。针对本文章tiff图为波纹板的深度图,它的图文件结构首先是文件头、图像数据、DE个数(占4字节),每个DE的类型(每个DE是12个字节)。然后是其他信息,可以不用读取,主要是图像数据和DE目录里面的图像的宽和图像的高。如下图。需要根据软件查看的图文件数据对着TIFF文件格式详解对照着码代码。TIFF文件格式详解在我另一个文章中。
代码区:只针对于我的tiff图像实现读写(波纹板深度图)因为tiff图像类型太多了,文件信息比bmp位图更灵活。(bmp是固定的位图文件格式)。
tiffFile.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <Windows.h>
#include <stdio.h>
#include "tiffFile.h"
using namespace std;
/***********定义文件头结构体************/
typedef struct
{
uint16_t endian; // (2个字节)字节顺序标志位,值为II或者MM。II表示小字节在前, 又称为littleendian。MM表示大字节在前,又成为bigendian。
uint16_t magic; //(2个字节)TIFF的标志位,一般都是42
uint32_t ifdOffset; //(4个字节)第一个IFD的偏移量
}IFH; //文件头变量
uint16_t DE_count; //DE的个数
/***************定义DE成员的结构体***********************/
typedef struct
{
uint16_t tag; // (2bit)TAG的唯一标识,每一种tagID代表了它所对应的图像信息,例如长,宽等。
uint16_t type; // (2bit)数据类型,integer类型,long类型,还有RATIONAL类型属于分数类型两个long组成。
uint32_t size; // (4bit)数量,类型和数量可以确定存储此TAG的数据需要占据的字节数
uint32_t valOffset; //(4bit)代表数值,对于tag对应图像信息的数值
}DE;
/***************定义IFD目录结构体***********************/
typedef struct
{
DE ImageWidth; //图像的宽
DE ImageHeight; //图像的高
DE BitsPerSample; //位深
DE Compression; //判断是否压缩
DE PhotometricInterpretation; //判断是什么图像(灰度?RGB?)
DE Make; //生产商的描述 x0F01
DE StripOffsets; //每个Strip的偏移量
DE Orientation; //方向
DE SamplesPerPixel; //每个像素通道个数
DE RowsPerStrip; //行
DE StripByteCounts; //长度
DE XResolution; //水平分辨率
DE YResolution; //垂直分辨率
DE PlanarConfiguration; //计划配置
DE ResolutionUnit; //解析度
DE Software; //软件啥的
DE DateTime; //图像创键日期
DE ExtraSamples; //其他
}IFD;
IFH filehead; //定义文件头
IFD infohead; //文件信息头
uint16_t othersize[4100]; //之后的数就没用了,找个空间写入
bool readtiff(char* fileName, int& tiffsize, int& width, int& height, float*& tiffImg)
{
FILE* fp = fopen(fileName, "rb"); //以二进制读方式打开
if (NULL == fp) {
cout << "File is opened failure!" << endl;
return FALSE;
}
fread(&filehead, sizeof(IFH), 1, fp);
tiffsize = (filehead.ifdOffset - sizeof(filehead));
tiffImg = new float[tiffsize];
fread(tiffImg, 1, tiffsize, fp);
//fseek(fp, filehead.ifdOffset,0);
//cout << "第一个IFD偏移量" << filehead.ifdOffset << endl;
fread(&DE_count, sizeof(DE_count), 1, fp);
fread(&infohead, sizeof(IFD), 1, fp);
width = infohead.ImageWidth.valOffset;
height = infohead.ImageHeight.valOffset;
fread(&othersize, sizeof(othersize), 1, fp);
fclose(fp);//关闭文件
return 1;
}
bool writetiff(char* fileName, int tiffsize, int width, int height, float* tiffimf)
{
if (!tiffimf)
return false;
//以二进制写的方式打开指定图像文件
FILE* fp = fopen(fileName, "w+b");
if (fp == 0) return false;
fwrite(&filehead, sizeof(IFH), 1, fp);//向文件中写入位图文件头
fwrite(tiffimf, 1, tiffsize, fp);
fwrite(&DE_count, sizeof(DE_count), 1, fp);
fwrite(&infohead, sizeof(IFD), 1, fp);//向文件中写入位图信息头
fwrite(&othersize, sizeof(othersize), 1, fp);
return 1;
}
tiffFile.h
#pragma once
#include <iostream>
using namespace std;
bool readtiff(char* fileName, int& tiffsize, int& width, int& height, float*& tiffImg);
bool writetiff(char* fileName, int tiffsize, int width, int height, float* tiffimf);
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <cstdint>
#include <cstring>
#include <math.h>
#include <fstream>
#include <algorithm>
#include <stdio.h>
#include <Windows.h>
#include "tiffFile.h"
#include "data_collation.h"
int main()
{
int width, tiffsize, height;
float* tiffImg; //定义读入的图像数据
clock_t startTime, endTime;
startTime = clock(); //计时开始
char readPath[]= "D:\\机器视觉学习工程\\波纹板深度检测\\111.tif";
readtiff(readPath,tiffsize, width, height, tiffImg);
cout << "宽" << width << endl;
cout << "高" << height << endl;
float* tiffout = new float[tiffsize];
memset(tiffout, 0, tiffsize);
data_collation(tiffImg, tiffout, height, width); //图像处理函数单纯读写需要去掉
char writePath[] = "D:\\机器视觉学习工程\\波纹板深度检测\\111write.tif";
writetiff(writePath,tiffsize,width, height, tiffout);
cout << width << endl;
ShellExecuteA(nullptr, "open", writePath, "", "", SW_SHOW); //打开写入的位图结果
endTime = clock(); //计时结束
cout << "The run time is: " << (float)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
delete[] tiffImg;
delete[] tiffout;
}
完事!