Skip to content

Commit

Permalink
Merge pull request #41 from hMatoba/dev
Browse files Browse the repository at this point in the history
Ver 1.0.13
  • Loading branch information
hMatoba committed Sep 10, 2017
2 parents 59dd657 + 6374931 commit 9bda766
Show file tree
Hide file tree
Showing 15 changed files with 408 additions and 21 deletions.
8 changes: 8 additions & 0 deletions doc/appendices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf
+---------------+----------------------+
| BYTE | int |
+---------------+----------------------+
| SIGNED BYTE | int |
+---------------+----------------------+
| ASCII | str |
+---------------+----------------------+
| SHORT | int |
+---------------+----------------------+
| SIGNED SHORT | int |
+---------------+----------------------+
| LONG | int |
+---------------+----------------------+
| RATIONAL | (int, int) |
Expand All @@ -25,6 +29,10 @@ http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf
+---------------+----------------------+
| SRATIONAL | (int, int) |
+---------------+----------------------+
| FLOAT | float |
+---------------+----------------------+
| DOUBLE | float |
+---------------+----------------------+

If value type is number(BYTE, SHORT, LONG, RATIONAL, or SRATIONAL) and value count is two or more number, it is expressed with tuple.

Expand Down
6 changes: 6 additions & 0 deletions doc/changes.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

1.0.13
------

- Added helper function to read and write "UserComment".
- Added to support for SignedByte, SigendShort, Float, and Double.

1.0.12
------

Expand Down
38 changes: 38 additions & 0 deletions doc/helper.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
================
Helper Functions
================

UserComment
-----------
.. py:function:: piexif.helper.UserComment.load(data)
Convert "UserComment" value in exif format to str.

:param bytes data: "UserComment" value from exif
:return: u"foobar"
:rtype: str(Unicode)

::

import piexif
import piexif.helper
exif_dict = piexif.load("foo.jpg")
user_comment = piexif.helper.UserComment.load(exif_dict["Exif"][piexif.ExifIFD.UserComment])

.. py:function:: piexif.helper.UserComment.dump(data, encoding="ascii")
Convert str to appropriate format for "UserComment".

:param data: Like u"foobar"
:param str encoding: "ascii", "jis", or "unicode"
:return: b"ASCII\x00\x00\x00foobar"
:rtype: bytes

::

import piexif
import piexif.helper
user_comment = piexif.helper.UserComment.dump(u"Edit now.")
exif_dict = piexif.load("foo.jpg")
exif_dict["Exif"][piexif.ExifIFD.UserComment] = user_comment
exif_bytes = piexif.dump(exif_dict)
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ To simplify exif manipulations with python. Writing, reading, and more... Piexif
about
installation
functions
helper
appendices
sample
changes
Expand Down
4 changes: 4 additions & 0 deletions piexif.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
<Compile Include="piexif\_dump.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="piexif\_exceptions.py" />
<Compile Include="piexif\_exif.py" />
<Compile Include="piexif\helper.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="piexif\_insert.py" />
<Compile Include="piexif\_load.py">
<SubType>Code</SubType>
Expand Down
4 changes: 2 additions & 2 deletions piexif/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ._transplant import transplant
from ._insert import insert
from ._exif import *
from ._exeptions import *
from ._exceptions import *


VERSION = '1.0.12'
VERSION = '1.0.13'
2 changes: 1 addition & 1 deletion piexif/_common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import struct

from ._exeptions import InvalidImageDataError
from ._exceptions import InvalidImageDataError


def split_into_segments(data):
Expand Down
43 changes: 38 additions & 5 deletions piexif/_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ def dump(exif_dict_original):
if exif_is:
exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length)
exif_length = len(exif_set[0]) + interop_is * 12 + len(exif_set[1])
#exif_bytes = b"".join(exif_set)
#exif_length = len(exif_bytes)
else:
exif_bytes = b""
exif_length = 0
Expand Down Expand Up @@ -163,18 +161,27 @@ def _get_thumbnail(jpeg):
def _pack_byte(*args):
return struct.pack("B" * len(args), *args)

def _pack_signed_byte(*args):
return struct.pack("b" * len(args), *args)

def _pack_short(*args):
return struct.pack(">" + "H" * len(args), *args)

def _pack_signed_short(*args):
return struct.pack(">" + "h" * len(args), *args)

def _pack_long(*args):
return struct.pack(">" + "L" * len(args), *args)


def _pack_slong(*args):
return struct.pack(">" + "l" * len(args), *args)

def _pack_float(*args):
return struct.pack(">" + "f" * len(args), *args)

def _pack_double(*args):
return struct.pack(">" + "d" * len(args), *args)


def _value_to_bytes(raw_value, value_type, offset):
four_bytes_over = b""
Expand Down Expand Up @@ -265,7 +272,33 @@ def _value_to_bytes(raw_value, value_type, offset):
value_str = raw_value + b"\x00" * (4 - length)
except TypeError:
raise ValueError("Got invalid type to convert.")

elif value_type == TYPES.SByte: # Signed Byte
length = len(raw_value)
if length <= 4:
value_str = (_pack_signed_byte(*raw_value) +
b"\x00" * (4 - length))
else:
value_str = struct.pack(">I", offset)
four_bytes_over = _pack_signed_byte(*raw_value)
elif value_type == TYPES.SShort: # Signed Short
length = len(raw_value)
if length <= 2:
value_str = (_pack_signed_short(*raw_value) +
b"\x00\x00" * (2 - length))
else:
value_str = struct.pack(">I", offset)
four_bytes_over = _pack_signed_short(*raw_value)
elif value_type == TYPES.Float:
length = len(raw_value)
if length <= 1:
value_str = _pack_float(*raw_value)
else:
value_str = struct.pack(">I", offset)
four_bytes_over = _pack_float(*raw_value)
elif value_type == TYPES.DFloat: # Double
length = len(raw_value)
value_str = struct.pack(">I", offset)
four_bytes_over = _pack_double(*raw_value)

