Example #1
0
 def decode(self, buffer):
     global DEBUG
     tex = self.args[
         0]  #it's not a "real" TexInfo, but the fields are the named the same, so duck typing saves the day!
     assert self.fd, "Something in PIL broke '_pulls_fd'! contact maintainer."
     buf = self.fd.read()
     bpp = bntx_extract.bpps[tex.format_ >> 8]
     if (tex.format_ >> 8) in bntx_extract.blk_dims:
         blkWidth, blkHeight = bntx_extract.blk_dims[tex.format_ >> 8]
     else:
         blkWidth, blkHeight = (1, 1)
     assert self.im is not None, "don't have an image before decode was called?"
     width, height = self.im.size
     size = swizzle.DIV_ROUND_UP(tex.width,
                                 blkWidth) * swizzle.DIV_ROUND_UP(
                                     tex.height, blkHeight) * bpp
     buf = swizzle.deswizzle(width, height, blkWidth, blkHeight, bpp,
                             tex.tileMode, tex.alignment, tex.sizeRange,
                             buf)
     buf = bytes(buf[:size])
     if DEBUG:
         print("Swizzle size:", size)
         print("Output buffer size:", len(buf))
     if pil:
         if (tex.format_ >> 8) > 0x19 and (tex.format_ >> 8) < 0x21:
             bcmode = (
                 tex.format_ >> 8
             ) - 0x19  #yes, this actually works; 0x1a is BC1, 1b is BC2, etc.
             if DEBUG:
                 print("BC[N] n-value:", bcmode)
         elif tex.format_ >> 8 in bntx_extract.BCn_formats:
             raise NotImplementedError(
                 "Unknown BlockCompression format. contact maintainer with sample."
             )
         if (tex.format_ >> 8) in bntx_extract.ASTC_formats:
             if astc:  #do we have the optional codec?
                 self.superdec = Image._getdecoder(self.mode, 'astc',
                                                   (blkWidth, blkHeight))
             else:
                 raise KeyError(
                     "This is an ASTC image, but the codec is not installed. please install 'astc_codec' with pip."
                 )
         else:
             self.superdec = Image._getdecoder(self.mode, 'bcn', (bcmode, ))
         self.superdec.setimage(self.im, self.state.extents())
         s = self.superdec.decode(buf)
         if s[0] >= 0:
             raise ValueError("not enough image data")
         if s[1] != 0:
             raise ValueError("cannot decode image data")
         return s
     else:
         raise NotImplementedError(
             "FIXME: non-PIL decoding of BC[n] pixelformats")
Example #2
0
 def decode(self, buffer):
     raw_heif_image: RawHeifImage = self.args[0]
     mode = raw_heif_image.mode
     raw_decoder = Image._getdecoder(mode, 'raw',
                                     (mode, raw_heif_image.stride))
     raw_decoder.setimage(self.im)
     return raw_decoder.decode(raw_heif_image.data)
