Skip to content

Commit

Permalink
Add support of Python3
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelometal committed Sep 18, 2017
1 parent 3aa77d3 commit 02f6de5
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 64 deletions.
68 changes: 40 additions & 28 deletions pexif.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,26 @@
E.g:
try:
print img.exif.tiff.exif.FocalLength
six.print_(img.exif.tiff.exif.FocalLength)
except AttributeError:
print "No Focal Length data"
six.print_("No Focal Length data")
"""

import StringIO
import six
import sys
from struct import unpack, pack

try:
integer_64 = long
except NameError: # Python3
integer_64 = int

MAX_HEADER_SIZE = 64 * 1024
DELIM = 0xff
EOI = 0xd9
SOI_MARKER = chr(DELIM) + '\xd8'
EOI_MARKER = chr(DELIM) + '\xd9'
SOI_MARKER = six.int2byte(DELIM) + six.b('\xd8')
EOI_MARKER = six.int2byte(DELIM) + six.b('\xd9')

TIFF_OFFSET = 6
TIFF_TAG = 0x2a
Expand All @@ -122,8 +127,8 @@ def debug(*debug_string):
DEBUG to 1."""
if DEBUG:
for each in debug_string:
print each,
print
six.print_(each),
six.print_()


class DefaultSegment:
Expand Down Expand Up @@ -160,7 +165,7 @@ def write(self, fd):
must write out any data in the segment. This shouldn't in general be
overloaded by subclasses, they should instead override the get_data()
method."""
fd.write('\xff')
fd.write(six.b('\xff'))
fd.write(pack('B', self.marker))
data = self.get_data()
fd.write(pack('>H', len(data) + 2))
Expand All @@ -180,8 +185,8 @@ def dump(self, fd):
"""This is called by JpegFile.dump() to output a human readable
representation of the segment. Subclasses should overload this to provide
extra information."""
print >> fd, " Section: [%5s] Size: %6d" % \
(jpeg_markers[self.marker][0], len(self.data))
six.print_(" Section: [%5s] Size: %6d" \
% (jpeg_markers[self.marker][0], len(self.data)), file=fd)


class StartOfScanSegment(DefaultSegment):
Expand Down Expand Up @@ -218,8 +223,8 @@ def write(self, fd):

def dump(self, fd):
"""Dump as ascii readable data to a given file object"""
print >> fd, " Section: [ SOS] Size: %6d Image data size: %6d" % \
(len(self.data), len(self.img_data))
six.print_(" Section: [ SOS] Size: %6d Image data size: %6d" % \
(len(self.data), len(self.img_data)), file=fd)


class ExifType:
Expand Down Expand Up @@ -435,9 +440,9 @@ def __init__(self, e, offset, exif_file, mode, data=None):
# raise JpegFile.InvalidFile("ASCII tag '%s' not
# NULL-terminated: %s [%s]" % (self.tags.get(tag,
# (hex(tag), 0))[0], the_data, map(ord, the_data)))
# print "ASCII tag '%s' not NULL-terminated:
# six.print_("ASCII tag '%s' not NULL-terminated:
# %s [%s]" % (self.tags.get(tag, (hex(tag), 0))[0],
# the_data, map(ord, the_data))
# the_data, map(ord, the_data)))
actual_data = the_data
elif exif_type == SHORT:
actual_data = list(unpack(e + ("H" * components), the_data))
Expand All @@ -453,7 +458,7 @@ def __init__(self, e, offset, exif_file, mode, data=None):
the_data[i*8:
i*8+8])))
else:
raise "Can't handle this"
six.raise_from("Can't handle this")

if (byte_size > 4):
debug("%s" % actual_data)
Expand Down Expand Up @@ -521,7 +526,7 @@ def getdata(self, e, offset, last=0):
for i in range(components):
actual_data += pack(e + t, *the_data[i].as_tuple())
else:
raise "Can't handle this", exif_type
raise six.raise_from("Can't handle this", exif_type)
if (byte_size) > 4:
output_data += actual_data
actual_data = pack(e + "I", data_offset)
Expand Down Expand Up @@ -549,7 +554,7 @@ def getdata(self, e, offset, last=0):

def dump(self, f, indent=""):
"""Dump the IFD file"""
print >> f, indent + "<--- %s start --->" % self.name
six.print_(indent + "<--- %s start --->" % self.name, file=f)
for entry in self.entries:
tag, exif_type, data = entry
if exif_type == ASCII:
Expand All @@ -559,9 +564,9 @@ def dump(self, f, indent=""):
else:
if data and len(data) == 1:
data = data[0]
print >> f, indent + " %-40s %s" % \
(self.tags.get(tag, (hex(tag), 0))[0], data)
print >> f, indent + "<--- %s end --->" % self.name
six.print_(indent + " %-40s %s" % \
(self.tags.get(tag, (hex(tag), 0))[0], data), file=f)
six.print_(indent + "<--- %s end --->" % self.name, file=f)


class IfdInterop(IfdData):
Expand Down Expand Up @@ -861,7 +866,10 @@ def parse_data(self, data):
"""Overloads the DefaultSegment method to parse the data of
this segment. Can raise InvalidFile if we don't get what we expect."""
exif = unpack("6s", data[:6])[0]
exif = exif.strip('\0')
try:
exif = exif.strip('\0')
except TypeError:
pass

