向TIFF文件添加自定义标记
Adding custom tags to a TIFF file
我对libtiff很陌生,但我已经设法获得tiff文件保存和打开不太麻烦。
现在,我正在雄心勃勃地尝试在我的文件中添加自定义标记。我阅读文档(见这里)并编写一些测试代码,这些代码编译时不需要方法的第一次调用时发生访问冲突,从而在运行时失败具有自定义字段的TIFFSetField(通过调用TIFFSetField)标准字段就可以)。
我的测试代码如下:不到100行,只有一个外部依赖(除了libtiff)是我的代码打开测试图像从.pgm文件。有人能指出我哪里做错了吗?顺便说一下,我使用的是libtiff 4.0.3。
#include "stdafx.h"
#include "PGM.h" // Just for reading in the test image
#include "tiffio.h"
// There are a number of TIFF-related definitions we need to make in order to support the custom tags
// that we want to include in our files. The form of these definitions and subroutines comes straight
// out of the libtiff documentation, and the values of the custom tags themselves come from the
// range (65000-75535) defined in the TIFF specification as "reusable" and suitable for private use
// within organisations. See http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
#define N(a) (sizeof(a) / sizeof (a[0]))
#define TIFFTAG_INCIDENTPOWER 65000
#define TIFFTAG_REFLECTEDPOWER 65001
#define TIFFTAG_T1 65002
#define TIFFTAG_T2 65003
#define TIFFTAG_HUMIDITY 65004
#define TIFFTAG_EXPOSURE 65005
static const TIFFFieldInfo xtiffFieldInfo[] = {
{ TIFFTAG_INCIDENTPOWER, -1, -1, TIFF_LONG, FIELD_CUSTOM, 0, 1, const_cast<char*>("LaserIncidentPower") },
{ TIFFTAG_REFLECTEDPOWER, -1, -1, TIFF_LONG, FIELD_CUSTOM, 0, 1, const_cast<char*>("LaserReflectedPower") },
{ TIFFTAG_T1, -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1, const_cast<char*>("Temperature_1") },
{ TIFFTAG_T2, -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1, const_cast<char*>("Temperature_2") },
{ TIFFTAG_HUMIDITY, -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1, const_cast<char*>("Humidity") },
{ TIFFTAG_EXPOSURE, -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1, const_cast<char*>("ExposureTime(ms)") }
}; // The casts are necessary because the
// string literals are inherently const,
// but the definition of TIFFFieldInfo
// requires a non-const string pointer.
// The Intel and Microsoft compilers
// tolerate this, but gcc doesn't.
static void registerCustomTIFFTags(TIFF *tif)
{
/* Install the extended Tag field info */
TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
}
void saveAsTiff(int nx, int ny, unsigned short *image, const char* filename,
int Power1, int Power2, float T1, float T2, float Humidity, float Exposure)
{
// Create the TIFF directory object:
TIFF* tif = TIFFOpen(filename, "w");
// Set the tags: first the standard ones...
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, nx);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ny);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 6); // Takes maximum advantage of Intel ZLIB enhancements
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tif, TIFFTAG_ORIENTATION, static_cast<int>(ORIENTATION_TOPLEFT));
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, ny);
// Saving the whole image in a single block makes heavy
// demands on memory but should enable optimum compression
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
// ... and now our own custom ones; if we comment out this next block then everything
// works as it should and we successfully save the image:
registerCustomTIFFTags(tif);
TIFFSetField(tif, TIFFTAG_INCIDENTPOWER, Power1); // Access violation here
TIFFSetField(tif, TIFFTAG_REFLECTEDPOWER, Power2);
TIFFSetField(tif, TIFFTAG_T1, T1);
TIFFSetField(tif, TIFFTAG_T2, T2);
TIFFSetField(tif, TIFFTAG_HUMIDITY, Humidity);
TIFFSetField(tif, TIFFTAG_EXPOSURE, Exposure);
TIFFWriteEncodedStrip(tif, 0, static_cast<void *>(image), nx * ny * 2);
// The '* 2' is present because each pixel
// has 16 bits, hence two bytes
// Write the directory to a file, and close it:
TIFFWriteDirectory(tif);
TIFFClose(tif);
}
int _tmain(int argc, _TCHAR* argv[])
{
// Variables to hold the image
int nx, ny;
unsigned short *image = nullptr;
// Information we'd like to put into our custom tags:
int Power1 = 1000000;
int Power2 = 8;
float T1 = 23.5f;
float T2 = -18.7f;
float Humidity = 0.98f;
float Exposure = 0.001f;
// Read the test image in from a PGM file:
readFromPGM(&nx, &ny, &image, "TestImage.pgm");
// Save the image as a TIF file:
saveAsTiff(nx, ny, image, "TestImage.tif", Power1, Power2, T1, T2, Humidity, Exposure);
return 0;
}
在TIFF用户邮件列表中,一位名叫Paul Heckbert的好心的先生给了我一些指导,下面是最终对我有效的代码。有两个关键字:
(1)正确定义TIFFFieldInfo字段,其方式与文档中给出的示例不同。(2)使用"扩展器"模式封装对TIFFMergeFieldInfo的调用,但在打开文件之前执行此。如果我在打开文件之后才调用,那么当读取带有自定义标签的文件时,打开文件时将立即发出一些"警告,未知字段"消息。
代码如下:
#include "stdafx.h"
#include "PGM.h"
#include "tiffio.h"
// There are a number of TIFF-related definitions we need to make in order to support the custom tags
// that we want to include in our files. The form of these definitions and subroutines comes straight
// out of the libtiff documentation, and the values of the custom tags themselves come from the
// range (65000-75535) defined in the TIFF specification as "reusable" and suitable for private use
// within organisations. See http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
#define N(a) (sizeof(a) / sizeof (a[0]))
#define TIFFTAG_INCIDENTPOWER 65000
#define TIFFTAG_REFLECTEDPOWER 65001
#define TIFFTAG_T1 65002
#define TIFFTAG_T2 65003
#define TIFFTAG_HUMIDITY 65004
#define TIFFTAG_EXPOSURE 65005
static const TIFFFieldInfo xtiffFieldInfo[] = {
{ TIFFTAG_INCIDENTPOWER, 1, 1, TIFF_LONG, FIELD_CUSTOM, 0, 0, const_cast<char*>("LaserIncidentPower") },
{ TIFFTAG_REFLECTEDPOWER, 1, 1, TIFF_LONG, FIELD_CUSTOM, 0, 0, const_cast<char*>("LaserReflectedPower") },
{ TIFFTAG_T1, 1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Temperature_1") },
{ TIFFTAG_T2, 1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Temperature_2") },
{ TIFFTAG_HUMIDITY, 1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Humidity") },
{ TIFFTAG_EXPOSURE, 1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("ExposureTime(ms)") }
}; // The casts are necessary because the
// string literals are inherently const,
// but the definition of TIFFFieldInfo
// requires a non-const string pointer.
// The Intel and Microsoft compilers
// tolerate this, but gcc doesn't.
static TIFFExtendProc parent_extender = NULL; // In case we want a chain of extensions
static void registerCustomTIFFTags(TIFF *tif)
{
/* Install the extended Tag field info */
int error = TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
if (parent_extender)
(*parent_extender)(tif);
}
static void augment_libtiff_with_custom_tags() {
static bool first_time = true;
if (!first_time) return;
first_time = false;
parent_extender = TIFFSetTagExtender(registerCustomTIFFTags);
}
void saveAsTiff(int nx, int ny, unsigned short *image, const char* filename,
int Power1, int Power2, float T1, float T2, float Humidity, float Exposure)
{
// Create the TIFF directory object:
augment_libtiff_with_custom_tags();
TIFF* tif = TIFFOpen(filename, "w");
// Set the tags: first the standard ones...
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, nx);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ny);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 6); // Takes maximum advantage of Intel ZLIB enhancements
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tif, TIFFTAG_ORIENTATION, static_cast<int>(ORIENTATION_TOPLEFT));
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, ny);
// Saving the whole image in a single block makes heavy
// demands on memory but should enable optimum compression
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
// ... and now our own custom ones:
TIFFSetField(tif, TIFFTAG_INCIDENTPOWER, Power1);
TIFFSetField(tif, TIFFTAG_REFLECTEDPOWER, Power2);
TIFFSetField(tif, TIFFTAG_T1, T1);
TIFFSetField(tif, TIFFTAG_T2, T2);
TIFFSetField(tif, TIFFTAG_HUMIDITY, Humidity);
TIFFSetField(tif, TIFFTAG_EXPOSURE, Exposure);
TIFFWriteEncodedStrip(tif, 0, static_cast<void *>(image), nx * ny * 2);
// The '* 2' is present because each pixel
// has 16 bits, hence two bytes
// Write the directory to a file, and close it:
TIFFWriteDirectory(tif);
TIFFClose(tif);
}
void readFromTiff(int *nx, int *ny, unsigned short **image, const char* filename,
int *Power1, int *Power2, float *T1, float *T2, float *Humidity, float *Exposure)
{
// Create the TIFF directory object:
augment_libtiff_with_custom_tags();
TIFF* tif = TIFFOpen(filename, "r");
if (NULL == tif)
{
*nx = -1;
*ny = -1;
return;
}
// Read in the image size and metadata:
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, nx);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ny);
TIFFGetField(tif, TIFFTAG_INCIDENTPOWER, Power1);
TIFFGetField(tif, TIFFTAG_REFLECTEDPOWER, Power2);
TIFFGetField(tif, TIFFTAG_T1, T1);
TIFFGetField(tif, TIFFTAG_T2, T2);
TIFFGetField(tif, TIFFTAG_HUMIDITY, Humidity);
TIFFGetField(tif, TIFFTAG_EXPOSURE, Exposure);
// Dimension the buffer, and read in the image data itself:
*image = new unsigned short[(*nx) * (*ny)];
TIFFReadEncodedStrip(tif, static_cast<tstrip_t>(0), static_cast<void *>(*image), static_cast<tsize_t>(-1));
TIFFClose(tif);
}
int _tmain(int argc, _TCHAR* argv[])
{
// Variables to hold the image
int nx, ny;
unsigned short *image = nullptr;
// Information we'd like to put into our custom tags:
int Power1 = 1000000;
int Power2 = 8;
float T1 = 23.5f;
float T2 = -18.7f;
float Humidity = 0.98f;
float Exposure = 0.001f;
// Read the test image in from a PGM file:
readFromPGM(&nx, &ny, &image, "TestImage.pgm");
// Save the image as a TIF file:
saveAsTiff(nx, ny, image, "TestImage.tif", Power1, Power2, T1, T2, Humidity, Exposure);
// Prepare to read back in: first clear the various fields
Power1 = 0;
Power2 = 0;
T1 = 0.0f;
T2 = 0.0f;
Humidity = 0.0f;
Exposure = 0.0f;
nx = 0;
ny = 0;
delete [] image;
readFromTiff(&nx, &ny, &image, "TestImage.tif", &Power1, &Power2, &T1, &T2, &Humidity, &Exposure);
printf("Image size = %d, %drn", ny, ny);
printf("Power1 = %drn", Power1);
printf("Power2 = %drn", Power2);
printf("T1 = %6.3frn", T1);
printf("T2 = %6.3frn", T2);
printf("Humidity = %6.3frn", Humidity);
printf("Exposure = %6.3frn", Exposure);
return 0;
}
相关文章:
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- TraciMobility::getExternalId 将自定义模块添加到示例中时出错Veins_Inet (Omne
- 如何在自定义对象的<<运算符中添加自定义前缀
- 如何在Qt C++中向自定义控件添加属性?
- 将自定义样式添加到 QTableview 中添加的按钮
- C++ 添加编译器警告,以错误使用自定义打印/日志功能
- 如何添加自定义关键字以 clang 格式被视为"class"?
- 向 std::map 添加对象和自定义比较<>
- 如何将自定义角色添加到 QFileSystemModel
- 为C /CLI中的所有请求添加自定义的标头到WebBrowser控件
- 将自定义代码添加到Swig包装器中
- 如何使用 word 对象模型中的C++接口在 word 中添加自定义 XML 艺术
- 如何将比较器添加到自定义排序函数
- 如何在Boost Graph库中的Grid_graph的边缘添加自定义属性
- 当我添加自定义比较器时,无法插入新元素以设置
- 我们如何添加Coverity工具的自定义规则
- Visual Studio Code 中的自定义库添加
- 如何在Tensorflow Lite中添加自定义运算符
- MFC 自定义 - 添加新工具栏