Example #3
0
    def _load_libtiff(self):
        """ Overload method triggered when we detect a g3/g4 tiff
            Calls out to lib tiff """

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.load_prepare()

        if not len(self.tile) == 1:
            raise IOError("Not exactly one tile")

        d, e, o, a = self.tile[0]
        d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
        try:
            d.setimage(self.im, e)
        except ValueError:
            raise IOError("Couldn't set the image")

        if hasattr(self.fp, "getvalue"):
            # We've got a stringio like thing passed in. Yay for all in memory.
            # The decoder needs the entire file in one shot, so there's not
            # a lot we can do here other than give it the entire file.
            # unless we could do something like get the address of the underlying
            # string for stringio.
            #
            # Rearranging for supporting byteio items, since they have a fileno
            # that returns an IOError if there's no underlying fp. Easier to deal
            # with here by reordering.
            if Image.DEBUG:
                print ("have getvalue. just sending in a string from getvalue")
            n,e = d.decode(self.fp.getvalue())
        elif hasattr(self.fp, "fileno"):
            # we've got a actual file on disk, pass in the fp.
            if Image.DEBUG:
                print ("have fileno, calling fileno version of the decoder.")
            self.fp.seek(0)
            n,e = d.decode(b"fpfp") # 4 bytes, otherwise the trace might error out
        else:
            # we have something else.
            if Image.DEBUG:
                print ("don't have fileno or getvalue. just reading")
            # UNDONE -- so much for that buffer size thing.
            n, e = d.decode(self.fp.read())


        self.tile = []
        self.readonly = 0
        self.fp = None # might be shared

        if e < 0:
            raise IOError(e)

        self.load_end()

        return Image.Image.load(self)
    def _load_libtiff(self):
        """ Overload method triggered when we detect a compressed tiff
            Calls out to libtiff """

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.load_prepare()

        if not len(self.tile) == 1:
            raise IOError("Not exactly one tile")

        d, e, o, a = self.tile[0]
        d = Image._getdecoder(self.mode, 'libtiff', a, self.decoderconfig)
        try:
            d.setimage(self.im, e)
        except ValueError:
            raise IOError("Couldn't set the image")

        if hasattr(self.fp, "getvalue"):
            # We've got a stringio like thing passed in. Yay for all in memory.
            # The decoder needs the entire file in one shot, so there's not
            # a lot we can do here other than give it the entire file.
            # unless we could do something like get the address of the underlying
            # string for stringio.
            #
            # Rearranging for supporting byteio items, since they have a fileno
            # that returns an IOError if there's no underlying fp. Easier to deal
            # with here by reordering.
            if Image.DEBUG:
                print("have getvalue. just sending in a string from getvalue")
            n, e = d.decode(self.fp.getvalue())
        elif hasattr(self.fp, "fileno"):
            # we've got a actual file on disk, pass in the fp.
            if Image.DEBUG:
                print("have fileno, calling fileno version of the decoder.")
            self.fp.seek(0)
            n, e = d.decode(
                b"fpfp")  # 4 bytes, otherwise the trace might error out
        else:
            # we have something else.
            if Image.DEBUG:
                print("don't have fileno or getvalue. just reading")
            # UNDONE -- so much for that buffer size thing.
            n, e = d.decode(self.fp.read())

        self.tile = []
        self.readonly = 0
        self.fp = None  # might be shared

        if e < 0:
            raise IOError(e)

        self.load_end()

        return Image.Image.load(self)
Example #5
0
    def _set_as_jpeg(self, data, mode):
        from PIL.JpegImagePlugin import RAWMODE

        d = Image._getdecoder(mode, "jpeg", (RAWMODE[mode], ""))
        d.setimage(self.im, self.state.extents())
        s = d.decode(data)

        if s[0] >= 0:
            raise GalImageError("not enough image data")
        if s[1] != 0:
            raise GalImageError("cannot decode image data")
Example #6
0
    def _set_as_raw(self, data, mode, rawmode=None, stride=0):
        # override PIL set_as_raw() so we can set stride
        if not rawmode:
            rawmode = mode
        d = Image._getdecoder(mode, "raw", (rawmode, stride, 1))
        d.setimage(self.im, self.state.extents())
        s = d.decode(data)

        if s[0] >= 0:
            raise GalImageError("not enough image data")
        if s[1] != 0:
            raise GalImageError("cannot decode image data")
