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

Better struct module usage #128

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
144 changes: 55 additions & 89 deletions piexif/_load.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import struct
import sys
from struct import unpack_from

from ._common import *
from ._exceptions import InvalidImageDataError
Expand Down Expand Up @@ -34,8 +34,8 @@ def load(input_data, key_is_name=False):
else:
exifReader.endian_mark = ">"

pointer = struct.unpack(exifReader.endian_mark + "L",
exifReader.tiftag[4:8])[0]
pointer = unpack_from(exifReader.endian_mark + "L",
exifReader.tiftag, 4)[0]
exif_dict["0th"] = exifReader.get_ifd_dict(pointer, "0th")
first_ifd_pointer = exif_dict["0th"].pop("first_ifd_pointer")
if ImageIFD.ExifTag in exif_dict["0th"]:
Expand All @@ -48,8 +48,8 @@ def load(input_data, key_is_name=False):
pointer = exif_dict["Exif"][ExifIFD.InteroperabilityTag]
exif_dict["Interop"] = exifReader.get_ifd_dict(pointer, "Interop")
if first_ifd_pointer != b"\x00\x00\x00\x00":
pointer = struct.unpack(exifReader.endian_mark + "L",
first_ifd_pointer)[0]
pointer = unpack_from(exifReader.endian_mark + "L",
first_ifd_pointer)[0]
exif_dict["1st"] = exifReader.get_ifd_dict(pointer, "1st")
if (ImageIFD.JPEGInterchangeFormat in exif_dict["1st"] and
ImageIFD.JPEGInterchangeFormatLength in exif_dict["1st"]):
Expand Down Expand Up @@ -105,32 +105,25 @@ def __init__(self, data):

def get_ifd_dict(self, pointer, ifd_name, read_unknown=False):
ifd_dict = {}
tag_count = struct.unpack(self.endian_mark + "H",
self.tiftag[pointer: pointer+2])[0]
tag_count = unpack_from(self.endian_mark + "H",
self.tiftag, pointer)[0]
offset = pointer + 2
if ifd_name in ["0th", "1st"]:
t = "Image"
else:
t = ifd_name
p_and_value = []
for x in range(tag_count):
pointer = offset + 12 * x
tag = struct.unpack(self.endian_mark + "H",
self.tiftag[pointer: pointer+2])[0]
value_type = struct.unpack(self.endian_mark + "H",
self.tiftag[pointer + 2: pointer + 4])[0]
value_num = struct.unpack(self.endian_mark + "L",
self.tiftag[pointer + 4: pointer + 8]
)[0]
tag, value_type, value_num = unpack_from(
self.endian_mark + "HHL", self.tiftag, pointer)
value = self.tiftag[pointer+8: pointer+12]
p_and_value.append((pointer, value_type, value_num, value))
v_set = (value_type, value_num, value, tag)
if tag in TAGS[t]:
ifd_dict[tag] = self.convert_value(v_set)
elif read_unknown:
ifd_dict[tag] = (v_set[0], v_set[1], v_set[2], self.tiftag)
#else:
# pass
else:
pass

if ifd_name == "0th":
pointer = offset + 12 * tag_count
Expand All @@ -145,108 +138,81 @@ def convert_value(self, val):

