L_ReadFileTags

Summary

Gets all the tags stored in a file.

Syntax

#include "l_bitmap.h"

L_LTFIL_API L_INT L_ReadFileTags(pszFile, uFlags, puTagCount, ppTags, puDataSize, ppData, pLoadOptions)

Parameters

L_TCHAR * pszFile

Character string that contains the input file name.

L_UINT uFlags

Flag that determines whether to read the tag overall data. You can combine values when appropriate by using a bitwise OR ( | ):

Flag Meaning
READFILEMETADATA_NOMEMORY [0x01] Do not read the tag overall data. If this flag is set, then puDataSize and ppData will not be used and the function will not read the tag overall data.
If this flag is set, the uDataOffset member of the LEADFILETAG structure will be filled with the lData value for the tag. This can be used to get the offset into the file where the data is stored for tags with more than 4 bytes of data.

L_UINT * puTagCount

Address of the variable to be updated with the number of tags found in the file.

pLEADFILETAG * ppTags

Pointer to an array of pLEADEADFILETAG structures. Each element of the array contains data for one tag found in the file. The number of elements in ppTags is puTagCount. When this array is no longer needed pass it to the L_FreeFileTags function to free the allocated memory.

L_SIZE_T * puDataSize

Address of the variable to be updated with the size in bytes of the overall tags data.

L_UCHAR ** ppData

Address of the variable to be updated with a pointer to the overall tags data. The size of this pointer in bytes is puDataSize. Each LEADEADFILETAG item found contains an offset to where the data for this item is stored in ppData.

pLOADFILEOPTION pLoadOptions

Pointer to optional extended load options. Pass NULL to use the default load options

Returns

Value Meaning
SUCCESS The function was successful
< 1 An error occurred. Refer to Return Codes.

Comments

You must free the data allocated with this function using the L_FreeFileTags function.

For general information about TIFF tags, refer to Implementing TIFF Comments and Tags.

This function is very useful for reading tags embedded inside SubIFDs. For instance, the MakerNote Exif tag sometimes contains an offset to a SubIFD. You can get the SubIFD offset using L_ReadFileTags and passing the READFILEMETADATA_NOMEMORY tag. You can then use the offset obtained to read data from the IFD by setting the offset value to LOADFILEOPTION.IFD. Note that sometimes this is not possible using L_ReadFileTag if the MakerNote data tag has a count greater than 4. Look below for an example.

Required DLLs and Libraries

Platforms

Win32, x64, Linux.

See Also

Functions

Topics

Example

These example deal with file tags, comments and geo keys.

//Example 1: This example will read all the tags, comments and geo keys stored in a disk file. 
L_INT ReadFileTagsExample1(L_VOID) 
{ 
   FILEINFO fi; 
   L_INT nRet; 
   L_UINT i, uTagCount=0, uCommentCount=0, uGeoKeyCount=0; 
   pLEADFILETAG pTags = NULL, pCurrentTag, pGeoKeys = NULL, pCurrentGeoKey; 
   L_SIZE_T uTagDataSize = 0, uCommentDataSize = 0, uGeoKeyDataSize = 0; 
   L_UCHAR *pTagData = NULL, *pCommentData = NULL, *pGeoKeyData = NULL; 
   L_CHAR *pszAscii = NULL; 
   pLEADFILECOMMENT pComments = NULL, pCurrentComment; 
   L_TCHAR szImageFileName[L_MAXPATH] ; 
   lstrcpy(szImageFileName,MAKE_IMAGE_PATH("ImageProcessingDemo\\image1.jpg")); 
 
 
   // Get the format of the file 
   ZeroMemory(&fi, sizeof(FILEINFO)); 
   fi.uStructSize = sizeof(FILEINFO); 
   nRet = L_FileInfo(szImageFileName, &fi, sizeof(FILEINFO), 0, NULL); 
   if(nRet != SUCCESS) 
      return nRet; 
 
   // Read all the tags in the file 
   if(nRet == SUCCESS && L_TagsSupported(fi.Format)) 
   { 
      // Yes, read all the tags from the file 
      nRet = L_ReadFileTags( 
         szImageFileName, 
         0, 
         &uTagCount, 
         &pTags, 
         &uTagDataSize, 
         &pTagData, 
         NULL); 
   } 
 
   // Read all the comments in the file 
   if(nRet == SUCCESS && L_CommentsSupported(fi.Format)) 
   { 
      // Yes, read all the comments from the file 
      nRet = L_ReadFileComments( 
         szImageFileName, 
         0, 
         &uCommentCount, 
         &pComments, 
         &uCommentDataSize, 
         &pCommentData, 
         NULL); 
   } 
 
   // Read all the geo keys in the file 
   if(nRet == SUCCESS && L_GeoKeysSupported(fi.Format)) 
   { 
      // Yes, read all the geo keys from the file 
      nRet = L_ReadFileGeoKeys( 
         szImageFileName, 
         0, 
         &uGeoKeyCount, 
         &pGeoKeys, 
         &uGeoKeyDataSize, 
         &pGeoKeyData, 
         NULL); 
   } 
 
   if(nRet == SUCCESS) 
   { 
      if(uTagCount > 0) 
      { 
         // Show the tags 
         wprintf(L"Tags\n"); 
         for(i = 0; i < uTagCount; i++) 
         { 
            pCurrentTag = &pTags[i]; 
 
            // If this tag is of type ASCII, get its data 
            if(pCurrentTag->uType == TAG_ASCII) 
            { 
               pszAscii = (L_CHAR*)malloc(pCurrentTag->uDataSize + 1); 
               ZeroMemory(pszAscii, pCurrentTag->uDataSize + 1); 
               CopyMemory(pszAscii, pTagData + pCurrentTag->uDataOffset, pCurrentTag->uDataSize); 
            } 
            else 
            { 
               pszAscii = NULL; 
            } 
 
            printf("Id: 0x%X, data length: %u, data: %s\n", pCurrentTag->uTag, pCurrentTag->uDataSize, pszAscii != NULL ? pszAscii : "Binary data"); 
         } 
 
         L_FreeFileTags(uTagCount, pTags, uTagDataSize, pTagData); 
      } 
 
      if(uCommentCount > 0) 
      { 
         // Show the Comments 
         wprintf(L"Comments\n"); 
         for(i = 0; i < uCommentCount; i++) 
         { 
            pCurrentComment = &pComments[i]; 
 
            // If this comment is of type ASCII, get its data 
            printf("Id: 0x%X, data length: %u\n", pCurrentComment->uType, pCurrentComment->uDataSize); 
         } 
 
         L_FreeFileComments(uCommentCount, pComments, uCommentDataSize, pCommentData); 
      } 
 
      if(uGeoKeyCount > 0) 
      { 
         // Show the geo keys 
         wprintf(L"GeoKeys\n"); 
         for(i = 0; i < uGeoKeyCount; i++) 
         { 
            pCurrentGeoKey = &pGeoKeys[i]; 
 
            // If this geo key is of type ASCII, get its data 
            if(pCurrentGeoKey->uType == TAG_ASCII) 
            { 
               pszAscii = (L_CHAR*)malloc(pCurrentGeoKey->uDataSize + 1); 
               ZeroMemory(pszAscii, pCurrentGeoKey->uDataSize + 1); 
               CopyMemory(pszAscii, pGeoKeyData + pCurrentGeoKey->uDataOffset, pCurrentGeoKey->uDataSize); 
            } 
            else 
            { 
               pszAscii = NULL; 
            } 
 
            printf("Id: 0x%X, data length: %u, data: %s\n", pCurrentGeoKey->uTag, pCurrentGeoKey->uDataSize, pszAscii != NULL ? pszAscii : "Binary data"); 
         } 
 
         L_FreeFileTags(uGeoKeyCount, pGeoKeys, uGeoKeyDataSize, pGeoKeyData); 
      } 
   } 
   return SUCCESS; 
} 
 
