Reading the IPTC Headline tag in photos

I’m now able to read some of the tags of a photo using Image Events, but I’m not able to get the Headline tag. Does anyone know if this is possible? I tried finding if this information was available using the SD debugger info but couldn’t find the info. Am I missing something or isn’t it simple possible?

I’m using this slightly modified version of a script I found online

set this_file to (choose file without invisibles) as text
try
	tell application "Image Events"
		-- start the Image Events application
		launch
		-- open the image file
		set this_image to open file this_file
		-- extract the metadata values
		tell this_image
			set picname to the name
			repeat with i from 1 to the count of metadata tags
				try
					set this_tag to metadata tag i
					set the tag_name to the name of this_tag
					set the tag_value to the value of this_tag
					if i is 1 then
						set the tag_text to tag_name & ": " & tag_value
					else
						set the tag_text to the tag_text & return & tag_name & ": " & tag_value
					end if
				on error
					if the tag_name is "profile" then
						set the tag_text to the tag_text & return & tag_name & ": " & name of tag_value
					end if
				end try
			end repeat
			set x to the count of metadata tags
		end tell
		-- purge the open image data
		close this_image
	end tell
	display dialog x
	display dialog picname
	display dialog tag_text
on error error_message
	display dialog error_message buttons {"Cancel"} default button 1
end try

In my testing, ExifTool returns IPTC tags but not Image Events or ASObjC. As you probably know, ExifTool is a free command-line utility that can be run in an AppleScript with the do shell script command. The following illustrate:

set sourceFile to quoted form of POSIX path of (choose file)

-- returns all metadata
set theData to (do shell script "/usr/local/bin/exiftool -sort " & sourceFile)

-- returns all IPTC metadata
set theData to (do shell script "/usr/local/bin/exiftool -sort -iptc:all " & sourceFile)

-- returns all XMP metadata
set theData to (do shell script "/usr/local/bin/exiftool -sort -xmp:all " & sourceFile)

-- returns headline tag
set theData to (do shell script "/usr/local/bin/exiftool -headline " & sourceFile)

You can retrieve it using ASObjC in macOS 12, but not earlier versions.

use AppleScript version "2.8" -- requires macOS 12 or later
use scripting additions
use framework "Foundation"
use framework "AppKit" -- for image stuff

set POSIXPath to POSIX path of (choose file)
set theImageRep to current application's NSBitmapImageRep's imageRepWithContentsOfFile:POSIXPath
set theIPTCData to theImageRep's valueForProperty:(current application's NSImageIPTCData)
if theIPTCData is missing value then error "NoIPTC data data found"
return theIPTCData as record

I’m running macOS 12, but in my ASOjbC test script I used NSImageEXIFData rather than NSImageIPTCData, which I didn’t know existed. Works great with that change.

They’re two seperate blocks of metadata. NSImageEXIFData support has been there for a long time.

Thanks to both of you, I’m getting closer to what I want … sorry about being dense but AppleScript haven’t been a language that I’ve used seriously for many years. I got two additional questions.

I got everything to work except that I’ve got problems in translating the strings for date/time into a date object. The conversion works but I get the wrong date. Example

-- Trying 'date "2022-02-03"'
date "Thursday, 14 August 2008 at 00:00:00"

At first I thought it was that I had the wrong date format set, I’m running my Mac with the language set to English (US) but with the date format set to YYYY-MM-DD (I confirmed this in the settings). Any idea why I get the wrong date.

Second question: I’m pretty sure that this could be done in a better way, how would you more experienced people write this (I want a record with date, title and caption that I then can pass to other handlers).

on getphotodata(photopath)
	set theImageRep to current application's NSBitmapImageRep's imageRepWithContentsOfFile:photopath
	set theIPTCData to theImageRep's valueForProperty:(current application's NSImageIPTCData)
	if theIPTCData is missing value then error "NoIPTC data data found"
	set pHeadline to (Headline of theIPTCData) as text
	set pCaption to (|Caption/Abstract| of theIPTCData) as text
	set pdate to (DateCreated of theIPTCData) as text
	set ptime to (TimeCreated of theIPTCData) as text
	set pd to (date ((text 1 thru 4 of pdate) & "-" & (text 5 thru 6 of pdate) & "-" & (text 7 thru 8 of pdate))) --+ ((text 1 thru 2 of ptime) as integer) * hours + ((text 3 thru 4 of ptime) as integer) * minutes + ((text 5 thru 6 of ptime) as integer)
	return {title:pHeadline, caption:pCaption, timestamp:pd}
