Implementing Exif Features

The Exif file format supports more complex comments than other formats. For a list of the comments, refer to Exif File Comments.

This example demonstrates how to handle Exif comments that are not stored as strings. (For a simpler example for saving strings, refer to the LFileSettings::SetComment function.)

This example does the following:

1.

Loads a bitmap.

2.

Updates the comment array by loading comments from the existing file.

3.

Reverses the image and creates an ASCII CMNT_USERCOMMENT comment that says that the image has been reversed.

4.

Saves the file. (All of the comments are saved, including the one that we updated.)

5.

Reads and displays two of the comments from the saved file. One of them is the comment that we created. The other is comment that uses the Exif RATIONAL data type.

6.

Cleans up the comment array.

void CTt2View::TestFunction(HWND hWnd, L_TCHAR L_FAR* szFilename)
{
   LBitmapBase LeadBitmap;

   L_CHAR L_FAR * pCommentToGet; /* Comment string that we will get */
   LBuffer CommentToGet; /* Handle for memory management */
   L_INT CommentLength; /* Length of the string */
   L_CHAR CommentToSet[80]; /* Comment string that we will set */
   L_CHAR L_FAR * pCommentToSet = CommentToSet;
   L_CHAR szUserComment[80]; /* User comment that we will add */
   L_CHAR L_FAR * pUserComment = szUserComment;

   L_UINT32 L_FAR * pDistance; /* Pointer for the Exif RATIONAL */
   L_UINT32 Numerator, Denominator; /* Components of the Exif RATIONAL */
   float fDistance; /* Result of the distance calculation */
   L_TCHAR szMessage[256]; /* MessageBox string */ 

   L_TCHAR szMessage2[256]; /* MessageBox string */

   L_INT i; /* Loop counter */
   /* Load the bitmap */
   LeadBitmap.Load(szFilename);
   /* Load the current comments from the file */
   for(i = 0 ; i < CMNT_LAST ; i++ )
   {
      /* Clear the comment */
      LFileSettings::SetComment(i,NULL,0);
      /* Use the return value to get the length of a comment in the file */
      CommentLength=LeadBitmap.File()->ReadComment(i,0);
      if(CommentLength>0)
      {
         /* Allocate and lock a zero-filled buffer for the comment */
         CommentToGet.Reallocate(CommentLength);
         /* Get the comment from the file */
         LeadBitmap.File()->ReadComment(i,&CommentToGet);
         /* Set the comment to be saved */
         LFileSettings::SetComment(i,(L_UCHAR L_FAR*)CommentToGet.Lock(),CommentLength);
         /* Unlock and free memory */
         CommentToGet.Unlock();
      }
   }
   

   /* Reverse the image */
   LeadBitmap.Reverse();
   /* Create the CMNT_USERCOMMENT comment as a byte array */
   LFileSettings::SetComment(CMNT_USERCOMMENT, NULL, 0);
   pUserComment ="The image has been reversed.";
   pCommentToSet[0] = 'A';
   pCommentToSet[1] = 'S';
   pCommentToSet[2] = 'C';
   pCommentToSet[3] = 'I';
   pCommentToSet[4] = 'I';
   pCommentToSet[5] = '\0';
   pCommentToSet[6] = '\0';
   pCommentToSet[7] = '\0';
   for( i = 0; pUserComment[i] != '\0'; i++)
   {
      pCommentToSet[i+8] = pUserComment[i];
   }
   pCommentToSet[i+8] = '\0';

   /* Set the CMNT_USERCOMMENT comment */
   LFileSettings::SetComment(CMNT_USERCOMMENT,(L_UCHAR L_FAR*)pCommentToSet,
   strlen(pUserComment) + 9);
   /* Save the image as an Exif file */
   LeadBitmap.Save(FILE_EXIF,24,0, NULL, NULL);
   /* Initialize the message string */
   szMessage[0] = '\0';
   /* Use the return value to get the length of the CMNT_SUBJECTDISTANCE comment */
   /* This shows how to translate the Exif RATIONAL data type */
   CommentLength=LeadBitmap.File()->ReadComment(CMNT_SUBJECTDISTANCE,0);

   if(CommentLength>0)
   {
      /* Allocate and lock a zero-filled buffer for the comment */
      CommentToGet.Reallocate(CommentLength);
      /* Get the actual comment from the file */
      LeadBitmap.File()->ReadComment(CMNT_SUBJECTDISTANCE,&CommentToGet);
      pDistance = (L_UINT32 L_FAR *)CommentToGet.Lock();
      Numerator = pDistance[0];
      Denominator = pDistance[1];
      fDistance = (float)Numerator / (float)Denominator;
      wsprintf (szMessage,TEXT("Subject distance: %.6f\n"),fDistance );

      CommentToGet.Unlock();
   }
   /* Use the return value to get the length of the CMNT_USERCOMMENT comment */
   CommentLength=LeadBitmap.File()->ReadComment(CMNT_USERCOMMENT,0);
   if (CommentLength > 0)
   {
      /* Allocate and lock a zero-filled buffer for the comment */
      CommentToGet.Reallocate(CommentLength);
      /* Get the actual comment from the file */
      LeadBitmap.File()->ReadComment(CMNT_USERCOMMENT,&CommentToGet);
      /* If the prefix is ASCII, move the pointer and update the message string */
      pCommentToGet=(L_CHAR L_FAR*)CommentToGet.Lock();
      if (strcmp(pCommentToGet,"ASCII")== 0)
      {
         pCommentToGet = pCommentToGet + 8;
      }

               wsprintf(szMessage2,TEXT("%s%hs"),szMessage, pCommentToGet);
               /* Unlock and free memory */
               CommentToGet.Unlock();
            }
            /* Show the two comments */
            ::MessageBox (NULL,szMessage2, TEXT("Notice"), MB_OK);
            /* Clear the comments */
            for(i = 0 ; i < CMNT_LAST ; i++ )
               LFileSettings::SetComment(i,NULL,0);
            /* Force a repaint */
            ::SendMessage(hWnd,WM_QUERYNEWPALETTE,0,0L);
            return;
         }