Example #7
0
    def _load_libtiff(self):
        """ Overload method triggered when we detect a compressed tiff
            Calls out to libtiff """

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.load_prepare()

        if not len(self.tile) == 1:
            raise IOError("Not exactly one tile")

        # (self._compression, (extents tuple),
        #   0, (rawmode, self._compression, fp))
        extents = self.tile[0][1]
        args = self.tile[0][3] + (self.tag_v2.offset,)
        decoder = Image._getdecoder(self.mode, 'libtiff', args,
                                    self.decoderconfig)
        try:
            decoder.setimage(self.im, extents)
        except ValueError:
            raise IOError("Couldn't set the image")

        if hasattr(self.fp, "getvalue"):
            # We've got a stringio like thing passed in. Yay for all in memory.
            # The decoder needs the entire file in one shot, so there's not
            # a lot we can do here other than give it the entire file.
            # unless we could do something like get the address of the
            # underlying string for stringio.
            #
            # Rearranging for supporting byteio items, since they have a fileno
            # that returns an IOError if there's no underlying fp. Easier to
            # deal with here by reordering.
            if DEBUG:
                print("have getvalue. just sending in a string from getvalue")
            n, err = decoder.decode(self.fp.getvalue())
        elif hasattr(self.fp, "fileno"):
            # we've got a actual file on disk, pass in the fp.
            if DEBUG:
                print("have fileno, calling fileno version of the decoder.")
            self.fp.seek(0)
            # 4 bytes, otherwise the trace might error out
            n, err = decoder.decode(b"fpfp")
        else:
            # we have something else.
            if DEBUG:
                print("don't have fileno or getvalue. just reading")
            # UNDONE -- so much for that buffer size thing.
            n, err = decoder.decode(self.fp.read())

        self.tile = []
        self.readonly = 0
        # libtiff closed the fp in a, we need to close self.fp, if possible
        if hasattr(self.fp, 'close'):
            if not self.__next:
                self.fp.close()
        self.fp = None  # might be shared

        if err < 0:
            raise IOError(err)

        self.load_end()

        return Image.Image.load(self)
Example #8
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            d, e, o, a = self.tile[0]
            if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper
                        self.map = Image.core.map(self.filename)
                        self.map.seek(o)
                        self.im = self.map.readimage(self.mode, self.size,
                                                     a[1], a[2])
                    else:
                        # use mmap, if possible
                        import mmap
                        fp = open(self.filename, "r+")
                        size = os.path.getsize(self.filename)
                        # FIXME: on Unix, use PROT_READ etc
                        self.map = mmap.mmap(fp.fileno(), size)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, d, e, o, a)
                    readonly = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        if not self.map:
            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            # Buffer length read; assign a default value
            t = 0

            for d, e, o, a in self.tile:
                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
                seek(o)
                try:
                    d.setimage(self.im, e)
                except ValueError:
                    continue
                b = prefix
                t = len(b)
                while True:
                    try:
                        s = read(self.decodermaxblock)
                    except IndexError as ie:  # truncated png/gif
                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IndexError(ie)

                    if not s and not d.handles_eof:  # truncated jpeg
                        self.tile = []

                        # JpegDecode needs to clean things up here either way
                        # If we don't destroy the decompressor,
                        # we have a memory leak.
                        d.cleanup()

                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IOError("image file is truncated "
                                          "(%d bytes not processed)" % len(b))

                    b = b + s
                    n, e = d.decode(b)
                    if n < 0:
                        break
                    b = b[n:]
                    t = t + n
                # Need to cleanup here to prevent leaks in PyPy
                d.cleanup()

        self.tile = []
        self.readonly = readonly

        self.fp = None  # might be shared

        if not self.map and (not LOAD_TRUNCATED_IMAGES or t == 0) and e < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(e)

        # post processing
        if hasattr(self, "tile_post_rotate"):
            # FIXME: This is a hack to handle rotated PCD's
            self.im = self.im.rotate(self.tile_post_rotate)
            self.size = self.im.size

        self.load_end()

        return Image.Image.load(self)
