Exemple #1
0
    def load(self, fp):

        self.reset()
        self._offset = fp.tell()

        try:
            for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
                tag, typ, count, data = self._unpack("HHL4s",
                                                     self._ensure_read(fp, 12))
                if DEBUG:
                    tagname = TAGS_V2.get(tag, TagInfo()).name
                    typname = TYPES.get(typ, "unknown")
                    print(
                        "tag: %s (%d) - type: %s (%d)" % (tagname, tag,
                                                          typname, typ),
                        end=" ")

                try:
                    unit_size, handler = self._load_dispatch[typ]
                except KeyError:
                    if DEBUG:
                        print("- unsupported type", typ)
                    continue  # ignore unsupported type
                size = count * unit_size
                if size > 4:
                    here = fp.tell()
                    offset, = self._unpack("L", data)
                    if DEBUG:
                        print(
                            "Tag Location: %s - Data Location: %s" % (here,
                                                                      offset),
                            end=" ")
                    fp.seek(offset)
                    data = ImageFile._safe_read(fp, size)
                    fp.seek(here)
                else:
                    data = data[:size]

                if len(data) != size:
                    warnings.warn(
                        "Possibly corrupt EXIF data.  "
                        "Expecting to read %d bytes but only got %d. "
                        "Skipping tag %s" % (size, len(data), tag))
                    continue

                self._tagdata[tag] = data
                self.tagtype[tag] = typ

                if DEBUG:
                    if size > 32:
                        print("- value: <table: %d bytes>" % size)
                    else:
                        print("- value:", self[tag])

            self.next, = self._unpack("L", self._ensure_read(fp, 4))
        except IOError as msg:
            warnings.warn(str(msg))
            return
Exemple #2
0
    def load(self, fp):

        self.reset()
        self._offset = fp.tell()

        try:
            for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
                tag, typ, count, data = self._unpack("HHL4s",
                                                     self._ensure_read(fp, 12))
                if DEBUG:
                    tagname = TAGS_V2.get(tag, TagInfo()).name
                    typname = TYPES.get(typ, "unknown")
                    print("tag: %s (%d) - type: %s (%d)" %
                          (tagname, tag, typname, typ),
                          end=" ")

                try:
                    unit_size, handler = self._load_dispatch[typ]
                except KeyError:
                    if DEBUG:
                        print("- unsupported type", typ)
                    continue  # ignore unsupported type
                size = count * unit_size
                if size > 4:
                    here = fp.tell()
                    offset, = self._unpack("L", data)
                    if DEBUG:
                        print("Tag Location: %s - Data Location: %s" %
                              (here, offset),
                              end=" ")
                    fp.seek(offset)
                    data = ImageFile._safe_read(fp, size)
                    fp.seek(here)
                else:
                    data = data[:size]

                if len(data) != size:
                    warnings.warn(
                        "Possibly corrupt EXIF data.  "
                        "Expecting to read %d bytes but only got %d. "
                        "Skipping tag %s" % (size, len(data), tag))
                    continue

                self._tagdata[tag] = data
                self.tagtype[tag] = typ

                if DEBUG:
                    if size > 32:
                        print("- value: <table: %d bytes>" % size)
                    else:
                        print("- value:", self[tag])

            self.next, = self._unpack("L", self._ensure_read(fp, 4))
        except IOError as msg:
            warnings.warn(str(msg))
            return
