This tutorial shows how to read and write Exif tags and comments in a macOS Swift Console application using the LEADTOOLS SDK.
Overview | |
---|---|
Summary | This tutorial covers how to work with Exif tags and comments in a macOS Swift Console application. |
Completion Time | 20 minutes |
Visual Studio Project | Download tutorial project (6 KB) |
Platform | macOS Swift Console Application |
IDE | Xcode |
Development License | Download LEADTOOLS |
Try it in another language |
|
Get familiar with the basic steps of creating a project by reviewing the Add References and Set a License tutorial, before working on the Read and Write Exif Tags and Comments - macOS Swift Console tutorial.
Start with a copy of the project created in the Add References and Set a License tutorial. If you do not have that project, follow the steps in that tutorial to create it.
The references needed depend upon the purpose of the project. This tutorial requires the following Framework references located at <INSTALL_DIR>\LEADTOOLS23\Bin\Xcode\Frameworks\macOS
:
Leadtools.Codecs.Cmp.framework
Leadtools.Codecs.Tif.framework
Leadtools.Codecs.framework
Leadtools.framework
Edit the Leadtools-Bridging-Header.h
file to add the following imports:
#import <Leadtools.Codecs/Leadtools.Codecs.h>
For a complete list of which files are required for your application, refer to Files to be Included in your Application.
The License unlocks the features needed for the project. It must be set before any toolkit function is called. For details, including tutorials for different platforms, refer to Setting a Runtime License.
There are two types of runtime licenses:
Note: Adding LEADTOOLS references and setting a license are covered in more detail in the Add References and Set a License tutorial.
With the project created, the references added, and the license set, coding can begin.
Using the Project Navigator, open main.swift
. Add two new string variables named srcFile
and destFile
below the call to the SetLicense()
function. Set srcFile
equal to the file path containing the source Exif file and set destFile
equal to the file path to export the EXIF file containing the added comment. Additionally, create a new instance of LTRasterCodecs
.
Next, add a new function named ReadAndWriteExifComments(srcFile: srcFile, destFile: destFile, codecs: codecs)
. Call this function below the LTRasterCodecs
object instance, as shown below.
SetLicense()
let srcFile = "<INSTALL_DIR>/LEADTOOLS23/Resources/Images/addcommand.tif"
let destFile = "<INSTALL_DIR>/save/addcommand.tif"
let codecs: LTRasterCodecs = LTRasterCodecs()
ReadAndWriteExifComments(srcFile: srcFile, destFile: destFile, codecs: codecs)
ReadAndWriteExifTags(srcFile: srcFile, codecs: codecs)
Add the below code to the ReadAndWriteExifComments()
function to flip the loaded image, write a tag to the file stating that the image has been flipped, and then display the user comment created to the console.
func ReadAndWriteExifComments(srcFile: String, destFile: String, codecs: LTRasterCodecs) {
do {
let image: LTRasterImage = try codecs.load(file: srcFile)
// Write Comment
// Flip the image
let flipCmd: LTFlipCommand = LTFlipCommand(horizontal: true)
try flipCmd.run(image)
// Add a user comment to the file and save it in another name
var comment: LTRasterCommentMetadata = LTRasterCommentMetadata()
comment.type = .userComment
let comments: String = "The image has been flipped"
let data: [UTF16Char] = Array(comments.utf16)
var dataComments: [UInt8] = Array(repeating: 0, count: 8 + comments.count)
// When you need to write a user comment the first 8 bytes must contain the "Ascii" word.
dataComments[0] = 41
dataComments[1] = 53
dataComments[2] = 43
dataComments[3] = 49
dataComments[4] = 49
for i in 0..<comments.count {
dataComments[8 + i] = UInt8(data[i])
}
// Set the data property in the comment object to the dataComments array
comment.fromByte(&dataComments, itemCount: UInt(dataComments.count))
// Add the user comment to the comments collection of the image
image.comments?.add(comment)
codecs.options.save.comments = true
try codecs.save(image, file: destFile, format: LTRasterImageFormat.exif, bitsPerPixel: 24)
// Read the comments
comment = try codecs.readComment(from: destFile, pageNumber: 1, type: .userComment)
dataComments = comment.data.bytes
var msg: String = "User comments = "
for i in 0..<(dataComments.count - 8) {
msg += String(UnicodeScalar(dataComments[i + 8]))
}
print(msg)
} catch {
print(error.localizedDescription)
}
}
Add a new function named ReadAndWriteExifTags(srcFile: String, codecs: LTRasterCodecs)
. Call this function below the call to the ReadAndWriteExifComments()
function, as shown in the previous section. add the code below to the ReadAndWriteExifTags
method to read the tags from the designated file.
func ReadAndWriteExifTags(srcFile: String, codecs: LTRasterCodecs) {
do {
let info: LTCodecsImageInfo = try codecs.imageInformation(file: srcFile, totalPages: false)
let format: LTRasterImageFormat = info.format
// Load the tags
if !LTRasterCodecs.tagsSupported(format) {
print("File Format Does not Support Tags")
return
}
let tags: [LTRasterTagMetadata] = [LTRasterTagMetadata](try codecs.readTags(from: srcFile, pageNumber: 1))
let txtFileName: String = "/path/to/save/metadata.txt"
let fileURL = URL(fileURLWithPath: txtFileName)
if !FileManager.default.fileExists(atPath: fileURL.path) {
try ("".data(using: .utf8))!.write(to: fileURL, options: .atomicWrite)
}
var writer = try FileHandle(forWritingTo: fileURL)
WriteTags(writer: &writer, name: "Tags", tags: tags)
} catch {
print(error.localizedDescription)
}
}
Add a new function named WriteTags(writer: inout FileHandle, name: String, tags: [LTRasterTagMetadata])
. This new function will be called within the ReadAndWriteExifTags()
function, as shown above. Add the code below to the WriteTags()
function to write the read tags to a TXT file.
func WriteTags(writer: inout FileHandle, name: String, tags: [LTRasterTagMetadata]) {
writer.write(name.data(using: .utf8)!)
if tags != nil {
for tag in tags {
writer.write("\nId: 0x\(String(format: "%02X", tag.tagId)) data length: \(tag.data.count)".data(using: .utf8)!)
}
} else {
writer.write("Not supported".data(using: .utf8)!)
}
writer.write("".data(using: .utf8)!)
}
In order to facilitate data type conversion add an extension named Data
.
extension Data {
var bytes: [UInt8] {
return [UInt8](self)
}
}
Clean the project to clear any errors by selecting Product -> Clean Build Folder or Shift + Command + K.
Run the project by selecting Product -> Run or Command + R.
If the steps were followed correctly, the application runs, writes an Exif user comment, reads the written user comment, then reads the Exif tags inside the given image and writes those tags to an external TXT file.
This tutorial showed how to read and write Exif comments and tags. Also, we covered how to use the LTRasterCodecs
and LTRasterTagMetadata
classes.