Example #9
0
    def feed(self, data):
        """
        (Consumer) Feed data to the parser.

        :param data: A string buffer.
        :exception IOError: If the parser failed to parse the image file.
        """
        # collect data

        if self.finished:
            return

        if self.data is None:
            self.data = data
        else:
            self.data = self.data + data

        # parse what we have
        if self.decoder:

            if self.offset > 0:
                # skip header
                skip = min(len(self.data), self.offset)
                self.data = self.data[skip:]
                self.offset = self.offset - skip
                if self.offset > 0 or not self.data:
                    return

            n, e = self.decoder.decode(self.data)

            if n < 0:
                # end of stream
                self.data = None
                self.finished = 1
                if e < 0:
                    # decoding error
                    self.image = None
                    raise_ioerror(e)
                else:
                    # end of image
                    return
            self.data = self.data[n:]

        elif self.image:

            # if we end up here with no decoder, this file cannot
            # be incrementally parsed.  wait until we've gotten all
            # available data
            pass

        else:

            # attempt to open this file
            try:
                try:
                    fp = io.BytesIO(self.data)
                    im = Image.open(fp)
                finally:
                    fp.close()  # explicitly close the virtual file
            except IOError:
                # traceback.print_exc()
                pass  # not enough data
            else:
                flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
                if flag or len(im.tile) != 1:
                    # custom load code, or multiple tiles
                    self.decode = None
                else:
                    # initialize decoder
                    im.load_prepare()
                    d, e, o, a = im.tile[0]
                    im.tile = []
                    self.decoder = Image._getdecoder(
                        im.mode, d, a, im.decoderconfig
                        )
                    self.decoder.setimage(im.im, e)

                    # calculate decoder offset
                    self.offset = o
                    if self.offset <= len(self.data):
                        self.data = self.data[self.offset:]
                        self.offset = 0

                self.image = im
Example #10
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            d, e, o, a = self.tile[0]
            if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper
                        self.map = Image.core.map(self.filename)
                        self.map.seek(o)
                        self.im = self.map.readimage(
                            self.mode, self.size, a[1], a[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        fp = open(self.filename, "r+")
                        size = os.path.getsize(self.filename)
                        # FIXME: on Unix, use PROT_READ etc
                        self.map = mmap.mmap(fp.fileno(), size)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, d, e, o, a
                            )
                    readonly = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        if not self.map:
            # sort tiles in file orders
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for d, e, o, a in self.tile:
                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
                seek(o)
                try:
                    d.setimage(self.im, e)
                except ValueError:
                    continue
                b = prefix
                while True:
                    try:
                        s = read(self.decodermaxblock)
                    except (IndexError, struct.error):  # truncated png/gif
                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IOError("image file is truncated")

                    if not s and not d.handles_eof:  # truncated jpeg
                        self.tile = []

                        # JpegDecode needs to clean things up here either way
                        # If we don't destroy the decompressor,
                        # we have a memory leak.
                        d.cleanup()

                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IOError("image file is truncated "
                                          "(%d bytes not processed)" % len(b))

                    b = b + s
                    n, e = d.decode(b)
                    if n < 0:
                        break
                    b = b[n:]
                # Need to cleanup here to prevent leaks in PyPy
                d.cleanup()

        self.tile = []
        self.readonly = readonly

        self.fp = None  # might be shared

        if not self.map and not LOAD_TRUNCATED_IMAGES and e < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(e)

        # post processing
        if hasattr(self, "tile_post_rotate"):
            # FIXME: This is a hack to handle rotated PCD's
            self.im = self.im.rotate(self.tile_post_rotate)
            self.size = self.im.size

        self.load_end()

        return Image.Image.load(self)
Example #11
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None

        readonly = 0

        if self.filename and len(self.tile) == 1:
            # try memory mapping
            d, e, o, a = self.tile[0]
            if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper
                        self.map = Image.core.map(self.filename)
                        self.map.seek(o)
                        self.im = self.map.readimage(self.mode, self.size,
                                                     a[1], a[2])
                    else:
                        # use mmap, if possible
                        import mmap
                        file = open(self.filename, "r+")
                        size = os.path.getsize(self.filename)
                        # FIXME: on Unix, use PROT_READ etc
                        self.map = mmap.mmap(file.fileno(), size)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, d, e, o, a)
                    readonly = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        # look for read/seek overrides
        try:
            read = self.load_read
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
        except AttributeError:
            seek = self.fp.seek

        if not self.map:

            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for d, e, o, a in self.tile:
                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
                seek(o)
                try:
                    d.setimage(self.im, e)
                except ValueError:
                    continue
                b = prefix
                t = len(b)
                while True:
                    try:
                        s = read(self.decodermaxblock)
                    except IndexError as ie:  # truncated png/gif
                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IndexError(ie)

                    if not s:  # truncated jpeg
                        self.tile = []

                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IOError(
                                "image file is truncated (%d bytes not processed)"
                                % len(b))

                    b = b + s
                    n, e = d.decode(b)
                    if n < 0:
                        break
                    b = b[n:]
                    t = t + n

        self.tile = []
        self.readonly = readonly

        self.fp = None  # might be shared

        if (not LOAD_TRUNCATED_IMAGES or t == 0) and not self.map and e < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(e)

        # post processing
        if hasattr(self, "tile_post_rotate"):
            # FIXME: This is a hack to handle rotated PCD's
            self.im = self.im.rotate(self.tile_post_rotate)
            self.size = self.im.size

        self.load_end()

        return Image.Image.load(self)
