Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load JPEG files independent of suffix #25

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 17 additions & 23 deletions piexif/_load.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import struct

from ._common import *
from ._exif import *


LITTLE_ENDIAN = b"\x49\x49"


def load(input_data):
def load(input_data, byte_data=False):
"""
py:function:: piexif.load(filename)

Expand All @@ -17,13 +16,22 @@ def load(input_data):
:return: Exif data({"0th":dict, "Exif":dict, "GPS":dict, "Interop":dict, "1st":dict, "thumbnail":bytes})
:rtype: dict
"""
exif_dict = {"0th":{},
"Exif":{},
"GPS":{},
"Interop":{},
"1st":{},
"thumbnail":None}
exifReader = _ExifReader(input_data)
exif_dict = {"0th": {},
"Exif": {},
"GPS": {},
"Interop": {},
"1st": {},
"thumbnail": None}
# this is just a hack to make it work.
# The load function (IMHO) has to be redesigned because it has to deal with
# incoming bytes and strings (filenames)
if byte_data:
data = input_data
else:
with open(input_data, 'rb') as f:
data = f.read()

exifReader = _ExifReader(data)
if exifReader.tiftag is None:
return exif_dict

Expand Down Expand Up @@ -71,20 +79,6 @@ def __init__(self, data):
self.tiftag = data
elif data[0:4] == b"Exif": # Exif
self.tiftag = data[6:]
elif data[-4:].lower() in (".jpg", "jpeg", ".jpe", ".tif", "tiff"):
with open(data, 'rb') as f:
data = f.read()
if data[0:2] == b"\xff\xd8": # JPEG
segments = split_into_segments(data)
app1 = get_exif_seg(segments)
if app1:
self.tiftag = app1[10:]
else:
self.tiftag = None
elif data[0:2] in (b"\x49\x49", b"\x4d4d"): # TIFF
self.tiftag = data
else:
raise ValueError("Given file is neither JPEG nor TIFF.")
else:
raise ValueError("Given file is neither JPEG nor TIFF.")

Expand Down
Binary file added tests/images/02.docx
Binary file not shown.
47 changes: 29 additions & 18 deletions tests/s_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
INPUT_FILE2 = os.path.join("tests", "images", "02.jpg")
INPUT_FILE_PEN = os.path.join("tests", "images", "r_pen.jpg")
NOEXIF_FILE = os.path.join("tests", "images", "noexif.jpg")
NODOCX_FILE = os.path.join("tests", "images", "02.docx")
# JPEG without APP0 and APP1 segments
NOAPP01_FILE = os.path.join("tests", "images", "noapp01.jpg")
INPUT_FILE_TIF = os.path.join("tests", "images", "01.tif")
Expand Down Expand Up @@ -89,14 +90,23 @@ class ExifTests(unittest.TestCase):
# load ------
def test_no_exif_load(self):
exif_dict = piexif.load(NOEXIF_FILE)
none_dict = {"0th":{},
"Exif":{},
"GPS":{},
"Interop":{},
"1st":{},
"thumbnail":None}
none_dict = {"0th": {},
"Exif": {},
"GPS": {},
"Interop": {},
"1st": {},
"thumbnail": None}
self.assertEqual(exif_dict, none_dict)

def test_jpg_in_docx_load(self):
"""
Loads an Image with jpg suffix and a copy with docx suffix and compares
exif data.
"""
exif_dict_docx = piexif.load(NODOCX_FILE)
exif_dict_jpg = piexif.load(INPUT_FILE2)
self.assertEqual(exif_dict_docx, exif_dict_jpg)

def test_load(self):
files = glob.glob(os.path.join("tests", "images", "r_*.jpg"))
for input_file in files:
Expand All @@ -108,11 +118,12 @@ def test_load(self):
def test_load_m(self):
"""'load' on memory.
"""
exif = piexif.load(I1)
exif = piexif.load(I1, True)
e = load_exif_by_PIL(INPUT_FILE1)
print("********************\n\n" + INPUT_FILE1 + "\n")
self._compare_piexifDict_PILDict(exif, e)


def test_load_tif(self):
exif = piexif.load(INPUT_FILE_TIF)
zeroth_ifd = exif["0th"]
Expand All @@ -122,22 +133,22 @@ def test_load_tif(self):
o = io.BytesIO()
im.save(o, format="jpeg", exif=exif_bytes)
im.close()
exif2 = piexif.load(o.getvalue())
exif2 = piexif.load(o.getvalue(), True)
zeroth_ifd2 = exif2["0th"]
self.assertDictEqual(zeroth_ifd, zeroth_ifd2)

