This tutorial shows how to read and write Exif tags and comments in a Windows C/C++ API application using the LEADTOOLS SDK.
| Overview | |
|---|---|
| Summary | This tutorial covers how to work with Exif tags and comments in a Windows C DLL application. |
| Completion Time | 30 minutes |
| Visual Studio Project | Download tutorial project (20 KB) |
| Platform | Windows C DLL Application |
| IDE | Visual Studio 2017, 2019 |
| Development License | Download LEADTOOLS |
| Try it in another language |
|
Get familiar with the basic steps of creating a project and loading/displaying an image by reviewing theAdd References and Set a LicenseandLoad, Display, and Save Imagestutorials, before working on theRead and Write Exif Tags and Comments - Windows C DLLtutorial.
Start with a copy of the project created in theLoad, Display, and Save Imagestutorial. If the project is not available, create it by following the steps in that tutorial.
Open the pre-compiled header file (eitherpch.horstdafx.h, depending on the version of Visual Studio used) and ensure the below lines are added.
#define LTV22_CONFIG#include"C:\LEADTOOLS22\Include\L_Bitmap.h"// use the actual path where LEADTOOLS is installed#pragma comment (lib,"C:\\LEADTOOLS22\\Lib\\CDLL\\x64\\Ltkrn_x.lib")#pragma comment (lib,"C:\\LEADTOOLS22\\Lib\\CDLL\\x64\\Ltfil_x.lib")// file loading and saving#pragma comment (lib,"C:\\LEADTOOLS22\\Lib\\CDLL\\x64\\Ltdis_x.lib")// image display
Note
For a complete list of DLLs that are required for specific application features, refer toFiles to be Included with your Application - C API
The License unlocks the features needed for the project. It must be set before any toolkit functionality is called. For details, including tutorials for different platforms, refer toSetting a Runtime License.
There are two types of runtime licenses:
Note
Adding LEADTOOLS references and setting a license are covered in more detail in theAdd References and Set a Licensetutorial.
With the project created, the references added, the license set, and the load image code added, coding can begin.
In theSolution Explorer, double-click the resources file (.rc).
Add a newExif &Commentmenu item to theFiledrop-down menu, between theOpenandSaveitems. Leave the new menu item's ID asID_FILE_EXIFCOMMENT.
Open the project's CPP file and navigate to theWndProcfunction. Under theswitch (wmId)statement that is below theWM_COMMANDcase, add a new case and the code below.
switch(wmId){caseID_FILE_EXIFCOMMENT:ReadAndWriteExifComments(hWnd);break;// Keep rest of the code as is
Add the ReadAndWriteExifComments function below to flip the loaded image, write a comment to the file stating that the image has been flipped, and then read the user comment created.
voidReadAndWriteExifComments(HWND hWnd){L_TCHAR szSrcFile[260] = TEXT(""), szDestFile[260] = TEXT("");if(SUCCESS != GetBitmapLoadingName(hWnd, szSrcFile, ARRAYSIZE(szSrcFile)))return;if(LEADBmp.Flags.Allocated)L_FreeBitmap(&LEADBmp);L_LoadBitmap(szSrcFile, &LEADBmp,sizeof(LEADBmp), 24, ORDER_BGR, NULL, NULL);InvalidateRect(hWnd, NULL, TRUE);MessageBox(hWnd, TEXT("Image loaded and will be flipped.\nSelect output file"), TEXT("LEADTOOLS Demo"), MB_ICONINFORMATION);// Flip the image.L_FlipBitmap(&LEADBmp);InvalidateRect(hWnd, NULL, TRUE);// Specify output fileif(SUCCESS != GetBitmapSavingName(hWnd, szDestFile, ARRAYSIZE(szDestFile)))return;// Load the current comments from the filefor(inti = 0; i < CMNT_LAST; i++){// Clear the commentL_SetComment(i, NULL, 0);// Use the return value to get the length of a comment in the fileL_INT CommentLength = L_ReadFileComment(szSrcFile, i, NULL, 0, NULL);if(CommentLength > 0){L_UCHAR* pCommentToGet =newL_UCHAR[CommentLength]();// parentheses initialize array to zeros// Get the comment from the fileL_ReadFileComment(szSrcFile, i, pCommentToGet, CommentLength, NULL);// Set the comment to be savedL_SetComment(i, pCommentToGet, CommentLength);delete[] pCommentToGet;}}// Create the CMNT_USERCOMMENT comment as a byte array// When writing a user comment, the first 8 bytes must contain the "ASCII" word.L_SetComment(CMNT_USERCOMMENT, NULL, 0);// IMPORTANT: initializing CommentToSet array causes remainder of array to contain null characters, which is needed for rest of code to workL_UCHAR CommentToSet[80] ="ASCII";constL_CHAR* pUserComment ="The image has been flipped!";strcpy_s((char*)CommentToSet + 8,sizeofCommentToSet - 8, pUserComment);// Set the CMNT_USERCOMMENT commentL_SetComment(CMNT_USERCOMMENT, CommentToSet, (L_UINT)strlen(pUserComment) + 9);L_SaveBitmap(szDestFile, &LEADBmp, FILE_EXIF, 24, 0, NULL);L_UCHAR CommentCheck[80] ="";L_ReadFileComment(szDestFile, CMNT_USERCOMMENT, CommentCheck,sizeofCommentCheck, NULL);charszMessageA[256] ="Comment read back from file:\n";strcat_s(szMessageA,sizeofszMessageA, (constchar*)CommentCheck + 8);// The returned string is in ASCII, so the "MessageBoxA" function is used to display itMessageBoxA(hWnd, szMessageA,"LEADTOOLS Demo", MB_OK);}
The code for theGetBitmapLoadingName()andGetBitmapSavingName()functions, called inside the code above, is listed in theLoad, Display, and Save Imagestutorial.
Using theSolution Explorer, navigate back to the resources file (.rc).
Add a newEXIF &Tagmenu item to theFiledrop-down menu, between theOpenandSaveitems. Leave the new menu item's ID asID_FILE_EXIFTAG.
Go to theWndProcfunction and under theswitch (wmId)statement that is below theWM_COMMANDcase, add a new case and the code below.
switch(wmId){caseID_FILE_EXIFTAG:ReadAndWriteExifTags(hWnd);break;// Keep rest of the code as is
Add the code of theReadAndWriteExifTagsfunction, which adds a custom text tag to the EXIF file then reads all the tags back from the file.
voidReadAndWriteExifTags(HWND hWnd){L_TCHAR szExifFile[260] = TEXT("");if(SUCCESS != GetBitmapLoadingName(hWnd, szExifFile, ARRAYSIZE(szExifFile)))return;FILEINFO info = { 0 };// Important: Must initialize to zeroinfo.uStructSize =sizeofinfo;L_FileInfo(szExifFile, &info,sizeofinfo, 0, NULL);if(!L_TagsSupported(info.Format)){MessageBox(hWnd, TEXT("File Format Does Not Support Tags"), TEXT("LEADTOOLS Demo"), MB_ICONERROR);return;}// Add a private (custom) "Phone Number" tagL_UINT16 PhoneNumber = 0x8001;charTagData[] ="+1-800-637-4699";// Set the tag data to be savedL_SetTag(PhoneNumber, TAG_ASCII,sizeofTagData, TagData);// Save the the tag into the fileL_WriteFileTag(szExifFile, NULL);// Clear the tag from memoryL_SetTag(0, 0, 0, NULL);// Read the tags from the file and display them in the debugger windowL_UINT uTagCount = 0;pLEADFILETAG pTags = NULL, pCurrentTag;L_SIZE_T uTagDataSize = 0;L_UCHAR* pTagsData = NULL;L_ReadFileTags(szExifFile, 0, &uTagCount, &pTags, &uTagDataSize, &pTagsData, NULL);if(uTagCount > 0){// Show the tagsOutputDebugString(TEXT("Tags\n"));for(L_UINT n = 0; n < uTagCount; n++){pCurrentTag = &pTags[n];// If this tag is of type ASCII, get its dataL_CHAR* pszAscii = NULL;if(pCurrentTag->uType == TAG_ASCII){pszAscii =newL_CHAR[pCurrentTag->uDataSize + 1]();memcpy(pszAscii, pTagsData + pCurrentTag->uDataOffset, pCurrentTag->uDataSize);}else{pszAscii = NULL;}CHAR szMessage[1024];wsprintfA(szMessage,"Id: 0x%X, data length: %u, data: %s\n", pCurrentTag->uTag, pCurrentTag->uDataSize, pszAscii != NULL ? pszAscii :"Binary data");if(pszAscii)delete[] pszAscii;OutputDebugStringA(szMessage);}L_FreeFileTags(uTagCount, pTags, uTagDataSize, pTagsData);}}
Run the project by pressingF5, or by selectingDebug -> Start Debugging.
If the steps are followed correctly, the application runs and gives the user the ability to execute the following commands:
This tutorial showed how to use theL_SetComment,L_ReadFileComment,L_ReadFileTags,L_SetTagandL_WriteFileTagfunctions with EXIF files.