end getphotodata

The date comes out wrong here as described in the first question but I assume I could do this in better way?

Jan. The AppleScript Language Guide states as follows:

You can create a date object using a string that follows the date format specified in the Formats pane in International preferences.

The trouble is that there are four date formats, and, in the circumstance you cite, one would expect the short date format to be followed but it isn’t. For example, I have the short date format set to “2022/06/01”, yet I get the following results:

set theDate to "2022/02/03" -- February 3, 2022
set theDateObject to date theDate --> date "Sunday, June 2, 12171 at 12:00:00 AM"

You can correct the above by changing the other date formats, which seems undesirable, or (apparently) by using the default short date format for your locale:

set theDate to "02/03/22" -- February 3, 2022
set theDateObject to date theDate --> date "Thursday, February 3, 2022 at 12:00:00 AM"

As regards the rest of your script, theIPTCData is a dictionary and I would probably use the valueForKey method to get the value of the desired keys. One advantage of this is that “missing value” is returned if a key is not found. Also, some error correction is necessary. There are a lot of ways to write your script but my suggestion FWIW:

use AppleScript version "2.8" -- requires macOS 12 or later
use framework "AppKit"
use framework "Foundation"
use scripting additions

set photopath to POSIX path of (choose file)
set theData to getphotodata(photopath)

on getphotodata(photopath)
	set theImageRep to current application's NSBitmapImageRep's imageRepWithContentsOfFile:photopath
	set theIPTCData to theImageRep's valueForProperty:(current application's NSImageIPTCData)
	if theIPTCData is missing value then error "NoIPTC data data found"
	set pHeadline to (theIPTCData's valueForKey:"Headline") as text
	if pHeadline = "missing value" then set pHeadline to "No IPTC headline"
	set pCaption to (theIPTCData's valueForKey:"Caption/Abstract") as text
	if pCaption = "missing value" then set pCaption to "No IPTC caption"
	set pDate to (theIPTCData's valueForKey:"DateCreated") as text
	if pDate = "missing value" then
		set pd to "No IPTC date"
	else
		set pd to (date ((text 5 thru 6 of pDate) & "/" & (text 7 thru 8 of pDate) & "/" & (text 3 thru 4 of pDate))) -- change for your locale
	end if
	return {title:pHeadline, caption:pCaption, timestamp:pd}
end getphotodata

I’d use ASObjC to do the date conversion, because I suspect the dates strings are UTC, not local time. I see the spec says TimeCreated can be 11 characters, so I presume in that case it includes a time zone value. So try something like this:

on dateFromPate:pdate andPime:ptime
	set fullDate to pdate & ptime
	set theFormatter to current application's NSDateFormatter's new()
	theFormatter's setLocale:(current application's NSLocale's localeWithLocaleIdentifier:"en_US_POSIX")
	theFormatter's setTimeZone:(current application's NSTimeZone's timeZoneWithAbbreviation:"GMT")
	if length of fullDate = 14 then
		theFormatter's setDateFormat:"yyyyMMddHHmmss"
	else -- time zone included?
		theFormatter's setDateFormat:"yyyyMMddHHmmssZZZ"
	end if
	return theFormatter's dateFromString:fullDate
end dateFromPate:andPime:

Huge thanks to both of you. I’m learning a lot, not only about my problem but about AS in general.

:+1:t2::pray:t2:

Is there a way to get the XMP data (similar to @peavine 's exiftool call)? I see there is no NSImageXMPData. We use Exiftool regularly but this use of ASObjC intrigues me if it can get at the custom XMP metadata fields that we use.

Secondarily (and more importantly for us), if it is possible to get the XMP data with ASObjC can it then also be modified on the file? This is what we’re primarily using ExifTool for. Applying custom metadata fields/values on files before we transfer to our retouch team/processing system. Would love to be able to do it without the requirement of Exiftool (just one less thing to remember to install).

Alas, no. I suspect exiftool is your best bet for that.