def test_load_tif_m(self):
with open(INPUT_FILE_TIF, "rb") as f:
tif = f.read()
exif = piexif.load(tif)
exif = piexif.load(tif, True)
zeroth_ifd = exif["0th"]
exif_bytes = piexif.dump({"0th":zeroth_ifd})

im = Image.new("RGBA", (8, 8))
o = io.BytesIO()
im.save(o, format="jpeg", exif=exif_bytes)
im.close()
exif2 = piexif.load(o.getvalue())
exif2 = piexif.load(o.getvalue(), True)
zeroth_ifd2 = exif2["0th"]
self.assertDictEqual(zeroth_ifd, zeroth_ifd2)

Expand All @@ -148,14 +159,14 @@ def test_load_fail(self):
with self.assertRaises(ValueError):
exif = piexif.load(os.path.join("tests", "images", "notjpeg.jpg"))

with self.assertRaises(ValueError):
with self.assertRaises(IOError):
exif = piexif.load("foo")

def test_load_from_pilImage_property(self):
o = io.BytesIO()
i = Image.open(INPUT_FILE1)
exif = i.info["exif"]
exif_dict = piexif.load(exif)
exif_dict = piexif.load(exif, True)
exif_bytes = piexif.dump(exif_dict)
i.save(o, "jpeg", exif=exif_bytes)
i.close()
Expand Down Expand Up @@ -226,7 +237,7 @@ def test_dump_and_load(self):
im.save(o, format="jpeg", exif=exif_bytes)
im.close()
o.seek(0)
exif = piexif.load(o.getvalue())
exif = piexif.load(o.getvalue(), True)
zeroth_ifd, exif_ifd, gps_ifd = exif["0th"], exif["Exif"], exif["GPS"]
zeroth_ifd.pop(ImageIFD.ExifTag) # pointer to exif IFD
zeroth_ifd.pop(ImageIFD.GPSTag) # pointer to GPS IFD
Expand Down Expand Up @@ -254,7 +265,7 @@ def test_dump_and_load2(self):
im.save(o, format="jpeg", exif=exif_bytes)
im.close()
o.seek(0)
exif = piexif.load(o.getvalue())
exif = piexif.load(o.getvalue(), True)
exif["0th"].pop(ImageIFD.ExifTag) # pointer to exif IFD
exif["0th"].pop(ImageIFD.GPSTag) # pointer to GPS IFD
exif["Exif"].pop(ExifIFD.InteroperabilityTag)
Expand Down Expand Up @@ -309,7 +320,7 @@ def test_dump_and_load3(self):
"Exif":{ExifIFD.ISOSpeed:long_v[x]},
"GPS":{GPSIFD.GPSVersionID:byte_v[x]},}
exif_bytes = piexif.dump(exif_dict)
e = piexif.load(exif_bytes)
e = piexif.load(exif_bytes, True)
self.assertEqual(
e["0th"][ImageIFD.ProcessingSoftware].decode("latin1"),
ascii_v[x])
Expand All @@ -330,7 +341,7 @@ def test_roundtrip_files(self):
exif_bytes = piexif.dump(exif)
o = io.BytesIO()
piexif.insert(exif_bytes, input_file, o)
e = piexif.load(o.getvalue())
e = piexif.load(o.getvalue(), True)

t = e.pop("thumbnail")
thumbnail = exif.pop("thumbnail")
Expand Down Expand Up @@ -383,7 +394,7 @@ def test_transplant_m(self):
"""
o = io.BytesIO()
piexif.transplant(I1, I2, o)
self.assertEqual(piexif.load(I1), piexif.load(o.getvalue()))
self.assertEqual(piexif.load(I1, True), piexif.load(o.getvalue(), True))
Image.open(o).close()

def test_transplant_fail1(self):
Expand Down Expand Up @@ -434,7 +445,7 @@ def test_remove_m(self):
with self.assertRaises(ValueError):
piexif.remove(I1)
piexif.remove(I1, o)
exif_dict = piexif.load(o.getvalue())
exif_dict = piexif.load(o.getvalue(), True)
none_dict = {"0th":{},
"Exif":{},
"GPS":{},
Expand Down