Exemple #3
0
    def save(self, fp):

        if fp.tell() == 0:  # skip TIFF header on subsequent pages
            # tiff header -- PIL always starts the first IFD at offset 8
            fp.write(self._prefix + self._pack("HL", 42, 8))

        # FIXME What about tagdata?
        fp.write(self._pack("H", len(self._tags_v2)))

        entries = []
        offset = fp.tell() + len(self._tags_v2) * 12 + 4
        stripoffsets = None

        # pass 1: convert tags to binary format
        # always write tags in ascending order
        for tag, value in sorted(self._tags_v2.items()):
            if tag == STRIPOFFSETS:
                stripoffsets = len(entries)
            typ = self.tagtype.get(tag)
            if DEBUG:
                print("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
            values = value if isinstance(value, tuple) else (value,)
            data = self._write_dispatch[typ](self, *values)
            if DEBUG:
                tagname = TAGS_V2.get(tag, TagInfo()).name
                typname = TYPES.get(typ, "unknown")
                print("save: %s (%d) - type: %s (%d)" %
                      (tagname, tag, typname, typ), end=" ")
                if len(data) >= 16:
                    print("- value: <table: %d bytes>" % len(data))
                else:
                    print("- value:", values)

            # count is sum of lengths for string and arbitrary data
            count = len(data) if typ in [2, 7] else len(values)
            # figure out if data fits into the entry
            if len(data) <= 4:
                entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
            else:
                entries.append((tag, typ, count, self._pack("L", offset), data))
                offset += (len(data) + 1) // 2 * 2  # pad to word

        # update strip offset data to point beyond auxiliary data
        if stripoffsets is not None:
            tag, typ, count, value, data = entries[stripoffsets]
            if data:
                raise NotImplementedError(
                    "multistrip support not yet implemented")
            value = self._pack("L", self._unpack("L", value)[0] + offset)
            entries[stripoffsets] = tag, typ, count, value, data

        # pass 2: write entries to file
        for tag, typ, count, value, data in entries:
            if DEBUG > 1:
                print(tag, typ, count, repr(value), repr(data))
            fp.write(self._pack("HHL4s", tag, typ, count, value))

        # -- overwrite here for multi-page --
        fp.write(b"\0\0\0\0")  # end of entries

        # pass 3: write auxiliary data to file
        for tag, typ, count, value, data in entries:
            fp.write(data)
            if len(data) & 1:
                fp.write(b"\0")

        return offset
Exemple #4
0
            fp.write(self._pack("HHL4s", tag, typ, count, value))

        # -- overwrite here for multi-page --
        fp.write(b"\0\0\0\0")  # end of entries

        # pass 3: write auxiliary data to file
        for tag, typ, count, value, data in entries:
            fp.write(data)
            if len(data) & 1:
                fp.write(b"\0")

        return offset

ImageFileDirectory_v2._load_dispatch = _load_dispatch
ImageFileDirectory_v2._write_dispatch = _write_dispatch
for idx, name in TYPES.items():
    name = name.replace(" ", "_")
    setattr(ImageFileDirectory_v2, "load_" + name, _load_dispatch[idx][1])
    setattr(ImageFileDirectory_v2, "write_" + name, _write_dispatch[idx])
del _load_dispatch, _write_dispatch, idx, name


# Legacy ImageFileDirectory support.
class ImageFileDirectory_v1(ImageFileDirectory_v2):
    """This class represents the **legacy** interface to a TIFF tag directory.

    Exposes a dictionary interface of the tags in the directory::

        ifd = ImageFileDirectory_v1()
        ifd[key] = 'Some Data'
        ifd.tagtype[key] = 2
Exemple #5
0
    def save(self, fp):

        if fp.tell() == 0:  # skip TIFF header on subsequent pages
            # tiff header -- PIL always starts the first IFD at offset 8
            fp.write(self._prefix + self._pack("HL", 42, 8))

        # FIXME What about tagdata?
        fp.write(self._pack("H", len(self._tags_v2)))

        entries = []
        offset = fp.tell() + len(self._tags_v2) * 12 + 4
        stripoffsets = None

        # pass 1: convert tags to binary format
        # always write tags in ascending order
        for tag, value in sorted(self._tags_v2.items()):
            if tag == STRIPOFFSETS:
                stripoffsets = len(entries)
            typ = self.tagtype.get(tag)
            if DEBUG:
                print("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
            values = value if isinstance(value, tuple) else (value, )
            data = self._write_dispatch[typ](self, *values)
            if DEBUG:
                tagname = TAGS_V2.get(tag, TagInfo()).name
                typname = TYPES.get(typ, "unknown")
                print("save: %s (%d) - type: %s (%d)" %
                      (tagname, tag, typname, typ),
                      end=" ")
                if len(data) >= 16:
                    print("- value: <table: %d bytes>" % len(data))
                else:
                    print("- value:", values)

            # count is sum of lengths for string and arbitrary data
            count = len(data) if typ in [2, 7] else len(values)
            # figure out if data fits into the entry
            if len(data) <= 4:
                entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
            else:
                entries.append((tag, typ, count, self._pack("L",
                                                            offset), data))
                offset += (len(data) + 1) // 2 * 2  # pad to word

        # update strip offset data to point beyond auxiliary data
        if stripoffsets is not None:
            tag, typ, count, value, data = entries[stripoffsets]
            if data:
                raise NotImplementedError(
                    "multistrip support not yet implemented")
            value = self._pack("L", self._unpack("L", value)[0] + offset)
            entries[stripoffsets] = tag, typ, count, value, data

        # pass 2: write entries to file
        for tag, typ, count, value, data in entries:
            if DEBUG > 1:
                print(tag, typ, count, repr(value), repr(data))
            fp.write(self._pack("HHL4s", tag, typ, count, value))

        # -- overwrite here for multi-page --
        fp.write(b"\0\0\0\0")  # end of entries

        # pass 3: write auxiliary data to file
        for tag, typ, count, value, data in entries:
            fp.write(data)
            if len(data) & 1:
                fp.write(b"\0")

        return offset
Exemple #6
0
        # -- overwrite here for multi-page --
        fp.write(b"\0\0\0\0")  # end of entries

        # pass 3: write auxiliary data to file
        for tag, typ, count, value, data in entries:
            fp.write(data)
            if len(data) & 1:
                fp.write(b"\0")

        return offset


ImageFileDirectory_v2._load_dispatch = _load_dispatch
ImageFileDirectory_v2._write_dispatch = _write_dispatch
for idx, name in TYPES.items():
    name = name.replace(" ", "_")
    setattr(ImageFileDirectory_v2, "load_" + name, _load_dispatch[idx][1])
    setattr(ImageFileDirectory_v2, "write_" + name, _write_dispatch[idx])
del _load_dispatch, _write_dispatch, idx, name


# Legacy ImageFileDirectory support.
class ImageFileDirectory_v1(ImageFileDirectory_v2):
    """This class represents the **legacy** interface to a TIFF tag directory.

    Exposes a dictionary interface of the tags in the directory::

        ifd = ImageFileDirectory_v1()
        ifd[key] = 'Some Data'
        ifd.tagtype[key] = 2