コード例 #1
0
ファイル: backgroundwindow.py プロジェクト: briend/mypaint
 def _get_preview_pixbuf(self, pixbuf):
     if pixbuf in self._pixbufs_scaled:
         return self._pixbufs_scaled[pixbuf]
     w, h = pixbuf.get_width(), pixbuf.get_height()
     if w == N and h == N:
         return pixbuf
     assert w >= N
     assert h >= N
     scale = max(0.25, N / min(w, h))
     scaled = new_blank_pixbuf((0, 0, 0), N, N)
     pixbuf.composite(
         dest=scaled,
         dest_x=0, dest_y=0,
         dest_width=N, dest_height=N,
         offset_x=0, offset_y=0,
         scale_x=scale, scale_y=scale,
         interp_type=GdkPixbuf.InterpType.BILINEAR,
         overall_alpha=255,
     )
     self.app.pixmaps.plus.composite(
         dest=scaled,
         dest_x=0, dest_y=0,
         dest_width=N, dest_height=N,
         offset_x=0, offset_y=0,
         scale_x=1.0, scale_y=1.0,
         interp_type=GdkPixbuf.InterpType.BILINEAR,
         overall_alpha=255,
     )
     self._pixbufs_scaled[pixbuf] = scaled
     return scaled
コード例 #2
0
    def render_thumbnail(self, bbox, **options):
        """Renders a 256x256 thumb of the layer in an arbitrary bbox.

        :param bbox: Bounding box to make a thumbnail of
        :type bbox: tuple
        :param **options: Passed to `render_as_pixbuf()`.
        :rtype: GtkPixbuf or None

        This implementation requires a working render_as_pixbuf().  Use
        the thumbnail property if you just want a reasonably up-to-date
        preview thumbnail for a single layer.

        """
        x, y, w, h = bbox
        if w == 0 or h == 0:
            # workaround to save empty documents
            x, y, w, h = 0, 0, lib.tiledsurface.N, lib.tiledsurface.N
        mipmap_level = 0
        while (mipmap_level < lib.tiledsurface.MAX_MIPMAP_LEVEL
               and max(w, h) >= 512):
            mipmap_level += 1
            x, y, w, h = x // 2, y // 2, w // 2, h // 2
        w = max(1, w)
        h = max(1, h)
        pixbuf = self.render_as_pixbuf(x,
                                       y,
                                       w,
                                       h,
                                       mipmap_level=mipmap_level,
                                       **options)
        assert pixbuf.get_width() == w and pixbuf.get_height() == h
        return helpers.scale_proportionally(pixbuf, 256, 256)
コード例 #3
0
ファイル: backgroundwindow.py プロジェクト: yazici/mypaint
def _tile_pixbuf(pixbuf, repeats_x, repeats_y):
    """Make a repeated tiled image of a pixbuf"""
    w, h = pixbuf.get_width(), pixbuf.get_height()
    result = new_blank_pixbuf((0, 0, 0), repeats_x * w, repeats_y * h)
    for xi in xrange(repeats_x):
        for yi in xrange(repeats_y):
            pixbuf.copy_area(0, 0, w, h, result, w * xi, h * yi)
    return result
コード例 #4
0
ファイル: backgroundwindow.py プロジェクト: briend/mypaint
def _tile_pixbuf(pixbuf, repeats_x, repeats_y):
    """Make a repeated tiled image of a pixbuf"""
    w, h = pixbuf.get_width(), pixbuf.get_height()
    result = new_blank_pixbuf((0, 0, 0), repeats_x * w, repeats_y * h)
    for xi in xrange(repeats_x):
        for yi in xrange(repeats_y):
            pixbuf.copy_area(0, 0, w, h, result, w * xi, h * yi)
    return result
コード例 #5
0
ファイル: helpers.py プロジェクト: chunws/mypaint
def scale_proportionally(pixbuf, w, h, shrink_only=True):
    width, height = pixbuf.get_width(), pixbuf.get_height()
    scale = min(w / float(width), h / float(height))
    if shrink_only and scale >= 1:
        return pixbuf
    new_width, new_height = int(width * scale), int(height * scale)
    new_width = max(new_width, 1)
    new_height = max(new_height, 1)
    return pixbuf.scale_simple(new_width, new_height, GdkPixbuf.InterpType.BILINEAR)