length_str = struct.pack(">I", length)
return length_str, value_str, four_bytes_over
Expand Down Expand Up @@ -294,7 +327,7 @@ def _dict_to_bytes(ifd_dict, ifd, ifd_offset):
type_str = struct.pack(">H", value_type)
four_bytes_over = b""

if isinstance(raw_value, numbers.Integral):
if isinstance(raw_value, numbers.Integral) or isinstance(raw_value, float):
raw_value = (raw_value,)
offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + len(values)

Expand Down
File renamed without changes.
13 changes: 11 additions & 2 deletions piexif/_exif.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ class TYPES:
Short = 3
Long = 4
Rational = 5
SByte = 6
Undefined = 7
SShort = 8
SLong = 9
SRational = 10
Float = 11
DFloat = 12


TAGS = {
Expand Down Expand Up @@ -196,7 +199,10 @@ class TYPES:
51009: {'name': 'OpcodeList2', 'type': TYPES.Undefined},
51022: {'name': 'OpcodeList3', 'type': TYPES.Undefined},
60606: {'name': 'ZZZTestSlong1', 'type': TYPES.SLong},
60607: {'name': 'ZZZTestSlong2', 'type': TYPES.SLong}},
60607: {'name': 'ZZZTestSlong2', 'type': TYPES.SLong},
60608: {'name': 'ZZZTestSByte', 'type': TYPES.SByte},
60609: {'name': 'ZZZTestSShort', 'type': TYPES.SShort},
60610: {'name': 'ZZZTestDFloat', 'type': TYPES.DFloat},},
'Exif': {33434: {'name': 'ExposureTime', 'type': TYPES.Rational},
33437: {'name': 'FNumber', 'type': TYPES.Rational},
34850: {'name': 'ExposureProgram', 'type': TYPES.Short},
Expand Down Expand Up @@ -229,7 +235,7 @@ class TYPES:
37386: {'name': 'FocalLength', 'type': TYPES.Rational},
37396: {'name': 'SubjectArea', 'type': TYPES.Short},
37500: {'name': 'MakerNote', 'type': TYPES.Undefined},
37510: {'name': 'UserComment', 'type': TYPES.Ascii},
37510: {'name': 'UserComment', 'type': TYPES.Undefined},
37520: {'name': 'SubSecTime', 'type': TYPES.Ascii},
37521: {'name': 'SubSecTimeOriginal', 'type': TYPES.Ascii},
37522: {'name': 'SubSecTimeDigitized', 'type': TYPES.Ascii},
Expand Down Expand Up @@ -503,6 +509,9 @@ class ImageIFD:
NoiseProfile = 51041
ZZZTestSlong1 = 60606
ZZZTestSlong2 = 60607
ZZZTestSByte = 60608
ZZZTestSShort = 60609
ZZZTestDFloat = 60610


class ExifIFD:
Expand Down
2 changes: 1 addition & 1 deletion piexif/_insert.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import struct

from ._common import *
from ._exeptions import InvalidImageDataError
from ._exceptions import InvalidImageDataError


def insert(exif, image, new_file=None):
Expand Down
45 changes: 36 additions & 9 deletions piexif/_load.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import struct

from ._common import *
from ._exeptions import InvalidImageDataError
from ._exceptions import InvalidImageDataError
from ._exif import *


Expand Down Expand Up @@ -133,36 +133,36 @@ def convert_value(self, val):
length = val[1]
value = val[2]

if t == 1: # BYTE
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])
else:
data = struct.unpack("B" * length, value[0:length])
elif t == 2: # ASCII
elif t == TYPES.Ascii: # ASCII
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = self.tiftag[pointer: pointer+length - 1]
else:
data = value[0: length - 1]
elif t == 3: # SHORT
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])
else:
data = struct.unpack(self.endian_mark + "H" * length,
value[0:length * 2])
elif t == 4: # LONG
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])
else:
data = struct.unpack(self.endian_mark + "L" * length,
value)
elif t == 5: # RATIONAL
elif t == TYPES.Rational: # RATIONAL
pointer = struct.unpack(self.endian_mark + "L", value)[0]
if length > 1:
data = tuple(
Expand All @@ -180,21 +180,36 @@ def convert_value(self, val):
struct.unpack(self.endian_mark + "L",
self.tiftag[pointer + 4: pointer + 8]
)[0])
elif t == 7: # UNDEFINED BYTES
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])
else:
data = struct.unpack("b" * length, value[0:length])
elif t == TYPES.Undefined: # UNDEFINED BYTES
if length > 4:
pointer = struct.unpack(self.endian_mark + "L", value)[0]
data = self.tiftag[pointer: pointer+length]
else:
data = value[0:length]
elif t == 9: # SLONG
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])
else:
data = struct.unpack(self.endian_mark + "h" * length,
value[0:length * 2])
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])
else:
data = struct.unpack(self.endian_mark + "l" * length,
value)
elif t == 10: # SRATIONAL
elif t == TYPES.SRational: # SRATIONAL
pointer = struct.unpack(self.endian_mark + "L", value)[0]
if length > 1:
data = tuple(
Expand All @@ -210,6 +225,18 @@ def convert_value(self, val):
struct.unpack(self.endian_mark + "l",
self.tiftag[pointer + 4: pointer + 8]
)[0])
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])
else:
data = struct.unpack(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])
else:
raise ValueError("Exif might be wrong. Got incorrect value " +
"type to decode.\n" +
Expand Down

0 comments on commit 9bda766

Please sign in to comment.