Implementing TIFF Comments and Tags

Handling Tags and Comments

Task: Determine if a certain file format supports metadata

Task: Read a certain tag or comment by ID from a TIFF or EXIF file

Task: Write a certain tag or comment to a TIFF or EXIF file

Task: Read all tags and comments found in a TIFF or EXIF file without loading the image

Task: Update comments or tags in a TIFF or EXIF file without loading the image

Task: Delete a tag by ID from a file without loading it

Task: Read or write the file stamp

Initially, only TIFF files supported TIFF tags. But the TIFF tags are so flexible and well documented that other formats added mechanisms for including TIFF tags:

In other words, TIFF tags are supported in file formats other than TIFF. You can use the L_TagsSupported function to determine whether a certain file format supports tags.

For these formats, the comments are simply TIFF tags saved with certain characteristics (fixed tag type, count and number of elements). To specify a comment to be saved, use the L_SetComment and L_GetComment functions to build the list of the comments you wish to save, then call one of the save functions. The output file will contains all these comments in addition to the image data.

To read a comment from an existing file, you can use L_ReadFileComment or L_ReadFileCommentMemory. To read a comment from a file at a specified location, use the L_ReadFileCommentOffset function.

To read all comments from an existing file, use L_ReadFileComments. L_ReadFileComments allocates a buffer large enough all the comments. The user is responsible for freing this buffer by calling L_FreeFileComments.

To write comments to an existing file, use L_WriteFileComment or L_WriteFileCommentExt (TIFF only). To check whether a file format supports comment fields, use L_CommentsSupported. You can use the L_DeleteComment function to delete a comment field from a file (TIFF only).

Note

If an error occurred in reading all file comments using the L_ReadFileComments function, then no comments will be returned, and the user is responsible to find the valid metadata in the file.

For a list of possible comments, refer to TIFF File Comments. The files that support Exif metadata can save the exif comments in addition to the TIFF comments. See Exif File comments for the full list.

If the comments do not meet your needs, you can define your own tag for saving additional non-raster data in a TIFF file. For example, you may want to define a tag to save annotations.

The TIFF 6.0 Specification sets aside a range of private tags that developers can define. To avoid conflicts with files created by other developers, you can register your tag by contacting Adobe Developer Relations. (The E-Mail address posted on The Unofficial TIFF Home Page is gapdevsup@adobe.com.)

To define a tag and to specify the data to save in the tag, you can use the L_SetTag and L_GetTag functions. To load the tagged data from a file, you can use L_ReadFileTag or L_ReadFileTagMemory .To read all tags from an existing file, use L_ReadFileTags. When the data allocated by calling the L_ReadFileTags function are no longer needed it must be freed by calling L_FreeFileTags. To write tags to an existing file, or to change existing tags in a file, use L_WriteFileTag (TIFF only). To check whether a file format supports tags, use L_TagsSupported.

Note

To write tags to an existing TIFF file, use L_WriteFileTag or L_WriteFileTagMemory instead of using L_SetTag followed by L_SaveFile or L_SaveFileMemory.

L_EnumFileTags2 enumerate all tags in a TIFF, Exif, HEIC/HEIF, PNG or WebP file. For each tag enumerated, the ENUMTAG2SCALLBACK function is called. Through this callback function, you can obtain information about, or otherwise process, each tag that is enumerated. To delete a specified tag from the file, call L_DeleteTag.

LEADTOOLS uses an additional private tag to store extra information in the TIFF file (region, LUT for 12/16-bit grayscale bitmaps, etc). This is done automatically, without any action required on your part.

Handling Tags and Comments

LEADTOOLS has extensive support to query/load/save metadata, such as, file tags, comments fields, and Geo keys (additional tags found in GeoTIFF files).

The following section lists common tasks performed when working with image markers as well as the LEADTOOLS functions to use.

Task: Determine if a certain file format supports metadata

