使用PIL获取从EXIF数据拍摄照片的日期和时间

时间:2014-04-14 15:50:30

标签: python python-imaging-library exif

我可以get the EXIF data from an image使用PIL,但我怎样才能获得拍摄照片的日期和时间?

7 个答案:

答案 0 :(得分:38)

最终找到了答案,我需要的标签是36867

from PIL import Image
def get_date_taken(path):
    return Image.open(path)._getexif()[36867]

答案 1 :(得分:11)

我喜欢使用<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:background="#283341" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_startup" tools:context=".StartupActivity"> <ImageView android:id="@+id/startupImg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_marginTop="150dp" android:layout_centerInParent="true" android:src="@drawable/q_orange" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:layout_marginBottom="30dp"> <ProgressBar android:id="@+id/loadingSpinner" style="?android:attr/progressBarStyleSmall" android:layout_centerInParent="true" android:layout_width="33dp" android:layout_height="33dp" android:visibility="visible" android:indeterminate="true" /> <TextView android:id="@+id/startupStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Loading..." android:textColor="#ff8a07" android:textSize="25sp" /> </LinearLayout> </RelativeLayout> ,因为它是纯python,不需要编译/安装,并且兼容python 2.x和3.x,非常适合捆绑小型便携式python应用

链接: https://github.com/ianare/exif-py

获取照片拍摄日期和时间的示例:

exif-py

答案 2 :(得分:5)

ExifTags.TAGS是从标记到标记名称的映射。您可以使用它来创建标记名称到值的映射。

在这张特定图片上,可以使用几种不同的“日期”属性(DateTimeDateTimeOriginalDateTimeDigitized)。

import json
from PIL import Image, ExifTags
from datetime import datetime

def main(filename):
    image_exif = Image.open(filename)._getexif()
    if image_exif:
        # Make a map with tag names
        exif = { ExifTags.TAGS[k]: v for k, v in image_exif.items() if k in ExifTags.TAGS and type(v) is not bytes }
        print(json.dumps(exif, indent=4))
        # Grab the date
        date_obj = datetime.strptime(exif['DateTimeOriginal'], '%Y:%m:%d %H:%M:%S')
        print(date_obj)
    else:
        print('Unable to get date from exif for %s' % filename)

输出:

{
    "DateTimeOriginal": "2008:11:15 19:36:24",
    "DateTimeDigitized": "2008:11:15 19:36:24",
    "ColorSpace": 1,
    "ExifImageWidth": 3088,
    "SceneCaptureType": 0,
    "ExifImageHeight": 2320,
    "SubjectDistanceRange": 2,
    "ImageDescription": "               ",
    "Make": "Hewlett-Packard                ",
    "Model": "HP Photosmart R740             ",
    "Orientation": 1,
    "DateTime": "2008:11:15 19:36:24",
    ...
}
2008-11-15 19:36:24

答案 3 :(得分:3)

try:
    import PIL
    import PIL.Image as PILimage
    from PIL import ImageDraw, ImageFont, ImageEnhance
    from PIL.ExifTags import TAGS, GPSTAGS
except ImportError as err:
    exit(err)


class Worker(object):
    def __init__(self, img):
        self.img = img
        self.get_exif_data()
        self.date =self.get_date_time()
        super(Worker, self).__init__()

    def get_exif_data(self):
        exif_data = {}
        info = self.img._getexif()
        if info:
            for tag, value in info.items():
                decoded = TAGS.get(tag, tag)
                if decoded == "GPSInfo":
                    gps_data = {}
                    for t in value:
                        sub_decoded = GPSTAGS.get(t, t)
                        gps_data[sub_decoded] = value[t]

                    exif_data[decoded] = gps_data
                else:
                    exif_data[decoded] = value
        self.exif_data = exif_data
        # return exif_data 

    def get_date_time(self):
        if 'DateTime' in self.exif_data:
            date_and_time = self.exif_data['DateTime']
            return date_and_time 


def main():
    date = image.date
    print(date)

if __name__ == '__main__':
    try:
        img = PILimage.open(path + filename)
        image = Worker(img)
        date = image.date
        print(date)

    except Exception as e:
        print(e)

答案 4 :(得分:1)

在较新版本的Pillow(我认为6.0+)中,这一点已发生了轻微变化。

他们添加了您应该使用的公共方法getexif()。先前的版本是私有的和实验性的(_getexif())。

from PIL import Image

im = Image.open('path/to/image.jpg')
exif = im.getexif()
creation_time = exif.get(36867)