if (exif != "Exif"):
raise self.InvalidSegment("Bad Exif Marker. Got <%s>, "
Expand Down Expand Up @@ -910,7 +918,7 @@ def parse_data(self, data):
offset = unpack(self.e + "I", tiff_data[start:start+4])[0]

def dump(self, fd):
print >> fd, " Section: [ EXIF] Size: %6d" % (len(self.data))
six.print_(" Section: [ EXIF] Size: %6d" % (len(self.data)), file=fd)
for ifd in self.ifds:
ifd.dump(fd)

Expand Down Expand Up @@ -1004,7 +1012,11 @@ def fromFile(filename, mode="rw"):

def fromString(str, mode="rw"):
"""Return a new JpegFile object taking data from a string."""
return JpegFile(StringIO.StringIO(str), "from buffer", mode=mode)
try:
str = six.b(str)
except AttributeError:
pass
return JpegFile(six.BytesIO(str), "from buffer", mode=mode)
fromString = staticmethod(fromString)

def fromFd(fd, mode="rw"):
Expand Down Expand Up @@ -1074,7 +1086,7 @@ def __init__(self, input, filename=None, mode="rw"):

def writeString(self):
"""Write the JpegFile out to a string. Returns a string."""
f = StringIO.StringIO()
f = six.BytesIO()
self.writeFd(f)
return f.getvalue()

Expand All @@ -1093,7 +1105,7 @@ def writeFd(self, output):
def dump(self, f=sys.stdout):
"""Write out ASCII representation of the file on a given file
object. Output default to stdout."""
print >> f, "<Dump of JPEG %s>" % self.filename
six.print_("<Dump of JPEG %s>" % self.filename, file=f)
for segment in self._segments:
segment.dump(f)

Expand Down Expand Up @@ -1175,8 +1187,8 @@ def convert(x):
(1/60.0 * float(min.num) / min.den) + \
(1/3600.0 * float(sec.num) / sec.den)
if not hasattr(self.exif.primary, 'GPSIFD'):
raise self.NoSection, "File %s doesn't have a GPS section." % \
self.filename
raise self.NoSection("File %s doesn't have a GPS section." % \
self.filename)

gps = self.exif.primary.GPS
lat = convert(gps.GPSLatitude)
Expand All @@ -1200,7 +1212,7 @@ def _parse(val):
other = (val - deg) * 60
minutes = int(other)
secs = (other - minutes) * 60
secs = long(secs * JpegFile.SEC_DEN)
secs = integer_64(secs * JpegFile.SEC_DEN)
return (sign, deg, minutes, secs)

_parse = staticmethod(_parse)
Expand Down
7 changes: 4 additions & 3 deletions scripts/dump_exif.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
#!/usr/bin/env python

from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: dump_exif.py filename.jpg"""

if len(sys.argv) != 2:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
ef.dump()
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
13 changes: 7 additions & 6 deletions scripts/dump_timestamp.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
#!/usr/bin/env python

from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: dump_timestamp.py filename.jpg"""

if len(sys.argv) != 2:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
primary = ef.get_exif().get_primary()
print "Primary DateTime :", primary.DateTime
print "Extended DateTimeOriginal :", primary.ExtendedEXIF.DateTimeOriginal
print "Extended DateTimeDigitized:", primary.ExtendedEXIF.DateTimeDigitized
print("Primary DateTime : {0}".format(primary.DateTime))
print("Extended DateTimeOriginal : {0}".format(primary.ExtendedEXIF.DateTimeOriginal))
print("Extended DateTimeDigitized: {0}".format(primary.ExtendedEXIF.DateTimeDigitized))
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
12 changes: 7 additions & 5 deletions scripts/getgps.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
#!/usr/bin/env python

from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: getgps.py filename.jpg"""

if len(sys.argv) != 2:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
print ef.get_geo()
print(ef.get_geo())
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
except JpegFile.NoSection:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error get GPS info:", value
print("Error get GPS info: {0}".format(value), file=sys.stderr)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)

9 changes: 5 additions & 4 deletions scripts/noop.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
#!/usr/bin/env python

from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: dump_exif.py filename.jpg out.jpg"""

if len(sys.argv) != 3:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
sys.exit(1)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
sys.exit(1)

try:
ef.writeFile(sys.argv[2])
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error saving file:", value
print("Error saving file: {0}".format(value), file=sys.stderr)
sys.exit(1)
10 changes: 6 additions & 4 deletions scripts/remove_metadata.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
#!/usr/bin/env python

from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: remove_metadata.py filename.jpg"""

if len(sys.argv) != 4:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
ef.remove_metadata(paranoid=True)
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)

try:
ef.writeFile(sys.argv[1])
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error saving file:", value
print("Error saving file: {0}".format(value), file=sys.stderr)
9 changes: 5 additions & 4 deletions scripts/setgps.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
#!/usr/bin/env python
from __future__ import print_function
from pexif import JpegFile
import sys

usage = """Usage: setgps.py filename.jpg lat lng"""

if len(sys.argv) != 4:
print >> sys.stderr, usage
print(usage, file=sys.stderr)
sys.exit(1)

try:
ef = JpegFile.fromFile(sys.argv[1])
ef.set_geo(float(sys.argv[2]), float(sys.argv[3]))
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)
except JpegFile.InvalidFile:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error opening file:", value
print("Error opening file: {0}".format(value), file=sys.stderr)

try:
ef.writeFile(sys.argv[1])
except IOError:
type, value, traceback = sys.exc_info()
print >> sys.stderr, "Error saving file:", value
print("Error saving file: {0}".format(value), file=sys.stderr)

Loading

0 comments on commit 02f6de5

Please sign in to comment.