Reputation: 466
I want to get the description of an .jpg image. It gets shown in the Mac OSx Info (cmd +i) window.
I want to read the "description" (Beschreibung in German) field. Trying this with PIL and exifread lead to no success.
I can get these exif Tags, but they do not include the description or keywords.
Key: Image ImageWidth
Key: Image ImageLength
Key: Image Compression
Key: Image Make
Key: Image Model
Key: Image XResolution
Key: Image YResolution
Key: Image PlanarConfiguration
Key: Image ResolutionUnit
Key: Image Software
Key: Image DateTime
Key: Image YCbCrPositioning
Key: Image ExifOffset
Key: Thumbnail Compression
Key: Thumbnail Orientation
Key: Thumbnail XResolution
Key: Thumbnail YResolution
Key: Thumbnail ResolutionUnit
Key: Thumbnail DateTime
Key: Thumbnail JPEGInterchangeFormat
Key: Thumbnail JPEGInterchangeFormatLength
Key: EXIF ExposureTime
Key: EXIF FNumber
Key: EXIF ExposureProgram
Key: EXIF ISOSpeedRatings
Key: EXIF SensitivityType
Key: EXIF ExifVersion
Key: EXIF DateTimeOriginal
Key: EXIF DateTimeDigitized
Key: EXIF ComponentsConfiguration
Key: EXIF ShutterSpeedValue
Key: EXIF ApertureValue
Key: EXIF ExposureBiasValue
Key: EXIF MaxApertureValue
Key: EXIF MeteringMode
Key: EXIF LightSource
Key: EXIF Flash
Key: EXIF FocalLength
Key: EXIF SubSecTimeOriginal
Key: EXIF SubSecTimeDigitized
Key: EXIF ColorSpace
Key: EXIF ExifImageWidth
Key: EXIF ExifImageLength
Key: EXIF FocalPlaneXResolution
Key: EXIF FocalPlaneYResolution
Key: EXIF FocalPlaneResolutionUnit
Key: EXIF SensingMethod
Key: EXIF FileSource
Key: EXIF SceneType
Key: EXIF CVAPattern
Key: EXIF CustomRendered
Key: EXIF ExposureMode
Key: EXIF WhiteBalance
Key: EXIF DigitalZoomRatio
Key: EXIF FocalLengthIn35mmFilm
Key: EXIF SceneCaptureType
Key: EXIF GainControl
Key: EXIF Contrast
Key: EXIF Saturation
Key: EXIF Sharpness
Key: EXIF SubjectDistanceRange
Key: EXIF BodySerialNumber
Key: EXIF LensSpecification
Key: EXIF LensModel
I assume these fields are not EXIF data? What do I need to look for in order to get the description?
Upvotes: 3
Views: 1883
Reputation: 445
Extracting EXIF is the easiest part. The hardest part is interpreting them and making them work for each make and model. Some make, and model comes with few tags missing (e.g., Fujifilm has both LensMake and LensModel whereas Canon has only LensModel). In short, it could be something like this.
from PIL import Image
from math import pow
from PIL.ExifTags import TAGS
import datetime
def get_labeled_exif(exif):
labeled = {}
for (key, val) in exif.items():
labeled[TAGS.get(key)] = val
return labeled
def get_exif(filename):
image = Image.open(filename)
image.verify()
return image._getexif()
def get_shutter_speed(shutter_speed):
print("shutter_speed = {0}, type = {1}".format(
shutter_speed, type(shutter_speed)))
ss_val1 = 0.0
ss_val2 = 0.0
if type(shutter_speed) != type(list):
ss_val1 = shutter_speed
ss_val2 = 0
ss = (str(ss_val1/1) + "s") if ss_val1 > 0 else str(ss_val1)+"s"
return ss
ss_val1 = float(shutter_speed[0])
ss_val2 = float(shutter_speed[1])
ss = ss_val1/ss_val2
return str(round(1/pow(2, ss))) + \
"s" if ss_val1 < 0 else "1/"+str(round(pow(2, ss)))
def get_aperture(aperture):
print("aperture = {0}, type(aperture) = {1}".format(
aperture, type(aperture)))
ap_val1 = 0.0
ap_val2 = 0.0
if type(aperture) != type(list):
ap = float(aperture)
else:
ap_val1 = float(aperture[0])
ap_val2 = float(aperture[1])
ap = ap_val1/ap_val2
print("get_aperture:: ap_val1 = {0}, ap_val2 = {1}, aperture = {2}".format(ap_val1, ap_val2, ap))
return "f/"+str(ap)
def get_exposure_mode(mode):
if mode == 0:
return "Auto"
elif mode == 1:
return "Manual"
else:
return "Auto Bracket"
def get_light_source(ls_val):
if ls_val==10:
return "Cloudy Weather"
elif ls_val==13:
return "Cool White Fluorescent"
elif ls_val==1:
return "Daylight"
elif ls_val==12:
return "Daylight Fluorescent"
elif ls_val==13:
return "Day White Fluorescent"
elif ls_val==9:
return "Fine Weather"
elif ls_val==4:
return "Flash"
elif ls_val==2:
return "Fluorescent"
elif ls_val==11:
return "Shade"
elif ls_val==3:
return "Tungsten (Incandescent Light)"
elif ls_val==15:
return "White Fluorescent"
else:
return "Other Light Source"
def printFujifilmExif(labeled):
shutter_speed = get_shutter_speed(labeled['ExposureTime'])
aperture = get_aperture(labeled['FNumber'])
format = "%Y:%m:%d %H:%M:%S"
date_created = datetime.datetime.strptime(labeled['DateTimeOriginal'], format)
exposure_mode = get_exposure_mode(labeled['ExposureMode'])
light_source = get_light_source(
labeled['LightSource']) # LightSource for Fujifilm
iso_value = labeled['ISOSpeedRatings']
camera_make = labeled['Make']
camera_model = labeled['Model']
lens_make = labeled['LensMake'] # LensMake for Fujifilm
lens_model = labeled['LensModel'] # LensModel for Fujifilm
software = labeled['Software']
print("\n\nPRINTING PROFILE FOR FUJIFILM***")
print("Camera Make: {0}".format(camera_make))
print("Camera Model: {0}".format(camera_model))
print("Lens Make: {0}".format(lens_make))
print("Lens Model: {0}".format(lens_model))
print("Date taken: {0}".format(date_created))
print("Aperture: {0}".format(aperture))
print("Shutter speed: {0}".format(shutter_speed))
print("ISO: {0}".format(iso_value))
print("Exposure mode: {0}".format(exposure_mode))
print("Light source: {0}".format(light_source))
print("Softwawre = {0}".format(software))
def printExifInfo(file_name):
exif = get_exif(file_name)
labeled = get_labeled_exif(exif)
print("EXIF: {0}\n\n".format(labeled))
if labeled['Make'].upper()=="FUJIFILM":
printFujifilmExif(labeled)
else:
printCanonExif(labeled)
print("****Printing Fujifilm profile****")
printExifInfo('DSCF3846_Lowres.jpg')
Sample output
Printing Fujifilm profile* EXIF: {'ResolutionUnit': 2, 'ExifOffset': 446, 'Make': 'FUJIFILM', 'Model': 'GFX 50S', 'Software': 'GIMP 2.10.18', 'DateTime': '2021:05:14 22:58:13', 'Copyright': '
', 'XResolution': 72.0, 'YResolution': 72.0, 'ExifVersion': b'0230', 'ShutterSpeedValue': 8.965784, 'ApertureValue': 4.970854, 'DateTimeOriginal': '2021:05:14 15:51:42', 'DateTimeDigitized': '2021:05:14 15:51:42', 'BrightnessValue': 9.94, 'ExposureBiasValue': 0.0, 'MaxApertureValue': 5.0, 'MeteringMode': 5, 'LightSource': 1, 'Flash': 0, 'FocalLength': 196.5, 'ColorSpace': 1, 'ExifImageWidth': 7333, 'FocalPlaneXResolution': 914.0, 'FocalPlaneYResolution': 914.0, 'ExifImageHeight': 5500, 'FocalPlaneResolutionUnit': 3, 'Sharpness': 0, 'SubjectDistanceRange': 0, 'SensingMethod': 2, 'FileSource': b'\x03', 'ExposureTime': 0.002, 'FNumber': 5.6, 'SceneType': b'\x01', 'ExposureProgram': 1, 'CustomRendered': 0, 'ISOSpeedRatings': 100, 'ExposureMode': 1, 'SensitivityType': 1, 'StandardOutputSensitivity': 100, 'WhiteBalance': 1, 'BodySerialNumber': '72012151', 'LensSpecification': (196.5, 196.5, 5.656854256854257, 5.656854256854257), 'LensMake': 'FUJIFILM', 'LensModel': 'GF100-200mmF5.6 R LM OIS WR', 'LensSerialNumber': '88A10682', 'FocalLengthIn35mmFilm': 155, 'SceneCaptureType': 0}shutter_speed = 0.002, type = <class 'PIL.TiffImagePlugin.IFDRational'> The shutter speed is not a list shutter speed value: 0.002, type <class 'PIL.TiffImagePlugin.IFDRational'> get_shutter_speed:: ss_val1 = 0.002, ss = 1/500s aperture = 5.6, type(aperture) = <class 'PIL.TiffImagePlugin.IFDRational'> get_aperture:: ap_val1 = 0.0, ap_val2 = 0.0, aperture = 5.6
PRINTING PROFILE FOR FUJIFILM*** Camera Make: FUJIFILM Camera Model: GFX 50S Lens Make: FUJIFILM Lens Model: GF100-200mmF5.6 R LM OIS WR Date taken: 2021-05-14 15:51:42 Aperture: f/5.6 Shutter speed: 1/500s ISO: 100 Exposure mode: Manual Light source: Daylight Software = GIMP 2.10.18
Upvotes: 0
Reputation: 466
Thanks to @Mark Serchells answer, I found that the description is no EXIF data but IPTC data (exiftool
shows all the fields).
In Python I now can use IPTCInfo3: https://pypi.org/project/IPTCInfo3/ and extract the description via:
info = IPTCInfo('img.jpg')
info['caption/abstract']
Which prints:
b'Gel\xe4ndewagen auf den Salzformationen im Salzsee Ass-Ale in der Danakil-Senke, Danakil-Senke, Hamed Ela, Wollo, \xc4thiopien, Afrika
Upvotes: 3
Reputation: 208107
In general, there are a number of places where the metadata might be hiding and a few techniques you could use to look for it. I'll write a few words about each in a different section of my answer.
The data you seek could be in the "extended attributes" of your file, or xattr
. You can see this if you run the following in Terminal:
ls -l image.jpg
-rw-r--r--@ 1 mark staff 214557 2 Jan 15:47 image.jpg
and any files with "extended attributes" will have @
after their permissions. You can then see the extended attributes with:
ls -@l image.jpg
-rw-r--r--@ 1 mark staff 2219100 3 Jan 18:07 image.jpg
com.apple.lastuseddate#PS 16
com.apple.quarantine 22
See manual page with man xattr
.
The data could be in the EXIF
section of your file. The best tool for EXIF data is exiftool
, so try:
exiftool -v -v image.jpg
You can install exiftool
on macOS with homebrew using:
brew install exiftool
Apple does all sorts of indexing when you create files on a Mac, so the data could be in the metadata database. You can check with mdls
like this:
mdls image.jpg
Sample Output
_kMDItemDisplayNameWithExtensions = "image.jpg"
kMDItemAcquisitionMake = "Apple"
kMDItemAcquisitionModel = "iPhone 4"
kMDItemAltitude = 1.128681019549616
kMDItemAperture = 2.970853573907009
kMDItemBitsPerSample = 32
kMDItemColorSpace = "RGB"
kMDItemContentCreationDate = 2013-03-09 08:59:50 +0000
kMDItemContentCreationDate_Ranking = 2013-03-09 00:00:00 +0000
kMDItemContentModificationDate = 2013-03-09 08:59:50 +0000
kMDItemContentModificationDate_Ranking = 2013-03-09 00:00:00 +0000
kMDItemContentType = "public.jpeg"
kMDItemContentTypeTree = (
"public.jpeg",
"public.image",
"public.data",
"public.item",
"public.content"
)
kMDItemCreator = "6.1.2"
kMDItemDateAdded = 2021-01-03 18:07:34 +0000
kMDItemDateAdded_Ranking = 2021-01-03 00:00:00 +0000
kMDItemDisplayName = "image.jpg"
kMDItemDocumentIdentifier = 0
kMDItemEXIFVersion = "2.2.1"
kMDItemExposureMode = 0
kMDItemExposureProgram = 2
kMDItemExposureTimeSeconds = 0.001094091903719912
kMDItemFlashOnOff = 0
kMDItemFNumber = 2.8
kMDItemFocalLength = 3.85
kMDItemFocalLength35mm = 35
kMDItemFSContentChangeDate = 2021-01-03 18:07:34 +0000
kMDItemFSCreationDate = 2021-01-03 18:07:34 +0000
kMDItemFSCreatorCode = ""
kMDItemFSFinderFlags = 0
kMDItemFSHasCustomIcon = (null)
kMDItemFSInvisible = 0
kMDItemFSIsExtensionHidden = 0
kMDItemFSIsStationery = (null)
kMDItemFSLabel = 0
kMDItemFSName = "image.jpg"
kMDItemFSNodeCount = (null)
kMDItemFSOwnerGroupID = 20
kMDItemFSOwnerUserID = 501
kMDItemFSSize = 2219100
kMDItemFSTypeCode = ""
kMDItemGPSDateStamp = "2013:03:09"
kMDItemHasAlphaChannel = 0
kMDItemImageDirection = 324.4435483870968
kMDItemInterestingDate_Ranking = 2019-08-27 00:00:00 +0000
kMDItemISOSpeed = 80
kMDItemKind = "JPEG image"
kMDItemLastUsedDate = 2019-08-27 14:26:14 +0000
kMDItemLastUsedDate_Ranking = 2019-08-27 00:00:00 +0000
kMDItemLatitude = 20.84433333333333
kMDItemLogicalSize = 2219100
kMDItemLongitude = 107.091
kMDItemMeteringMode = 5
kMDItemOrientation = 0
kMDItemPhysicalSize = 2220032
kMDItemPixelCount = 5018112
kMDItemPixelHeight = 1936
kMDItemPixelWidth = 2592
kMDItemProfileName = "sRGB IEC61966-2.1"
kMDItemRedEyeOnOff = 0
kMDItemResolutionHeightDPI = 72
kMDItemResolutionWidthDPI = 72
kMDItemTimestamp = "01:59:48"
kMDItemUseCount = 1
kMDItemUsedDates = (
"2019-08-26 23:00:00 +0000"
)
kMDItemWhiteBalance = 0
You could try an old-fashioned "brute-force" approach. The strings
utility hunts through any binary file looking for anything that looks like text, so you could try extracting anything that looks like a bunch of letters and searching for a relatively rare word - in your example I would choose Wollo
, so you might do this to see if the string Wollo
actually exists in your file - else it may be elsewhere:
strings image.jpg | grep "Wollo"
Upvotes: 1