コード例 #6
0
ファイル: helpers.py プロジェクト: thorsummoner/mypaint
def scale_proportionally(pixbuf, w, h, shrink_only=True):
    width, height = pixbuf.get_width(), pixbuf.get_height()
    scale = min(w / float(width), h / float(height))
    if shrink_only and scale >= 1:
        return pixbuf
    new_width, new_height = int(width * scale), int(height * scale)
    new_width = max(new_width, 1)
    new_height = max(new_height, 1)
    return pixbuf.scale_simple(new_width, new_height,
                               GdkPixbuf.InterpType.BILINEAR)
コード例 #7
0
ファイル: backgroundwindow.py プロジェクト: yazici/mypaint
 def _get_preview_pixbuf(self, pixbuf):
     if pixbuf in self._pixbufs_scaled:
         return self._pixbufs_scaled[pixbuf]
     w, h = pixbuf.get_width(), pixbuf.get_height()
     if w == N and h == N:
         return pixbuf
     assert w >= N
     assert h >= N
     scale = max(0.25, N / min(w, h))
     scaled = new_blank_pixbuf((0, 0, 0), N, N)
     pixbuf.composite(
         dest=scaled,
         dest_x=0,
         dest_y=0,
         dest_width=N,
         dest_height=N,
         offset_x=0,
         offset_y=0,
         scale_x=scale,
         scale_y=scale,
         interp_type=GdkPixbuf.InterpType.BILINEAR,
         overall_alpha=255,
     )
     self.app.pixmaps.plus.composite(
         dest=scaled,
         dest_x=0,
         dest_y=0,
         dest_width=N,
         dest_height=N,
         offset_x=0,
         offset_y=0,
         scale_x=1.0,
         scale_y=1.0,
         interp_type=GdkPixbuf.InterpType.BILINEAR,
         overall_alpha=255,
     )
     self._pixbufs_scaled[pixbuf] = scaled
     return scaled
