{"id":67,"date":"2018-07-04T09:36:52","date_gmt":"2018-07-04T13:36:52","guid":{"rendered":"http:\/\/bhoey.com\/blog\/?p=67"},"modified":"2020-06-19T22:24:29","modified_gmt":"2020-06-20T02:24:29","slug":"extracting-raw-photo-exif-data-with-python","status":"publish","type":"post","link":"https:\/\/bhoey.com\/blog\/extracting-raw-photo-exif-data-with-python\/","title":{"rendered":"Extracting RAW Photo Exif Data With Python"},"content":{"rendered":"<h3>Background<\/h3>\n<p>I've always enjoyed taking pictures. Before smartphones put a camera in everyone's pocket, I would use whatever (usually cheap) camera was handy. More recently I decided to get more into taking \"real photographs\" instead of just pictures. As anyone will tell you taking the dive into photography, there is much more complexity than you would normally expect, particularly when compared to point-and-shoot or smartphone cameras. As part of the journey, you will inevitably need to work with RAW image files. While RAW files provide much more information to work with, you may find support for different manufacturers RAW format lacking in tools and libraries that you may have used in the past. This post briefly covers extracting Exif metadata from most RAW file formats with python.<\/p>\n<h3>pyexiv2<\/h3>\n<p>We will be using pyexiv2\/py3exiv2 for this example, which are python wrappers around the exiv2 C++ library that does the actual image file processing.<\/p>\n<ul>\n<li>pyexiv2 is the python 2.x version of the library<\/li>\n<li>py3exiv2 is the python 3.x version<\/li>\n<\/ul>\n<p>The code snippet below will work with with either pyexiv2 or py3exiv2.<\/p>\n<h3>Setup<\/h3>\n<h4>Python 3: py3exiv2<\/h4>\n<p>For Python 3.x, since the py3exiv2 isn't available from apt, you'll need to build it locally. To do this you'll need to install some prerequisites:<\/p>\n<pre class=\"brush: plain; notranslate\">apt-get install \\\n        libboost-python-dev \\\n        libexiv2-dev \\\n        python3-pip\n<\/pre>\n<p>Then use pip3 to download, build and install py3exiv2:<\/p>\n<pre class=\"brush: plain; notranslate\">pip3 install py3exiv2\n<\/pre>\n<h4>Python 2: pyexiv2<\/h4>\n<p>For Python 2.x, the current Debian stable as of this writing (Debian 10 Buster) and current Ubuntu LTS (18.04) already include pyexiv2 in their respective package repositories, you only need to run:<\/p>\n<pre class=\"brush: plain; notranslate\">apt-get install python-pyexiv2\n<\/pre>\n<h3>exiv2_demo.py<\/h3>\n<p>The following code snippet will:<\/p>\n<ul>\n<li>Read a file given on the command line<\/li>\n<li>Print all Exif tags found in the file<\/li>\n<li>Print a specific tag value<\/li>\n<\/ul>\n<h4>Code<\/h4>\n<pre class=\"brush: python; notranslate\">#!\/usr\/bin\/env python3\n\n# usage: exiv2_demo.py &lt;file&gt;\n\nimport sys\nimport pyexiv2\n\nfile = sys.argv[1]\n\nmd = pyexiv2.ImageMetadata(file)\nmd.read()\n\n# print all exif tags in file\nfor m in md.exif_keys:\n    print(m + \"=\" + str(md[m]))\n\n# print specific tag \naperture = float(md['Exif.Photo.FNumber'].value)\nprint(\"Aperture: F{}\".format(aperture))\n<\/pre>\n<p><b>Note 1<\/b>: One thing to keep in mind is that different Exif keys will return different value types. For example Exif.Photo.FNumber returns a Rational type which was converted above to float to print how aperture is commonly expressed. The 'Exif metadata reference tables' link in the References section has a list of tags and their respective types<\/p>\n<p><b>Note 2<\/b>: Different RAW file formats (.ARW, .CR2, .NEF, etc) will often have a different set of Exif tags, particularly for lesser used\/uncommon ones (for example Exif.Photo.LensModel).<\/p>\n<h4>Example Run<\/h4>\n<pre class=\"brush: plain; notranslate\">$ .\/exiv2_demo.py test.sony.ARW\n\nExif.Photo.ExposureTime=&lt;Exif.Photo.ExposureTime [Rational] = 1\/125&gt;\nExif.Photo.FNumber=&lt;Exif.Photo.FNumber [Rational] = 40\/10&gt;\n...\nExif.Photo.ISOSpeedRatings=&lt;Exif.Photo.ISOSpeedRatings [Short] = 1600&gt;\nAperture: F4.0\n<\/pre>\n<h4>Dockerfile<\/h4>\n<p>If you'd like to experiment in a Docker sandbox, the following Dockerfile will spin up a docker container with py3exiv2 and run the script:<\/p>\n<pre class=\"brush: plain; notranslate\">FROM python:3.8-buster\n\nRUN apt-get update &amp;&amp; \\\n    apt-get install -y \\\n        libboost-python-dev \\\n        libexiv2-dev \\\n        python3-pip\n\nCOPY \\\n    exiv2_demo.py \\\n    test.sony.ARW \\\n    .\/\n\nRUN pip3 install py3exiv2\n\nCMD [ \"python3\", \".\/exiv2_demo.py\", \"test.sony.ARW\" ]\n<\/pre>\n<h3>References<\/h3>\n<ol>\n<li>Exiv2 project: <a href=\"http:\/\/www.exiv2.org\/\">http:\/\/www.exiv2.org\/<\/a><\/li>\n<li>py3exiv2 project: <a href=\"https:\/\/launchpad.net\/py3exiv2\">https:\/\/launchpad.net\/py3exiv2<\/a><\/li>\n<li>EXIF metadata reference tables: <a href=\"http:\/\/www.exiv2.org\/tags.html\">http:\/\/www.exiv2.org\/tags.html<\/a><\/li>\n<li>EXIF tag value chart:<a href=\"https:\/\/www.sno.phy.queensu.ca\/~phil\/exiftool\/TagNames\/EXIF.html\"> https:\/\/www.sno.phy.queensu.ca\/~phil\/exiftool\/TagNames\/EXIF.html<\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>While RAW files provide much more information to work with, you may find support for different manufacturers RAW format lacking in tools and libraries that you may have used in the past. This post briefly covers extracting Exif metadata from most RAW file formats with python.&nbsp;<a href=\"https:\/\/bhoey.com\/blog\/extracting-raw-photo-exif-data-with-python\/\">[Continue&nbsp;reading...] <span class=\"screen-reader-text\">Extracting RAW Photo Exif Data With Python<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":797,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[33,23],"tags":[26,27,25,30,28,29,32,31,24],"_links":{"self":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/67"}],"collection":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":35,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":799,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions\/799"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/media\/797"}],"wp:attachment":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}