LEADTOOLS uses defined constants to denote an image file format. You can obtain the format of a file by using the Format member of the FILEINFO structure after calling L_FileInfo. When you use any of the L_LoadXXX functions, the image format of the original source image will be stored in the OriginalFormat member of the BITMAPHANDLE.

To determine if a particular file format supports the type of metadata required, use one of the following:

Function Support
L_CommentsSupported Determines if the format supports comment fields. TIFF, EXIF, DICOM and ICA are some of the common file formats that support comment fields.
L_GeoKeysSupported Determines if the format supports Geo key tags. GeoTIFF is the main file format that supports Geo key tags.
L_MarkersSupported Determines if the format supports markers. JPEG and and EXIF JPEG are main File formats that support markers.
L_TagsSupported Determines if the format supports tags. TIFF and EXIF are some of the common File formats that support tags.

Many of the LEADTOOLS metadata query, read and write functions will return an error if the file format does not support metadata. For example, trying to call L_ReadFileTag on a BMP file will almost certainly return ERROR_FEATURE_NOT_SUPPORTED. To eliminate the need to check and process these error values and speed up your code, use any of the functions above and only call the corresponding query, read or write metadata function if the format supports it.

For example, the following code will read the Description comment field from a disk image file. If the file supports comments, the value will be read and parsed, otherwise, it will display a message:

L_VOID ReadDescriptionComment (L_TCHAR * pszFileName) 
{ 
   // Get the file format 
   FILEINFO FileInfo; 
   memset(&FileInfo, 0, sizeof(FILEINFO)); 
   FileInfo.uStructSize = sizeof(FILEINFO); 
   L_INT nRet = L_FileInfo(pszFileName, &FileInfo, sizeof(FILEINFO), 0, NULL); 
   if(nRet == SUCCESS) 
   { 
      // Check if this file format supports comment fields 
      if(L_CommentsSupported(FileInfo.Format)) 
      { 
         // Yes, read it 
         L_UCHAR buf[800]="\0"; 
         nRet = L_ReadFileComment(pszFileName, CMNT_SZDESC, buf, 800, NULL); 
         OutputDebugStringA((LPCSTR)buf); 
         OutputDebugStringA("\n"); 
      } 
      else 
      { 
         OutputDebugStringA("Description comment not supported\n"); 
      } 
   } 
} 

Similarly, you can use L_TagsSupported and L_GeoKeysSupported to determine if the format supports tags and Geo TIFF keys respectively.

Task: Read a certain tag or comment by ID from a TIFF or EXIF file

According to the EXIF format specification, the tag with ID 0x8298 (h8298) is the EXIF tag denoting the copyright string.

The following code will print the copyright tag value found in an EXIF file:

L_VOID ReadTagById(L_TCHAR * pszFileName) 
{ 
   // L_ReadFileTag will return an error if pszFileName does not support tags. 
   // If required, use L_TagsSupported first. 
   const L_INT ExifCopyrightTagId = 0x8298; 
   L_UCHAR buf[800]="\0"; 
   L_UINT16 uType=0; 
   L_UINT uCount=0; 
   L_INT nRet = L_ReadFileTag(pszFileName, ExifCopyrightTagId, &uType, &uCount, buf, NULL); 
   if(nRet>0) 
   { 
      // Tag is found, show the value 
      OutputDebugStringA((LPCSTR)buf); 
      OutputDebugStringA("\n"); 
   } 
} 

The following code will print the description comment value found in an EXIF file:

L_VOID ReadCommentById(L_TCHAR * pszFileName) 
{ 
   // L_ReadFileComment will return an error if pszFileName does not support comments. 
   // If required, use L_CommentsSupported first. 
   L_UCHAR buf[800]="\0"; 
   L_INT nRet = L_ReadFileComment(pszFileName, CMNT_SZDESC, buf, 800, NULL); 
   if(nRet>0) 
   { 
      // comment is found, show the value 
      OutputDebugStringA((LPCSTR)buf); 
      OutputDebugStringA("\n"); 
   } 
} 