if t == TYPES.Byte: # BYTE
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack("B" * length,
self.tiftag[pointer: pointer + length])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from("B" * length, self.tiftag, pointer)
else:
data = struct.unpack("B" * length, value[0:length])
data = unpack_from("B" * length, value)
elif t == TYPES.Ascii: # ASCII
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = self.tiftag[pointer: pointer+length - 1]
else:
data = value[0: length - 1]
elif t == TYPES.Short: # SHORT
if length > 2:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "H" * length,
self.tiftag[pointer: pointer+length*2])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "H" * length,
self.tiftag, pointer)
else:
data = struct.unpack(self.endian_mark + "H" * length,
value[0:length * 2])
data = unpack_from(self.endian_mark + "H" * length, value)
elif t == TYPES.Long: # LONG
if length > 1:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "L" * length,
self.tiftag[pointer: pointer+length*4])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "L" * length,
self.tiftag, pointer)
else:
data = struct.unpack(self.endian_mark + "L" * length,
value)
data = unpack_from(self.endian_mark + "L" * length, value)
elif t == TYPES.Rational: # RATIONAL
pointer = struct.unpack(self.endian_mark + "L", value)[0]
if length > 1:
data = tuple(
(struct.unpack(self.endian_mark + "L",
self.tiftag[pointer + x * 8:
pointer + 4 + x * 8])[0],
struct.unpack(self.endian_mark + "L",
self.tiftag[pointer + 4 + x * 8:
pointer + 8 + x * 8])[0])
for x in range(length)
)
else:
data = (struct.unpack(self.endian_mark + "L",
self.tiftag[pointer: pointer + 4])[0],
struct.unpack(self.endian_mark + "L",
self.tiftag[pointer + 4: pointer + 8]
)[0])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = tuple(
unpack_from(self.endian_mark + "LL",
self.tiftag, pointer + x * 8)
for x in range(length)
)
elif t == TYPES.SByte: # SIGNED BYTES
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack("b" * length,
self.tiftag[pointer: pointer + length])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from("b" * length, self.tiftag, pointer)
else:
data = struct.unpack("b" * length, value[0:length])
data = unpack_from("b" * length, value)
elif t == TYPES.Undefined: # UNDEFINED BYTES
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = self.tiftag[pointer: pointer+length]
else:
data = value[0:length]
data = value[0: length]
elif t == TYPES.SShort: # SIGNED SHORT
if length > 2:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "h" * length,
self.tiftag[pointer: pointer+length*2])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "h" * length,
self.tiftag, pointer)
else:
data = struct.unpack(self.endian_mark + "h" * length,
value[0:length * 2])
data = unpack_from(self.endian_mark + "h" * length, value)
elif t == TYPES.SLong: # SLONG
if length > 1:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "l" * length,
self.tiftag[pointer: pointer+length*4])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "l" * length,
self.tiftag, pointer)
else:
data = struct.unpack(self.endian_mark + "l" * length,
value)
data = unpack_from(self.endian_mark + "l" * length, value)
elif t == TYPES.SRational: # SRATIONAL
pointer = struct.unpack(self.endian_mark + "L", value)[0]
if length > 1:
data = tuple(
(struct.unpack(self.endian_mark + "l",
self.tiftag[pointer + x * 8: pointer + 4 + x * 8])[0],
struct.unpack(self.endian_mark + "l",
self.tiftag[pointer + 4 + x * 8: pointer + 8 + x * 8])[0])
for x in range(length)
)
else:
data = (struct.unpack(self.endian_mark + "l",
self.tiftag[pointer: pointer + 4])[0],
struct.unpack(self.endian_mark + "l",
self.tiftag[pointer + 4: pointer + 8]
)[0])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = tuple(
unpack_from(self.endian_mark + "ll",
self.tiftag, pointer + x * 8)
for x in range(length)
)
elif t == TYPES.Float: # FLOAT
if length > 1:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "f" * length,
self.tiftag[pointer: pointer+length*4])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "f" * length,
self.tiftag, pointer)
else:
data = struct.unpack(self.endian_mark + "f" * length,
value)
data = unpack_from(self.endian_mark + "f" * length, value)
elif t == TYPES.DFloat: # DOUBLE
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = struct.unpack(self.endian_mark + "d" * length,
self.tiftag[pointer: pointer+length*8])
pointer = unpack_from(self.endian_mark + "L", value)[0]
data = unpack_from(self.endian_mark + "d" * length,
self.tiftag, pointer)
else:
raise ValueError("Exif might be wrong. Got incorrect value " +
"type to decode.\n" +
Expand Down