Example #12
0
    def _load_libtiff(self):
        """ Overload method triggered when we detect a compressed tiff
            Calls out to libtiff """

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.load_prepare()

        if not len(self.tile) == 1:
            raise IOError("Not exactly one tile")

        # (self._compression, (extents tuple),
        #   0, (rawmode, self._compression, fp))
        ignored, extents, ignored_2, args = self.tile[0]
        args = args + (self.ifd.offset, )
        decoder = Image._getdecoder(self.mode, 'libtiff', args,
                                    self.decoderconfig)
        try:
            decoder.setimage(self.im, extents)
        except ValueError:
            raise IOError("Couldn't set the image")

        if hasattr(self.fp, "getvalue"):
            # We've got a stringio like thing passed in. Yay for all in memory.
            # The decoder needs the entire file in one shot, so there's not
            # a lot we can do here other than give it the entire file.
            # unless we could do something like get the address of the
            # underlying string for stringio.
            #
            # Rearranging for supporting byteio items, since they have a fileno
            # that returns an IOError if there's no underlying fp. Easier to
            # dea. with here by reordering.
            if Image.DEBUG:
                print("have getvalue. just sending in a string from getvalue")
            n, err = decoder.decode(self.fp.getvalue())
        elif hasattr(self.fp, "fileno"):
            # we've got a actual file on disk, pass in the fp.
            if Image.DEBUG:
                print("have fileno, calling fileno version of the decoder.")
            self.fp.seek(0)
            # 4 bytes, otherwise the trace might error out
            n, err = decoder.decode(b"fpfp")
        else:
            # we have something else.
            if Image.DEBUG:
                print("don't have fileno or getvalue. just reading")
            # UNDONE -- so much for that buffer size thing.
            n, err = decoder.decode(self.fp.read())

        self.tile = []
        self.readonly = 0
        # libtiff closed the fp in a, we need to close self.fp, if possible
        if hasattr(self.fp, 'close'):
            if not self.__next:
                self.fp.close()
        self.fp = None  # might be shared

        if err < 0:
            raise IOError(err)

        self.load_end()

        return Image.Image.load(self)
