Example #1
0
    def load_from_png(self, filename, x, y, feedback_cb=None,
                      convert_to_srgb=True,
                      **kwargs):
        """Load from a PNG, one tilerow at a time, discarding empty tiles.

        :param str filename: The file to load
        :param int x: X-coordinate at which to load the replacement data
        :param int y: Y-coordinate at which to load the replacement data
        :param bool convert_to_srgb: If True, convert to sRGB
        :param callable feedback_cb: Called every few tile rows
        :param dict \*\*kwargs: Ignored

        Raises a `lib.errors.FileHandlingError` with a descriptive
        string when conversion or PNG reading fails.

        """
        dirty_tiles = set(self.tiledict.keys())
        self.tiledict = {}

        state = {}
        state['buf'] = None  # array of height N, width depends on image
        state['ty'] = y/N  # current tile row being filled into buf
        state['frame_size'] = None

        def get_buffer(png_w, png_h):
            state['frame_size'] = x, y, png_w, png_h
            if feedback_cb:
                feedback_cb()
            buf_x0 = x/N*N
            buf_x1 = ((x+png_w-1)/N+1)*N
            buf_y0 = state['ty']*N
            buf_y1 = buf_y0+N
            buf_w = buf_x1-buf_x0
            buf_h = buf_y1-buf_y0
            assert buf_w % N == 0
            assert buf_h == N
            if state['buf'] is not None:
                consume_buf()
            else:
                state['buf'] = numpy.empty((buf_h, buf_w, 4), 'uint8')

            png_x0 = x
            png_x1 = x+png_w
            subbuf = state['buf'][:, png_x0-buf_x0:png_x1-buf_x0]
            if 1:  # optimize: only needed for first and last
                state['buf'].fill(0)
                png_y0 = max(buf_y0, y)
                png_y1 = min(buf_y0+buf_h, y+png_h)
                assert png_y1 > png_y0
                subbuf = subbuf[png_y0-buf_y0:png_y1-buf_y0, :]

            state['ty'] += 1
            return subbuf

        def consume_buf():
            ty = state['ty']-1
            for i in xrange(state['buf'].shape[1]/N):
                tx = x/N + i
                src = state['buf'][:, i*N:(i+1)*N, :]
                if src[:, :, 3].any():
                    with self.tile_request(tx, ty, readonly=False) as dst:
                        mypaintlib.tile_convert_rgba8_to_rgba16(src, dst)

        if sys.platform == 'win32':
            filename_sys = filename.encode("utf-8")
        else:
            filename_sys = filename.encode(sys.getfilesystemencoding())  # FIXME: should not do that, should use open(unicode_object)
        try:
            flags = mypaintlib.load_png_fast_progressive(
                filename_sys,
                get_buffer,
                convert_to_srgb,
            )
        except (IOError, OSError, RuntimeError) as ex:
            raise FileHandlingError(_("PNG reader failed: %s") % str(ex))
        consume_buf()  # also process the final chunk of data
        logger.debug("PNG loader flags: %r", flags)

        dirty_tiles.update(self.tiledict.keys())
        bbox = lib.surface.get_tiles_bbox(dirty_tiles)
        self.notify_observers(*bbox)

        # return the bbox of the loaded image
        return state['frame_size']
    def load_from_png(self, filename, x, y, feedback_cb=None):
        """Load from a PNG, one tilerow at a time, discarding empty tiles.
        """
        dirty_tiles = set(self.tiledict.keys())
        self.tiledict = {}

        state = {}
        state['buf'] = None # array of height N, width depends on image
        state['ty'] = y/N # current tile row being filled into buf
        state['frame_size'] = None

        def get_buffer(png_w, png_h):
            state['frame_size'] = x, y, png_w, png_h
            if feedback_cb:
                feedback_cb()
            buf_x0 = x/N*N
            buf_x1 = ((x+png_w-1)/N+1)*N
            buf_y0 = state['ty']*N
            buf_y1 = buf_y0+N
            buf_w = buf_x1-buf_x0
            buf_h = buf_y1-buf_y0
            assert buf_w % N == 0
            assert buf_h == N
            if state['buf'] is not None:
                consume_buf()
            else:
                state['buf'] = empty((buf_h, buf_w, 4), 'uint8')

            png_x0 = x
            png_x1 = x+png_w
            subbuf = state['buf'][:,png_x0-buf_x0:png_x1-buf_x0]
            if 1: # optimize: only needed for first and last
                state['buf'].fill(0)
                png_y0 = max(buf_y0, y)
                png_y1 = min(buf_y0+buf_h, y+png_h)
                assert png_y1 > png_y0
                subbuf = subbuf[png_y0-buf_y0:png_y1-buf_y0,:]

            state['ty'] += 1
            return subbuf

        def consume_buf():
            ty = state['ty']-1
            for i in xrange(state['buf'].shape[1]/N):
                tx = x/N + i
                src = state['buf'][:,i*N:(i+1)*N,:]
                if src[:,:,3].any():
                    with self.tile_request(tx, ty, readonly=False) as dst:
                        mypaintlib.tile_convert_rgba8_to_rgba16(src, dst)

        filename_sys = filename.encode(sys.getfilesystemencoding()) # FIXME: should not do that, should use open(unicode_object)
        flags = mypaintlib.load_png_fast_progressive(filename_sys, get_buffer)
        consume_buf() # also process the final chunk of data
        print flags

        dirty_tiles.update(self.tiledict.keys())
        bbox = get_tiles_bbox(dirty_tiles)
        self.notify_observers(*bbox)

        # return the bbox of the loaded image
        return state['frame_size']