答案 5 :(得分:1)

我创建了一个函数(get_exif),可以更轻松地获取属性。

用法

your_date_time: str = get_exif(Path('test.jpg'), 'DateTimeOriginal')
# your_date_time = get_exif(Path('test.jpg'), 0x9003)  # same as above

get_exif

from pathlib import Path
from typing import Union, List, Tuple
import PIL.Image
import PIL.ExifTags


def get_exif(file_path: Path,
             search_list: Union[int, str, List, Tuple] = None,
             ignore_error=True
             ) -> Union[int, PIL.Image.Exif, List]:
    """
    :param file_path: image path
    :param search_list: if you want to get some property, then you can pass the id or name, it will return by order.
    :param ignore_error:
    :return:
        int: -1 FileNotFoundError, or exif is None
        PIL.Image.Exif: when the `search_list` is None, return the whole Exif
    """
    tag_by_id: dict = PIL.ExifTags.TAGS
    try:
        im: PIL.Image.Image = PIL.Image.open(str(file_path))
    except FileNotFoundError:
        if ignore_error:
            return -1
        else:
            raise FileNotFoundError(file_path)
    exif: PIL.Image.Exif = im.getexif()
    if not exif:
        if ignore_error:
            return -1
        else:
            raise ValueError("exif is None")
    if search_list is None:
        return exif
    tag_by_name = {tag_by_id[dec_value]: exif[dec_value] for dec_value in exif if dec_value in tag_by_id}
    result_list = []
    if not isinstance(search_list, (list, tuple)):
        search_list = [search_list]
    for key in search_list:
        if isinstance(key, int):
            result_list.append(exif.get(key, None))
            continue
        try:
            dec_value = int(key, 16)
            result_list.append(exif.get(dec_value, None))
            continue
        except ValueError:
            ...
        result_list.append(tag_by_name.get(key, None))
    return result_list if len(result_list) > 1 else result_list[0]

更多测试

import unittest

class ExifTests(unittest.TestCase):
    def test(self):
        exif: PIL.Image.Exif = get_exif(Path('test.jpg'))  # same as the ``PIL.Image.open().getexif()``

        # get specify attribute only
        date_t_ori1 = get_exif(Path('test.jpg'), 0x9003)
        date_t_ori2 = get_exif(Path('test.jpg'), '0x9003', )  # hex string is ok too.
        date_t_ori3 = get_exif(Path('test.jpg'), 'DateTimeOriginal')  # Give name is also working.
        self.assertTrue(date_t_ori1 == date_t_ori2 == date_t_ori3)

        # You can get multiple values at once. If the key does not exist, it returns None.
        date_t_ori4, img_length, _, __ = get_exif(Path('test.jpg'),
                                                  (36867, 'ImageLength', 'NoteExitName', -12345))

        # Occurring error return -1 (by default ignore_error=True)
        self.assertEqual(-1, get_exif(Path('not exist.jpg')))  # FileNotFoundError
        self.assertEqual(-1, get_exif(Path('no_exif_tag.jpg')))  # ValueError

        self.assertRaises(FileNotFoundError, get_exif, Path('not exist.jpg'), ignore_error=False)
        self.assertRaises(ValueError, get_exif, Path('no_exif_tag.jpg'), ignore_error=False)

注意

这个website很好,但是如果要获取完整列表,则应该引用PIL.ExifTags.py,请参见下文,

# ExifTags.py

# Maps EXIF tags to tag names.

TAGS = {
    # possibly incomplete
    0x000B: "ProcessingSoftware",
    0x00FE: "NewSubfileType",
    0x00FF: "SubfileType",
    0x0100: "ImageWidth",
    0x0101: "ImageLength",
    0x0102: "BitsPerSample",
    ...
    0xA430: "CameraOwnerName",  # <-- The website does not record it. (The website record last tag is A420.)
    0xA431: "BodySerialNumber",
    0xA432: "LensSpecification",
    0xA433: "LensMake",
    0xA434: "LensModel",
}


# Maps EXIF GPS tags to tag names.

GPSTAGS = {
    0: "GPSVersionID",
    1: "GPSLatitudeRef",
    2: "GPSLatitude",
    3: "GPSLongitudeRef",
    4: "GPSLongitude",
    5: "GPSAltitudeRef",
    6: "GPSAltitude",
    7: "GPSTimeStamp",
    ...
}

答案 6 :(得分:0)

从_getexif()返回的词典使用键&#39; DateTimeOriginal&#39;?