Similarly, you can use L_ReadFileGeoKey to read an individual TIFF Geo Key by ID from a file.

Task: Write a certain tag or comment to a TIFF or EXIF file

According to the EXIF format specification, the tag with ID 0x8298 (h8298) is the EXIF tag denoting the copyright string.

The following code will update the copyright tag text in an EXIF file to "Copyright (c) My Company":

L_VOID WriteTagById(L_TCHAR * pszFileName) 
{ 
   const L_INT ExifCopyrightTagId = 0x8298; 
   // Create the tag 
   L_UCHAR buf[80]="Copyright (c) My Company"; 
   L_INT nRet = L_SetTag(ExifCopyrightTagId, TAG_ASCII, strlen((const char*)buf)+1, (L_UCHAR*)buf); 
   // Write the tag to the file 
   nRet = L_WriteFileTag(pszFileName, NULL); 
} 

The following code will update the description comment field in an EXIF file with "My description":

L_VOID WriteCommentById(L_TCHAR * pszFileName) 
{ 
   // Create the comment 
   L_UCHAR buf[]="My description\0"; 
   L_INT nRet = L_SetComment(CMNT_SZDESC, (L_UCHAR*)buf, strlen((const char*)buf)+1); 
   // Write it to the file 
   nRet = L_WriteFileComment(pszFileName, NULL); 
} 

Similarly, you can use L_WriteFileGeoKey to write an individual TIFF Geo Key by ID to a file.

Task: Read all tags and comments found in a TIFF or EXIF file without loading the image

Use the following code to read all the tags found in a TIFF or EXIF file:

L_VOID ReadAllTagsWithoutLoadingImage(L_TCHAR * pszFileName) 
{ 
   // L_ReadFileTags will return an error if pszFileName does not support tags. 
   // If required, use L_TagsSupported first. 
   L_UINT uTagCount=0; 
   pLEADFILETAG pTags=NULL; 
   L_UCHAR *pData=NULL; 
   L_SIZE_T uDataSize=0; 
   L_INT nRet = L_ReadFileTags(pszFileName, 0, &uTagCount, &pTags, &uDataSize, &pData, NULL); 
   if(nRet == SUCCESS) 
   { 
      for(L_UINT i=0; i<uTagCount; i++) 
      { 
         L_TCHAR buf[80]; 
         wsprintf(buf, L_TEXT("Tag found, id=%ld\n"), pTags[i].uTag); 
         OutputDebugString(buf); 
      } 
      L_FreeFileTags(uTagCount, pTags, uDataSize, pData); 
   } 
} 

The code above reads all the tags as well as their data. To enumerate all the tags without reading the data, you can use L_EnumFileTags. Here is an example:

L_INT EXT_CALLBACK EnumFileTagCallback(L_UINT16  uTag, 
L_UINT16  uType, 
L_UINT32  uCount, 
L_VOID  * pUserData) 
{ 
   UNREFERENCED_PARAMETER(uType); 
   UNREFERENCED_PARAMETER(uCount); 
   UNREFERENCED_PARAMETER(pUserData); 
   L_TCHAR buf[80]; 
   wsprintf(buf, L_TEXT("Tag found, id=%ld\n"), uTag); 
   OutputDebugString(buf); 
   return SUCCESS; 
} 
L_VOID ReadAllTagsWithoutData(L_TCHAR * pszFileName) 
{ 
   // L_EnumTags will return an error if pszFileName does not support tags. 
   // If required, use L_TagsSupported first. 
   L_INT nRet = L_EnumFileTags(pszFileName, 0, EnumFileTagCallback, NULL, NULL); 
} 

Use the following code to read all the comment fields found in a TIFF or EXIF file:

