Exif example for C++ 4.0 and later

This example does the following:

1. Reads all of the comments in an existing Exif file, updating the Comment array.

2. Loads and modifies the file's image.

3. Updates some of the comments in the comment array.

4. Saves the file.

5. Reads and displays the updated comments.

Note: Comments for GIF, TIFF, and DICOM files are simpler than the ones in this Exif example. With those file types, all of the comments are strings that you can get and set with simple assignments.

// Array index for general use.
long MyIndex;

// Value for clearing comments.
COleVariant Empty = COleVariant();

// File that we will load and update.
CString FilePath = "d:\\lead\\images\\exif1.tif";

// Get all of the current comments from an Exif file.
// Temporarily disable errors so that we do not fail when comments are missing.
m_Lead1.SetEnableMethodErrors(FALSE);
for(short i = 0; i <= CMNT_LAST; ++i)
{
  m_Lead1.SetComment(i, Empty);
  m_Lead1.SetComment(i, m_Lead1.ReadComment(FilePath, 0, i));
}
m_Lead1.SetEnableMethodErrors(TRUE);

// Load and modify the image.
m_Lead1.Load(FilePath, 0, 0, 1);
m_Lead1.Reverse();

// Update the date when the file is generated.
CTime RightNow = CTime::GetCurrentTime();
CString DateTimeString = RightNow.Format("%Y:%m:%d %H:%M:%S");
m_Lead1.SetComment(CMNT_SZDATETIMEDIGITIZED, COleVariant(DateTimeString));
m_Lead1.SetComment(CMNT_SZSUBSECTIMEDIGITIZED, Empty);

// Change the CMNT_SUBJECTDISTANCE comment to 4 1/3 meters.

// Create a SAFEARRAY that contains the RATIONAL values.
COleSafeArray ASubjectDistance;
ASubjectDistance.CreateOneDim( VT_I4, 2, NULL, 0 );
long SaveNumerator = 13;
long SaveDenominator = 3;
MyIndex = 0;
ASubjectDistance.PutElement( &MyIndex, &SaveNumerator );
MyIndex = 1;
ASubjectDistance.PutElement( &MyIndex, &SaveDenominator );

// Update the CMNT_SUBJECTDISTANCE comment.
m_Lead1.SetComment(CMNT_SUBJECTDISTANCE, ASubjectDistance);

// Add an ASCII CMNT_USERCOMMENT comment.

// Specify the user comment string.
CString MyCommentText = "This is my new comment.";
int MyCommentSize = 8 + MyCommentText.GetLength();

// Define the array for the user comment.
CByteArray MyComment;
MyComment.SetSize(MyCommentSize + 1);

// Fill in the ASCII prefix.
MyComment[0] = 'A';
MyComment[1] = 'S';
MyComment[2] = 'C';
MyComment[3] = 'I';
MyComment[4] = 'I';
MyComment[5] = '\0';
MyComment[6] = '\0';
MyComment[7] = '\0';

// Fill in the rest of the CMNT_USERCOMMENT comment.
for( i = 8; i < MyCommentSize; ++i)
{
  MyComment[i] = MyCommentText[i-8];
}
MyComment[MyCommentSize] = '\0';

// Update the CMNT_USERCOMMENT comment.
m_Lead1.SetComment(CMNT_USERCOMMENT, Empty);
m_Lead1.SetComment(CMNT_USERCOMMENT, COleVariant(MyComment));

// Save the file.
m_Lead1.Save(FilePath, FILE_EXIF, 24, 0, SAVE_OVERWRITE);

// Read the comments that we saved.
VARIANT V1 = m_Lead1.ReadComment(FilePath, 0, CMNT_SZDATETIMEDIGITIZED);
COleVariant VDateTimeString;
VDateTimeString.Attach(V1);

VARIANT V2 = m_Lead1.ReadComment(FilePath, 0, CMNT_SUBJECTDISTANCE);
COleVariant VSubjectDistance;
VSubjectDistance.Attach(V2);

VARIANT V3 = m_Lead1.ReadComment(FilePath, 0, CMNT_USERCOMMENT);
COleVariant VMyComment;
VMyComment.Attach(V3);

// Interpret the CMNT_SUBJECTDISTANCE RATIONAL.
long MyNumerator, MyDenominator;
MyIndex = 0;
SafeArrayGetElement(VSubjectDistance.parray, &MyIndex, &MyNumerator);
MyIndex = 1;
SafeArrayGetElement(VSubjectDistance.parray, &MyIndex, &MyDenominator);

// Format the Subject Distance as a string.
CString DistanceString;
DistanceString.Format("%f", (double)MyNumerator / MyDenominator);

// Format the CMNT_SZDATETIMEDIGITIZED comment as a string.
CString NewDateTime =  CString(VDateTimeString.bstrVal);

// Initialize the string for the message box.
CString MyMsg = "Subject Distance = " + DistanceString + "\nDate/Time = " + NewDateTime;

// Add the ASCII comment to the message, if the comment is there.
MyIndex = 0;
char OneCharacter;
SafeArrayGetElement(VMyComment.parray, &MyIndex, &OneCharacter);

if( OneCharacter == 'A')
{
   MyMsg = MyMsg + "\n\n";
   long ArraySize, LowerBound, UpperBound;
   SafeArrayGetLBound(VMyComment.parray, 1, &LowerBound);
   SafeArrayGetUBound(VMyComment.parray, 1, &UpperBound);
   ArraySize = UpperBound - LowerBound;
   for ( MyIndex = 8; MyIndex <= ArraySize; MyIndex++)
   {
      SafeArrayGetElement(VMyComment.parray, &MyIndex, &OneCharacter);
      MyMsg = MyMsg + CString(OneCharacter);
   }
}

// Display the message.
MessageBox(MyMsg);

// Clear the comments from memory
for( i = 0; i <= CMNT_LAST; ++i)
  m_Lead1.SetComment(i, Empty);