Example #13
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            decoder_name, extents, offset, args = self.tile[0]
            if decoder_name == "raw" and len(args) >= 3 and args[0] == self.mode \
                   and args[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper  WIN32 only
                        self.map = Image.core.map(self.filename)
                        self.map.seek(offset)
                        self.im = self.map.readimage(
                            self.mode, self.size, args[1], args[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        fp = open(self.filename, "r")
                        size = os.path.getsize(self.filename)
                        self.map = mmap.mmap(fp.fileno(), size, access=mmap.ACCESS_READ)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, decoder_name, extents, offset, args
                            )
                    readonly = 1
                    # After trashing self.im, we might need to reload the palette data.
                    if self.palette:
                        self.palette.dirty = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        if not self.map:
            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for decoder_name, extents, offset, args in self.tile:
                decoder = Image._getdecoder(self.mode, decoder_name,
                                      args, self.decoderconfig)
                seek(offset)
                try:
                    decoder.setimage(self.im, extents)
                except ValueError:
                    continue
                if decoder.pulls_fd:
                    decoder.setfd(self.fp)
                    status, err_code = decoder.decode(b"")
                else:
                    b = prefix
                    while True:
                        try:
                            s = read(self.decodermaxblock)
                        except (IndexError, struct.error):  # truncated png/gif
                            if LOAD_TRUNCATED_IMAGES:
                                break
                            else:
                                raise IOError("image file is truncated")

                        if not s:  # truncated jpeg
                            self.tile = []

                            # JpegDecode needs to clean things up here either way
                            # If we don't destroy the decompressor,
                            # we have a memory leak.
                            decoder.cleanup()

                            if LOAD_TRUNCATED_IMAGES:
                                break
                            else:
                                raise IOError("image file is truncated "
                                              "(%d bytes not processed)" % len(b))

                        b = b + s
                        n, err_code = decoder.decode(b)
                        if n < 0:
                            break
                        b = b[n:]

                # Need to cleanup here to prevent leaks in PyPy
                decoder.cleanup()

        self.tile = []
        self.readonly = readonly

        self.fp = None  # might be shared

        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(err_code)

        self.load_end()

        return Image.Image.load(self)
 def decode(self, buffer):
     heif_file = self.args[0]
     mode = heif_file.mode
     raw_decoder = Image._getdecoder(mode, 'raw', (mode, heif_file.stride))
     raw_decoder.setimage(self.im)
     return raw_decoder.decode(heif_file.data)
Example #15
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            decoder_name, extents, offset, args = self.tile[0]
            if decoder_name == "raw" and len(args) >= 3 and args[0] == self.mode \
                   and args[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper  WIN32 only
                        self.map = Image.core.map(self.filename)
                        self.map.seek(offset)
                        self.im = self.map.readimage(
                            self.mode, self.size, args[1], args[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        fp = open(self.filename, "r")
                        size = os.path.getsize(self.filename)
                        self.map = mmap.mmap(fp.fileno(), size, access=mmap.ACCESS_READ)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, decoder_name, extents, offset, args
                            )
                    readonly = 1
                    # After trashing self.im, we might need to reload the palette data.
                    if self.palette:
                        self.palette.dirty = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        if not self.map:
            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for decoder_name, extents, offset, args in self.tile:
                decoder = Image._getdecoder(self.mode, decoder_name,
                                      args, self.decoderconfig)
                seek(offset)
                try:
                    decoder.setimage(self.im, extents)
                except ValueError:
                    continue
                if decoder.pulls_fd:
                    decoder.setfd(self.fp)
                    status, err_code = decoder.decode(b"")
                else:
                    b = prefix
                    while True:
                        try:
                            s = read(self.decodermaxblock)
                        except (IndexError, struct.error):  # truncated png/gif
                            if LOAD_TRUNCATED_IMAGES:
                                break
                            else:
                                raise IOError("image file is truncated")

                        if not s:  # truncated jpeg
                            self.tile = []

                            # JpegDecode needs to clean things up here either way
                            # If we don't destroy the decompressor,
                            # we have a memory leak.
                            decoder.cleanup()

                            if LOAD_TRUNCATED_IMAGES:
                                break
                            else:
                                raise IOError("image file is truncated "
                                              "(%d bytes not processed)" % len(b))

                        b = b + s
                        n, err_code = decoder.decode(b)
                        if n < 0:
                            break
                        b = b[n:]

                # Need to cleanup here to prevent leaks in PyPy
                decoder.cleanup()

        self.tile = []
        self.readonly = readonly

        self.fp = None  # might be shared

        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(err_code)

        self.load_end()

        return Image.Image.load(self)
Example #16
0
    def feed(self, data):
        """
        (Consumer) Feed data to the parser.

        :param data: A string buffer.
        :exception IOError: If the parser failed to parse the image file.
        """
        # collect data

        if self.finished:
            return

        if self.data is None:
            self.data = data
        else:
            self.data = self.data + data

        # parse what we have
        if self.decoder:

            if self.offset > 0:
                # skip header
                skip = min(len(self.data), self.offset)
                self.data = self.data[skip:]
                self.offset = self.offset - skip
                if self.offset > 0 or not self.data:
                    return

            n, e = self.decoder.decode(self.data)

            if n < 0:
                # end of stream
                self.data = None
                self.finished = 1
                if e < 0:
                    # decoding error
                    self.image = None
                    raise_ioerror(e)
                else:
                    # end of image
                    return
            self.data = self.data[n:]

        elif self.image:

            # if we end up here with no decoder, this file cannot
            # be incrementally parsed.  wait until we've gotten all
            # available data
            pass

        else:

            # attempt to open this file
            try:
                try:
                    fp = io.BytesIO(self.data)
                    im = Image.open(fp)
                finally:
                    fp.close()  # explicitly close the virtual file
            except IOError:
                # traceback.print_exc()
                pass  # not enough data
            else:
                flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
                if flag or len(im.tile) != 1:
                    # custom load code, or multiple tiles
                    self.decode = None
                else:
                    # initialize decoder
                    im.load_prepare()
                    d, e, o, a = im.tile[0]
                    im.tile = []
                    self.decoder = Image._getdecoder(
                        im.mode, d, a, im.decoderconfig
                        )
                    self.decoder.setimage(im.im, e)

                    # calculate decoder offset
                    self.offset = o
                    if self.offset <= len(self.data):
                        self.data = self.data[self.offset:]
                        self.offset = 0

                self.image = im
Example #17
0
    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None

        readonly = 0

        if self.filename and len(self.tile) == 1:
            # try memory mapping
            d, e, o, a = self.tile[0]
            if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper
                        self.map = Image.core.map(self.filename)
                        self.map.seek(o)
                        self.im = self.map.readimage(
                            self.mode, self.size, a[1], a[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        file = open(self.filename, "r+")
                        size = os.path.getsize(self.filename)
                        # FIXME: on Unix, use PROT_READ etc
                        self.map = mmap.mmap(file.fileno(), size)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, d, e, o, a
                            )
                    readonly = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()

        # look for read/seek overrides
        try:
            read = self.load_read
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
        except AttributeError:
            seek = self.fp.seek

        if not self.map:

            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for d, e, o, a in self.tile:
                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
                seek(o)
                try:
                    d.setimage(self.im, e)
                except ValueError:
                    continue
                b = prefix
                t = len(b)
                while True:
                    try:
                        s = read(self.decodermaxblock)
                    except IndexError as ie: # truncated png/gif
                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IndexError(ie)

                    if not s: # truncated jpeg
                        self.tile = []

                        if LOAD_TRUNCATED_IMAGES:
                            break
                        else:
                            raise IOError("image file is truncated (%d bytes not processed)" % len(b))

                    b = b + s
                    n, e = d.decode(b)
                    if n < 0:
                        break
                    b = b[n:]
                    t = t + n

        self.tile = []
        self.readonly = readonly

        self.fp = None # might be shared

        if (not LOAD_TRUNCATED_IMAGES or t == 0) and not self.map and e < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(e)

        # post processing
        if hasattr(self, "tile_post_rotate"):
            # FIXME: This is a hack to handle rotated PCD's
            self.im = self.im.rotate(self.tile_post_rotate)
            self.size = self.im.size

        self.load_end()

        return Image.Image.load(self)