L_VOID ReadAllCommentsWithoutLoadingImage(L_TCHAR * pszFileName) 
{ 
   // L_ReadFileComments will return an error if pszFileName does not support comments. 
   // If required, use RasterCodecs.CommentsSupported first. 
   L_UINT uCommentCount=0; 
   pLEADFILECOMMENT pComments=NULL; 
   L_UCHAR *pData=NULL; 
   L_SIZE_T uDataSize=0; 
   L_INT nRet = L_ReadFileComments(pszFileName, 0, &uCommentCount, &pComments, &uDataSize, &pData, NULL); 
   if(nRet == SUCCESS) 
   { 
      for(L_UINT i=0; i<uCommentCount; i++) 
      { 
         L_TCHAR buf[80]; 
         wsprintf(buf, L_TEXT("Comment found, type=%ld\n"), pComments[i].uType); 
         OutputDebugString(buf); 
      } 
      L_FreeFileComments(uCommentCount, pComments, uDataSize, pData); 
   } 
} 

Similarly, you can use L_ReadFileGeoKeys and L_EnumFileGeoKeys to read all TIFF Geo Keys by ID from a file.

Task: Update comments or tags in a TIFF or EXIF file without loading the image

According to the EXIF format specification, the tag with ID 0x8298 (&h8298) is the EXIF tag denoting the copyright string and tag with ID 0x010E(&h010E) is the EXIF tag denoting the image title. The following code will update these tags in an EXIF file on disk with "Copyright (c) My Company" and "My Image" respectively.

L_VOID WriteTagsWithoutLoadingImage(L_TCHAR * pszFileName) 
{ 
   // L_WriteFileTag will return an error if pszFileName does not support tags. 
   // If required, use L_TagsSupported first. 
   // Create the tags 
   const L_INT ExifCopyrightTagId = 0x8298; 
   const L_INT ExifImageTitleTagId = 0x010E; 
   L_UCHAR buf1[80]="Copyright (c) My Company"; 
   L_INT nRet = L_SetTag(ExifCopyrightTagId, TAG_ASCII, strlen((const char*)buf1)+1, (L_UCHAR*)buf1); 
   L_UCHAR buf2[80]="My Image"; 
   nRet = L_SetTag(ExifImageTitleTagId, TAG_ASCII, strlen((const char*)buf2)+1, (L_UCHAR*)buf2); 
   // Write them to the file 
   nRet = L_WriteFileTag(pszFileName, NULL); 
} 

Use the following code to update the copyright and description comment fields in an EXIF file without loading the image:

L_VOID WriteCommentsWithoutLoadingImage(L_TCHAR * pszFileName) 
{ 
   // L_WriteFileComment will return an error if pszFileName does not support comments. 
   // If required, use L_CommentsSupported first. 
   // Create the comments 
   L_UCHAR buf1[]="Copyright (c) My Company\0"; 
   L_INT nRet = L_SetComment(CMNT_SZCOPYRIGHT, (L_UCHAR*)buf1, strlen((const char*)buf1)+1); 
   L_UCHAR buf2[]="My description\0"; 
   nRet = L_SetComment(CMNT_SZDESC, (L_UCHAR*)buf2, strlen((const char*)buf2)+1); 
   // Write it to the file 
   nRet = L_WriteFileComment(pszFileName, NULL); 
} 

Similarly, you can use L_WriteFileGeoKey to update the TIFF Geo Keys by ID in a file.

Task: Delete a tag by ID from a file without loading it

The fastest way to delete a tag with a known ID from a file is by using L_DeleteTag. This function has the advantage of deleting the tag directly from the disk file without requiring loading or parsing the image data.

Task: Read or write the file stamp

The stamp is a special metadata used by only EXIF, CMP, JFIF and FlashPix formats to store a thumbnail of the image. To read or write the stamp, use L_ReadFileStamp and L_WriteFileStamp.

Related Topics

Help Version 22.0.2023.7.11
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Raster Imaging C API Help

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.