Example #3
0
    def load_from_png(self, filename, x, y, progress=None,
                      convert_to_srgb=True,
                      **kwargs):
        """Load from a PNG, one tilerow at a time, discarding empty tiles.

        :param str filename: The file to load
        :param int x: X-coordinate at which to load the replacement data
        :param int y: Y-coordinate at which to load the replacement data
        :param bool convert_to_srgb: If True, convert to sRGB
        :param progress: Unsized UI feedback obj.
        :type progress: lib.feedback.Progress or None
        :param dict \*\*kwargs: Ignored

        Raises a `lib.errors.FileHandlingError` with a descriptive
        string when conversion or PNG reading fails.

        """
        if not progress:
            progress = lib.feedback.Progress()

        # Catch this error up front, since the code below hides it.
        if progress.items is not None:
            raise ValueError("progress arg must be unsized")

        dirty_tiles = set(self.tiledict.keys())
        self.tiledict = {}

        ty0 = int(y // N)
        state = {}
        state['buf'] = None   # array of height N, width depends on image
        state['ty'] = ty0  # current tile row being filled into buf
        state['frame_size'] = None
        state['progress'] = progress

        def get_buffer(png_w, png_h):
            if state["frame_size"] is None:
                if state['progress']:
                    ty_final = int((y + png_h) // N)
                    # We have to handle feedback exceptions ourself
                    try:
                        state["progress"].items = ty_final - ty0
                    except Exception:
                        logger.exception("setting progress.items failed")
                        state["progress"] = None
                state['frame_size'] = (x, y, png_w, png_h)

            buf_x0 = x // N * N
            buf_x1 = ((x + png_w - 1) // N + 1) * N
            buf_y0 = state['ty']*N
            buf_y1 = buf_y0+N
            buf_w = buf_x1-buf_x0
            buf_h = buf_y1-buf_y0
            assert buf_w % N == 0
            assert buf_h == N
            if state['buf'] is not None:
                consume_buf()
            else:
                state['buf'] = np.empty((buf_h, buf_w, 4), 'uint8')

            png_x0 = x
            png_x1 = x+png_w
            subbuf = state['buf'][:, png_x0-buf_x0:png_x1-buf_x0]
            if 1:  # optimize: only needed for first and last
                state['buf'].fill(0)
                png_y0 = max(buf_y0, y)
                png_y1 = min(buf_y0+buf_h, y+png_h)
                assert png_y1 > png_y0
                subbuf = subbuf[png_y0-buf_y0:png_y1-buf_y0, :]

            state['ty'] += 1
            return subbuf

        def consume_buf():
            ty = state['ty']-1
            for i in xrange(state['buf'].shape[1] // N):
                tx = x // N + i
                src = state['buf'][:, i*N:(i+1)*N, :]
                if src[:, :, 3].any():
                    with self.tile_request(tx, ty, readonly=False) as dst:
                        mypaintlib.tile_convert_rgba8_to_rgba16(src, dst)
            if state["progress"]:
                try:
                    state["progress"].completed(ty - ty0)
                except Exception:
                    logger.exception("Progress.completed() failed")
                    state["progress"] = None

        if sys.platform == 'win32':
            filename_sys = filename.encode("utf-8")
        else:
            filename_sys = filename.encode(sys.getfilesystemencoding())
            # FIXME: should not do that, should use open(unicode_object)

        try:
            flags = mypaintlib.load_png_fast_progressive(
                filename_sys,
                get_buffer,
                convert_to_srgb,
            )
        except (IOError, OSError, RuntimeError) as ex:
            raise FileHandlingError(_("PNG reader failed: %s") % str(ex))
        consume_buf()  # also process the final chunk of data
        progress.close()
        logger.debug("PNG loader flags: %r", flags)

        dirty_tiles.update(self.tiledict.keys())
        bbox = lib.surface.get_tiles_bbox(dirty_tiles)
        self.notify_observers(*bbox)

        # return the bbox of the loaded image
        return state['frame_size']
Example #4
0
    def load_from_png(self,
                      filename,
                      x,
                      y,
                      feedback_cb=None,
                      convert_to_srgb=True,
                      **kwargs):
        """Load from a PNG, one tilerow at a time, discarding empty tiles.

        :param str filename: The file to load
        :param int x: X-coordinate at which to load the replacement data
        :param int y: Y-coordinate at which to load the replacement data
        :param bool convert_to_srgb: If True, convert to sRGB
        :param callable feedback_cb: Called every few tile rows
        :param dict \*\*kwargs: Ignored

        Raises a `lib.errors.FileHandlingError` with a descriptive
        string when conversion or PNG reading fails.

        """
        dirty_tiles = set(self.tiledict.keys())
        self.tiledict = {}

        state = {}
        state['buf'] = None  # array of height N, width depends on image
        state['ty'] = y / N  # current tile row being filled into buf
        state['frame_size'] = None

        def get_buffer(png_w, png_h):
            state['frame_size'] = x, y, png_w, png_h
            if feedback_cb:
                feedback_cb()
            buf_x0 = x / N * N
            buf_x1 = ((x + png_w - 1) / N + 1) * N
            buf_y0 = state['ty'] * N
            buf_y1 = buf_y0 + N
            buf_w = buf_x1 - buf_x0
            buf_h = buf_y1 - buf_y0
            assert buf_w % N == 0
            assert buf_h == N
            if state['buf'] is not None:
                consume_buf()
            else:
                state['buf'] = numpy.empty((buf_h, buf_w, 4), 'uint8')

            png_x0 = x
            png_x1 = x + png_w
            subbuf = state['buf'][:, png_x0 - buf_x0:png_x1 - buf_x0]
            if 1:  # optimize: only needed for first and last
                state['buf'].fill(0)
                png_y0 = max(buf_y0, y)
                png_y1 = min(buf_y0 + buf_h, y + png_h)
                assert png_y1 > png_y0
                subbuf = subbuf[png_y0 - buf_y0:png_y1 - buf_y0, :]

            state['ty'] += 1
            return subbuf

        def consume_buf():
            ty = state['ty'] - 1
            for i in xrange(state['buf'].shape[1] / N):
                tx = x / N + i
                src = state['buf'][:, i * N:(i + 1) * N, :]
                if src[:, :, 3].any():
                    with self.tile_request(tx, ty, readonly=False) as dst:
                        mypaintlib.tile_convert_rgba8_to_rgba16(src, dst)

        if sys.platform == 'win32':
            filename_sys = filename.encode("utf-8")
        else:
            filename_sys = filename.encode(sys.getfilesystemencoding(
            ))  # FIXME: should not do that, should use open(unicode_object)
        try:
            flags = mypaintlib.load_png_fast_progressive(
                filename_sys,
                get_buffer,
                convert_to_srgb,
            )
        except (IOError, OSError, RuntimeError) as ex:
            raise FileHandlingError(_("PNG reader failed: %s") % str(ex))
        consume_buf()  # also process the final chunk of data
        logger.debug("PNG loader flags: %r", flags)

        dirty_tiles.update(self.tiledict.keys())
        bbox = lib.surface.get_tiles_bbox(dirty_tiles)
        self.notify_observers(*bbox)

        # return the bbox of the loaded image
        return state['frame_size']
Example #5
0
    def load_from_png(self, filename, x, y, feedback_cb=None):
        """Load from a PNG, one tilerow at a time, discarding empty tiles.
        """
        dirty_tiles = set(self.tiledict.keys())
        self.tiledict = {}

        state = {}
        state['buf'] = None  # array of height N, width depends on image
        state['ty'] = y / N  # current tile row being filled into buf
        state['frame_size'] = None

        def get_buffer(png_w, png_h):
            state['frame_size'] = x, y, png_w, png_h
            if feedback_cb:
                feedback_cb()
            buf_x0 = x / N * N
            buf_x1 = ((x + png_w - 1) / N + 1) * N
            buf_y0 = state['ty'] * N
            buf_y1 = buf_y0 + N
            buf_w = buf_x1 - buf_x0
            buf_h = buf_y1 - buf_y0
            assert buf_w % N == 0
            assert buf_h == N
            if state['buf'] is not None:
                consume_buf()
            else:
                state['buf'] = numpy.empty((buf_h, buf_w, 4), 'uint8')

            png_x0 = x
            png_x1 = x + png_w
            subbuf = state['buf'][:, png_x0 - buf_x0:png_x1 - buf_x0]
            if 1:  # optimize: only needed for first and last
                state['buf'].fill(0)
                png_y0 = max(buf_y0, y)
                png_y1 = min(buf_y0 + buf_h, y + png_h)
                assert png_y1 > png_y0
                subbuf = subbuf[png_y0 - buf_y0:png_y1 - buf_y0, :]

            state['ty'] += 1
            return subbuf

        def consume_buf():
            ty = state['ty'] - 1
            for i in xrange(state['buf'].shape[1] / N):
                tx = x / N + i
                src = state['buf'][:, i * N:(i + 1) * N, :]
                if src[:, :, 3].any():
                    with self.tile_request(tx, ty, readonly=False) as dst:
                        mypaintlib.tile_convert_rgba8_to_rgba16(src, dst)

        filename_sys = filename.encode(sys.getfilesystemencoding(
        ))  # FIXME: should not do that, should use open(unicode_object)
        flags = mypaintlib.load_png_fast_progressive(filename_sys, get_buffer)
        consume_buf()  # also process the final chunk of data
        logger.debug("PNG loader flags: %r", flags)

        dirty_tiles.update(self.tiledict.keys())
        bbox = get_tiles_bbox(dirty_tiles)
        self.notify_observers(*bbox)

        # return the bbox of the loaded image
        return state['frame_size']