//Example 2: This example will read a custom tag contained inside a Canon MakerNote tag. The Canon MakerNote tag contains an offset into a SubIFD containing Canon-specific tags. You can do a web search for "canon makernote specification" to get the details on the Canon Makernote tag. 
L_INT ReadCanonSerialNumber2(HWND hWnd, TCHAR *pszFile) 
{ 
   // read the MakerNote tag 
   // Step1: Find the ExifIFD tag offset 
   L_UINT16 uType = TAG_LONG; 
   L_UINT   uCount = 1; 
   L_INT    nExifIFDOffset; 
   L_INT    nTagSize = L_ReadFileTag(pszFile, 0x8769, &uType, &uCount, &nExifIFDOffset, NULL); 
 
   if(nTagSize != 4) 
      return -5000; // custom error: this file is not an Exif file 
 
   // set up the LOADFILEOPTION structure to read tags from the Exif IFD 
   LOADFILEOPTION LoadFileOption; 
   L_GetDefaultLoadFileOption(&LoadFileOption, sizeof(LoadFileOption)); 
   LoadFileOption.IFD = nExifIFDOffset; 
   LoadFileOption.Flags = ELO_USEIFD; 
 
   // step2: Find the offset of the MakerNote tag. Use L_EnumFileTags instead of L_ReadFileTag 
   //        because it is the only way to get the offset value for a tag with more than 4 bytes 
   L_UINT uTags; 
   LEADFILETAG *pTags; 
   L_INT nRet = L_ReadFileTags(pszFile, READFILEMETADATA_NOMEMORY, &uTags, &pTags, NULL, NULL, &LoadFileOption); 
   if(nRet != SUCCESS) 
      return nRet; 
 
   for(UINT u = 0; u < uTags; u++) 
   { 
      if(pTags[u].uTag == 0x927C) // makernote tag 
      { 
         // read the makernote tags 
         LoadFileOption.IFD = pTags[u].uDataOffset; 
 
         // The Canon Makernote tags lists the Camera Serial number  
         // 12    Camera Serial Number    Special - To display serial number as on camera use: printf( "%04X%05d", highword, lowword ) 
         nTagSize = L_ReadFileTag(pszFile, 12, &uType, &uCount, NULL, &LoadFileOption); 
 
         if(nTagSize == 4) 
         { 
            L_UINT uSerialNumber; 
            nTagSize = L_ReadFileTag(pszFile, 12, &uType, &uCount, &uSerialNumber, &LoadFileOption); 
            if(nTagSize == 4) 
            { 
               TCHAR s[50]; 
               _stprintf_s(s, _countof(s), TEXT("%04X%05d"), HIWORD(uSerialNumber), LOWORD(uSerialNumber)); 
               MessageBox(hWnd, s, TEXT("Serial Number"), MB_OK); 
            } 
         } 
         L_FreeFileTags(uTags, pTags, 0, NULL); 
 
         return SUCCESS; 
      } 
   } 
 
   L_FreeFileTags(uTags, pTags, 0, NULL); 
 
   return -5001; // custom error: did not find the tag 
}  

Help Version 23.0.2024.2.29
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2024 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.