TIFF files can contain private tags. LEADTOOLS can allow you to create, set and read private tags in TIFF files for your applications own use. In order to do this, you must create a SubIFD (Image File Directory) and then create your own private tags inside that IFD.
The following code writes a SubIFD and then creates two private tags into the file you specify.
Example:
#define MY_SUBIFDTAG 0xFFFE
L_UINT GetSubIFDOffset(L_TCHAR *pszFileName)
{
L_UINT uTags;
pLEADFILETAG pTags;
L_INT nRet = L_ReadFileTags(pszFileName, READFILEMETADATA_NOMEMORY, &uTags, &pTags, NULL, NULL, NULL);
if(nRet != SUCCESS)
return 0;
L_UINT u;
// find the new tag
for(u = 0; u < uTags; u++)
{
if(pTags[u].uTag == MY_SUBIFDTAG)
break;
}
if(u >= uTags)
{
L_FreeFileTags(uTags, pTags, 0, NULL);
return 0;
}
L_UINT uOffset = (L_UINT)pTags[u].uDataOffset;
// I do not need the tags anymore
L_FreeFileTags(uTags, pTags, 0, NULL);
return uOffset;
}
L_INT CreateSubIFD(L_TCHAR *pszFileName)
{
SAVEFILEOPTION SaveFileOption;
L_INT nRet;
// get the SubIFD offset, if it exists
L_UINT uSubIFD = GetSubIFDOffset(pszFileName);
if(uSubIFD == 0)
{
// the SubIFD does not exist, write it
// allocate an array of 6 bytes and set them all to 0
#define TAG_COUNT 2 // since we will be writing two tags
#define TAG_SIZE 12 // the number of bytes in one tag
#define PRIVATETAG_1 0x8003 // use private tags, because LEADTOOLS will reject attempts to write tags below 0x8000
#define PRIVATETAG_2 0x8004 // use private tags, because LEADTOOLS will reject attempts to write tags below 0x8000
L_UINT uIFDSize = 6 + TAG_COUNT * TAG_SIZE;
L_UINT16 *pIFD = (L_UINT16 *)malloc(uIFDSize);
if(!pIFD)
return ERROR_NO_MEMORY;
memset(pIFD, 0, uIFDSize);
// build the IFD: set the number of tags in the IFD
pIFD[0] = TAG_COUNT;
// and set dummy placeholders for each tag as follows: pIFD[1 + (TAG_SIZE / 2) * tag_index] = tag value
pIFD[1 + (TAG_SIZE / 2) * 0] = PRIVATETAG_1;
pIFD[1 + (TAG_SIZE / 2) * 1] = PRIVATETAG_2;
// write the tag as UNDEFINED
nRet = L_SetTag(MY_SUBIFDTAG, TAG_UNDEFINED, uIFDSize, pIFD);
if(nRet != SUCCESS)
return nRet;
// write the SubIFD in the file
nRet = L_WriteFileTag(pszFileName, NULL);
if(nRet != SUCCESS)
return nRet;
// clear MY_TAG from the internal tag list. I do not need to write it anymore
nRet = L_SetTag(MY_SUBIFDTAG, 0, 0, NULL);
if(nRet != SUCCESS)
return nRet;
// get the SubIFD offset. It should be > 0 now
uSubIFD = GetSubIFDOffset(pszFileName);
if(uSubIFD == 0)
return FAILURE;
}
L_GetDefaultSaveFileOption(&SaveFileOption, sizeof(SAVEFILEOPTION));
SaveFileOption.Flags |= ESO_USEIFD;
SaveFileOption.IFD = (L_UINT)uSubIFD;
// write the private tags
// set private tags 1 and 2
L_UINT uValue = 5;
L_SetTag(PRIVATETAG_1, TAG_LONG, 1, &uValue);
L_SetTag(PRIVATETAG_2, TAG_ASCII, 10, "My String");
// write the private tags into the SubIFD
nRet = L_WriteFileTag(pszFileName, &SaveFileOption);
if(nRet != SUCCESS)
return nRet;
LOADFILEOPTION LoadFileOption;
L_GetDefaultLoadFileOption(&LoadFileOption, sizeof(LoadFileOption));
LoadFileOption.Flags |= ESO_USEIFD;
LoadFileOption.IFD = SaveFileOption.IFD;
// read private tag 1 from SubIFD
L_UINT16 uType;
L_UINT uCount;
L_UINT uData;
nRet = L_ReadFileTag(pszFileName, PRIVATETAG_1, &uType, &uCount, NULL, &LoadFileOption);
if(nRet == 4 && uType == TAG_LONG && uCount == 1)
{
nRet = L_ReadFileTag(pszFileName, PRIVATETAG_1, &uType, &uCount, &uData, &LoadFileOption);
assert(uData == 5);
}
// read private tag 2 from SubIFD
char szBuffer[10];
nRet = L_ReadFileTag(pszFileName, PRIVATETAG_2, &uType, &uCount, NULL, &LoadFileOption);
if(nRet > 0 && uType == TAG_ASCII && uCount >= 9)
nRet = L_ReadFileTag(pszFileName, PRIVATETAG_2, &uType, &uCount, &szBuffer, &LoadFileOption);
return SUCCESS;
}
You can create private tags in TIFF or EXIF JPEG files. This code will fail if you use it with regular JPEG files
NOTE: Once you have created the SubIFD, you can add and read tags from it as many times as you need.
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document