Working With Private TIFF Tags

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(LFile * pLeadFile) 
{ 
   L_UINT uTags; 
   pLEADFILETAG pTags; 
   L_INT nRet = pLeadFile->ReadTags(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) 
   { 
      pLeadFile->FreeTags(uTags, pTags, 0, NULL); 
      return 0; 
   } 
   L_UINT uOffset = (L_UINT)pTags[u].uDataOffset; 
   // I don't need the tags anymore 
   pLeadFile->FreeTags(uTags, pTags, 0, NULL); 
   return uOffset; 
} 
L_INT CreateSubIFD(L_TCHAR *pszFileName) 
{ 
   LFile LeadFile; 
   SAVEFILEOPTION SaveFileOption; 
   L_INT nRet; 
   LeadFile.SetFileName(pszFileName); 
   // get the SubIFD offset, if it exists 
   L_UINT uSubIFD = GetSubIFDOffset(&LeadFile); 
   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 = LFileSettings::SetTag(MY_SUBIFDTAG, TAG_UNDEFINED, uIFDSize, pIFD); 
      if(nRet != SUCCESS) 
         return nRet; 
      // write the SubIFD in the file 
      nRet = LeadFile.WriteTag(NULL); 
      if(nRet != SUCCESS) 
         return nRet; 
      // clear MY_TAG from the internal tag list. I don't need to write it anymore 
      nRet = LFileSettings::SetTag(MY_SUBIFDTAG, 0, 0, NULL); 
      if(nRet != SUCCESS) 
         return nRet; 
      // get the SubIFD offset. It should be > 0 now 
      uSubIFD = GetSubIFDOffset(&LeadFile); 
      if(uSubIFD == 0) 
         return FAILURE; 
   } 
   LBaseFile::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; 
   LFileSettings::SetTag(PRIVATETAG_1, TAG_LONG, 1, &uValue); 
   LFileSettings::SetTag(PRIVATETAG_2, TAG_ASCII, 10, "My String"); 
   // write the private tags into the SubIFD 
   nRet = LeadFile.WriteTag(&SaveFileOption); 
   if(nRet != SUCCESS) 
      return nRet; 
   LOADFILEOPTION LoadFileOption; 
   LBaseFile::GetDefaultLoadFileOption(&LoadFileOption, sizeof(LoadFileOption)); 
   LoadFileOption.Flags |= ESO_USEIFD; 
   LoadFileOption.IFD = SaveFileOption.IFD; 
   // read private tag 1 from SubIFD 
   L_UINT16 uType; 
   L_UINT uCount; 
   nRet = LeadFile.ReadTag(PRIVATETAG_1, &uType, &uCount, NULL, &LoadFileOption); 
   if(nRet == 4 && uType == TAG_LONG && uCount == 1) 
   { 
      LBuffer * pLeadBuffer = new LBuffer(sizeof(L_UINT)); 
      nRet = LeadFile.ReadTag(PRIVATETAG_1, &uType, &uCount, pLeadBuffer, &LoadFileOption); 
      L_UINT * pBuffer = (L_UINT *)pLeadBuffer->Lock(); 
      assert(*pBuffer == 5); 
      pLeadBuffer->Unlock(); 
      delete pLeadBuffer; 
   } 
   // read private tag 2 from SubIFD 
   nRet = LeadFile.ReadTag(PRIVATETAG_2, &uType, &uCount, NULL, &LoadFileOption); 
   if(nRet > 0 && uType == TAG_ASCII && uCount >= 9) 
   { 
      LBuffer * pLeadBuffer = new LBuffer(sizeof(char) * 10); 
      nRet = LeadFile.ReadTag(PRIVATETAG_2, &uType, &uCount, pLeadBuffer, &LoadFileOption); 
      delete pLeadBuffer; 
   } 
   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 Version 20.0.2018.9.26
Products | Support | Contact Us | Copyright Notices
© 1991-2018 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Raster Imaging C++ Class Library Help