コード例 #8
0
ファイル: backgroundwindow.py プロジェクト: yazici/mypaint
def load_background(filename, bloatmax=BLOAT_MAX_SIZE):
    """Load a pixbuf, testing it for suitability as a background

    :param str filename: Full path to the filename to load.
    :param int bloatmax: Repeat up to this size
    :rtype: tuple

    The returned tuple is a pair ``(PIXBUF, ERRORS)``,
    where ``ERRORS`` is a list of localized strings
    describing the errors encountered,
    and ``PIXBUF`` contains the loaded background pixbuf.
    If there were errors, ``PIXBUF`` is None.

    The MyPaint rendering engine can only manage
    background layers which fit into its tile structure.
    Formerly, only background images with dimensions
    which were exact multiples of the tile size were permitted.
    We have a couple of workarounds now:

    * "Bloating" the background by repetition (pixel-perfect)
    * Scaling the image down to fit (distorts the image)

    """
    filename_display = _filename_to_display(filename)
    load_errors = []
    try:
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
    except Exception as ex:
        logger.error("Failed to load background %r: %s", filename, ex)
        msg = unicode(
            _('Gdk-Pixbuf couldn\'t load "{filename}", and reported "{error}"')
        )
        load_errors.append(
            msg.format(
                filename=filename_display,
                error=repr(ex),
            ))
        return (None, load_errors)
    # Validity check
    w, h = pixbuf.get_width(), pixbuf.get_height()
    if w == 0 or h == 0:
        msg = unicode(_("{filename} has zero size (w={w}, h={h})"))
        load_errors.append(msg.format(
            filename=filename_display,
            w=w,
            h=h,
        ))
        return (None, load_errors)
    # Flatten
    if pixbuf.get_has_alpha():
        logger.warning(
            "%r has an alpha channel, which should be removed manually",
            filename,
        )
        new_pixbuf = new_blank_pixbuf((0, 0, 0), w, h)
        pixbuf.composite(
            dest=new_pixbuf,
            dest_x=0,
            dest_y=0,
            dest_width=w,
            dest_height=h,
            offset_x=0,
            offset_y=0,
            scale_x=1.0,
            scale_y=1.0,
            interp_type=GdkPixbuf.InterpType.NEAREST,
            overall_alpha=255,
        )
        pixbuf = new_pixbuf
        logger.debug(
            "Flattened %s by compositing it onto a black backdrop",
            filename,
        )
    # Attempt to fit the image into our grid.
    exact_fit = ((w % N, h % N) == (0, 0))
    if not exact_fit:
        logger.warning(
            "%r (%dx%d) does not fit the %dx%d tile grid exactly",
            filename,
            w,
            h,
            N,
            N,
        )
        repeats_x = _best_nrepeats_for_scaling(w, bloatmax)
        repeats_y = _best_nrepeats_for_scaling(h, bloatmax)
        if repeats_x > 1 or repeats_y > 1:
            logger.info(
                "Tiling %r to %dx%d (was: %dx%d, repeats: %d vert, %d horiz)",
                filename,
                w * repeats_x,
                h * repeats_y,
                w,
                h,
                repeats_x,
                repeats_y,
            )
            pixbuf = _tile_pixbuf(pixbuf, repeats_x, repeats_y)
        w, h = pixbuf.get_width(), pixbuf.get_height()
        if (w % N != 0) or (h % N != 0):
            orig_w, orig_h = w, h
            w = max(1, w // N) * N
            h = max(1, h // N) * N
            logger.info(
                "Scaling %r to %dx%d (was: %dx%d)",
                filename,
                w,
                h,
                orig_w,
                orig_h,
            )
            pixbuf = pixbuf.scale_simple(
                dest_width=w,
                dest_height=h,
                interp_type=GdkPixbuf.InterpType.BILINEAR,
            )
        assert (w % N == 0) and (h % N == 0)
    if load_errors:
        pixbuf = None
    return pixbuf, load_errors
コード例 #9
0
ファイル: backgroundwindow.py プロジェクト: mmorello1/mypaint
 filename_display = filename.decode(sys.getfilesystemencoding(), 'replace')
 load_errors = []
 try:
     pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
 except Exception, ex:
     logger.error("Failed to load background %r: %s", filename, ex)
     msg = _(
         'Gdk-Pixbuf couldn\'t load "{filename}", and reported "{error}"')
     load_errors.append(
         msg.format(
             filename=filename_display,
             error=repr(ex),
         ))
     return (None, load_errors)
 # Validity check
 w, h = pixbuf.get_width(), pixbuf.get_height()
 if w == 0 or h == 0:
     msg = _("{filename} has zero size (w={w}, h={h})")
     load_errors.append(msg.format(
         filename=filename_display,
         w=w,
         h=h,
     ))
     return (None, load_errors)
 # Flatten
 if pixbuf.get_has_alpha():
     logger.warning(
         "%r has an alpha channel, which should be removed manually",
         filename,
     )
     new_pixbuf = new_blank_pixbuf((0, 0, 0), w, h)
コード例 #10
0
ファイル: backgroundwindow.py プロジェクト: briend/mypaint
def load_background(filename, bloatmax=BLOAT_MAX_SIZE):
    """Load a pixbuf, testing it for suitability as a background

    :param str filename: Full path to the filename to load.
    :param int bloatmax: Repeat up to this size
    :rtype: tuple

    The returned tuple is a pair ``(PIXBUF, ERRORS)``,
    where ``ERRORS`` is a list of localized strings
    describing the errors encountered,
    and ``PIXBUF`` contains the loaded background pixbuf.
    If there were errors, ``PIXBUF`` is None.

    The MyPaint rendering engine can only manage
    background layers which fit into its tile structure.
    Formerly, only background images with dimensions
    which were exact multiples of the tile size were permitted.
    We have a couple of workarounds now:

    * "Bloating" the background by repetition (pixel-perfect)
    * Scaling the image down to fit (distorts the image)

    """
    filename_display = _filename_to_display(filename)
    load_errors = []
    try:
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
    except Exception as ex:
        logger.error("Failed to load background %r: %s", filename, ex)
        msg = unicode(_(
            'Gdk-Pixbuf couldn\'t load "{filename}", and reported "{error}"'
        ))
        load_errors.append(msg.format(
            filename=filename_display,
            error=repr(ex),
        ))
        return (None, load_errors)
    # Validity check
    w, h = pixbuf.get_width(), pixbuf.get_height()
    if w == 0 or h == 0:
        msg = unicode(_("{filename} has zero size (w={w}, h={h})"))
        load_errors.append(msg.format(
            filename=filename_display,
            w=w, h=h,
        ))
        return (None, load_errors)
    # Flatten
    if pixbuf.get_has_alpha():
        logger.warning(
            "%r has an alpha channel, which should be removed manually",
            filename,
        )
        new_pixbuf = new_blank_pixbuf((0, 0, 0), w, h)
        pixbuf.composite(
            dest=new_pixbuf,
            dest_x=0, dest_y=0,
            dest_width=w, dest_height=h,
            offset_x=0, offset_y=0,
            scale_x=1.0, scale_y=1.0,
            interp_type=GdkPixbuf.InterpType.NEAREST,
            overall_alpha=255,
        )
        pixbuf = new_pixbuf
        logger.debug(
            "Flattened %s by compositing it onto a black backdrop",
            filename,
        )
    # Attempt to fit the image into our grid.
    exact_fit = ((w % N, h % N) == (0, 0))
    if not exact_fit:
        logger.warning(
            "%r (%dx%d) does not fit the %dx%d tile grid exactly",
            filename,
            w, h,
            N, N,
        )
        repeats_x = _best_nrepeats_for_scaling(w, bloatmax)
        repeats_y = _best_nrepeats_for_scaling(h, bloatmax)
        if repeats_x > 1 or repeats_y > 1:
            logger.info(
                "Tiling %r to %dx%d (was: %dx%d, repeats: %d vert, %d horiz)",
                filename,
                w * repeats_x, h * repeats_y,
                w, h,
                repeats_x, repeats_y,
            )
            pixbuf = _tile_pixbuf(pixbuf, repeats_x, repeats_y)
        w, h = pixbuf.get_width(), pixbuf.get_height()
        if (w % N != 0) or (h % N != 0):
            orig_w, orig_h = w, h
            w = max(1, w // N) * N
            h = max(1, h // N) * N
            logger.info(
                "Scaling %r to %dx%d (was: %dx%d)",
                filename,
                w, h,
                orig_w, orig_h,
            )
            pixbuf = pixbuf.scale_simple(
                dest_width=w, dest_height=h,
                interp_type=GdkPixbuf.InterpType.BILINEAR,
            )
        assert (w % N == 0) and (h % N == 0)
    if load_errors:
        pixbuf = None
    return pixbuf, load_errors
コード例 #11
0
 filename_display = _filename_to_display(filename)
 load_errors = []
 try:
     pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
 except Exception, ex:
     logger.error("Failed to load background %r: %s", filename, ex)
     msg = unicode(_(
         'Gdk-Pixbuf couldn\'t load "{filename}", and reported "{error}"'
     ))
     load_errors.append(msg.format(
         filename=filename_display,
         error=repr(ex),
     ))
     return (None, load_errors)
 # Validity check
 w, h = pixbuf.get_width(), pixbuf.get_height()
 if w == 0 or h == 0:
     msg = unicode(_("{filename} has zero size (w={w}, h={h})"))
     load_errors.append(msg.format(
         filename=filename_display,
         w=w, h=h,
     ))
     return (None, load_errors)
 # Flatten
 if pixbuf.get_has_alpha():
     logger.warning(
         "%r has an alpha channel, which should be removed manually",
         filename,
     )
     new_pixbuf = new_blank_pixbuf((0, 0, 0), w, h)
     pixbuf.composite(