def _get_pixbuf(self, index):
        """Return the pixbuf indexed by <index> from cache.
        Pixbufs not found in cache are fetched from disk first.
        """
        if index not in self._raw_pixbufs:
            self._wait_on_page(index + 1)
            pxb_err = False
            try:
                """ Check for gif in the name of the file.  If it is a gif,
                and the user wishes GIFs to be animated, load it as a
                PixbufAnimation and make sure that it actually is animated. 
                If it isn't animated, load a pixbuf instead.  """
                if not (prefs['animate gifs'] or prefs['animate']) \
                    or "gif" not in self._image_files[index][-3:].lower():
                    self._raw_pixbufs[index] = gtk.gdk.pixbuf_new_from_file(
                        self._image_files[index])
                else:
                    self._raw_pixbufs[index] = gtk.gdk.PixbufAnimation(
                        self._image_files[index])
                    if self._raw_pixbufs[index].is_static_image():
                        self._raw_pixbufs[index] = self._raw_pixbufs[
                            index].get_static_image()
            except Exception:
                pxb_err = True

            if pxb_err:
                try:
                    im = image.Image.open(self._image_files[index])
                    self._raw_pixbufs[index] = image.pil_to_pixbuf(im)
                except Exception:
                    self._raw_pixbufs[index] = self._get_missing_image()
        return self._raw_pixbufs[index]
    def _get_pixbuf(self, index):
        """Return the pixbuf indexed by <index> from cache.
        Pixbufs not found in cache are fetched from disk first.
        """
        if index not in self._raw_pixbufs:
            self._wait_on_page(index + 1)
            pxb_err = False
            try:
                """ Check for gif in the name of the file.  If it is a gif,
                and the user wishes GIFs to be animated, load it as a
                PixbufAnimation and make sure that it actually is animated. 
                If it isn't animated, load a pixbuf instead.  """
                if not (prefs['animate gifs'] or prefs['animate']) \
                    or "gif" not in self._image_files[index][-3:].lower():
                    self._raw_pixbufs[index] = gtk.gdk.pixbuf_new_from_file(self._image_files[index])
                else:
                    self._raw_pixbufs[index] = gtk.gdk.PixbufAnimation(self._image_files[index])
                    if self._raw_pixbufs[index].is_static_image():
                        self._raw_pixbufs[index] = self._raw_pixbufs[index].get_static_image()
            except Exception:
                pxb_err = True

            if pxb_err:
                try:
                    im = image.Image.open( self._image_files[index] )
                    self._raw_pixbufs[index] = image.pil_to_pixbuf( im )
                except Exception:
                    self._raw_pixbufs[index] = self._get_missing_image()
        return self._raw_pixbufs[index]
Beispiel #3
0
def draw_histogram(pixbuf, height=170, fill=170, text=True):
    """Draw a histogram from <pixbuf> and return it as another pixbuf.

    The returned prixbuf will be 262x<height> px.

    The value of <fill> determines the colour intensity of the filled graphs,
    valid values are between 0 and 255.

    If <text> is True a label with the maximum pixel value will be added to
    one corner.
    """
    im = Image.new('RGB', (258, height - 4), (30, 30, 30))
    hist_data = image.pixbuf_to_pil(pixbuf).histogram()
    maximum = max(hist_data[:768] + [1])
    y_scale = float(height - 6) / maximum
    r = [int(hist_data[n] * y_scale) for n in xrange(256)]
    g = [int(hist_data[n] * y_scale) for n in xrange(256, 512)]
    b = [int(hist_data[n] * y_scale) for n in xrange(512, 768)]
    im_data = im.getdata()
    # Draw the filling colours
    for x in xrange(256):
        for y in xrange(1, max(r[x], g[x], b[x]) + 1):
            r_px = y <= r[x] and fill or 0
            g_px = y <= g[x] and fill or 0
            b_px = y <= b[x] and fill or 0
            im_data.putpixel((x + 1, height - 5 - y), (r_px, g_px, b_px))
    # Draw the outlines
    for x in xrange(1, 256):
        for y in range(r[x-1] + 1, r[x] + 1) + [r[x]] * (r[x] != 0):
            r_px, g_px, b_px = im_data.getpixel((x + 1, height - 5 - y))
            im_data.putpixel((x + 1, height - 5 - y), (255, g_px, b_px))
        for y in range(r[x] + 1, r[x-1] + 1):
            r_px, g_px, b_px = im_data.getpixel((x, height - 5 - y))
            im_data.putpixel((x, height - 5 - y), (255, g_px, b_px))
        for y in range(g[x-1] + 1, g[x] + 1) + [g[x]] * (g[x] != 0):
            r_px, g_px, b_px = im_data.getpixel((x + 1, height - 5 - y))
            im_data.putpixel((x + 1, height - 5 - y), (r_px, 255, b_px))
        for y in range(g[x] + 1, g[x-1] + 1):
            r_px, g_px, b_px = im_data.getpixel((x, height - 5 - y))
            im_data.putpixel((x, height - 5 - y), (r_px, 255, b_px))
        for y in range(b[x-1] + 1, b[x] + 1) + [b[x]] * (b[x] != 0):
            r_px, g_px, b_px = im_data.getpixel((x + 1, height - 5 - y))
            im_data.putpixel((x + 1, height - 5 - y), (r_px, g_px, 255))
        for y in range(b[x] + 1, b[x-1] + 1):
            r_px, g_px, b_px = im_data.getpixel((x, height - 5 - y))
            im_data.putpixel((x, height - 5 - y), (r_px, g_px, 255))
    if text:
        maxstr = 'max: ' + str(maximum)
        draw = ImageDraw.Draw(im)
        draw.rectangle((0, 0, len(maxstr) * 6 + 2, 10), fill=(30, 30, 30))
        draw.text((2, 0), maxstr, fill=(255, 255, 255))
    im = ImageOps.expand(im, 1, (80, 80, 80))
    im = ImageOps.expand(im, 1, (0, 0, 0))
    return image.pil_to_pixbuf(im)
Beispiel #4
0
    def _drag_begin(self, iconview, context):
        """Create a cursor image for drag-n-drop from the library.

        This method relies on implementation details regarding PIL's 
        drawing functions and default font to produce good looking results.
        If those are changed in a future release of PIL, this method might
        produce bad looking output (e.g. non-centered text).
        
        It's also used with connect_after() to overwrite the cursor
        automatically created when using enable_model_drag_source(), so in
        essence it's a hack, but at least it works.
        """
        icon_path = iconview.get_cursor()[0]
        num_books = len(iconview.get_selected_items())
        book = self.get_book_at_path(icon_path)

        cover = self._library.backend.get_book_cover(book)
        if cover is None:
            cover = self._library.render_icon(gtk.STOCK_MISSING_IMAGE,
                gtk.ICON_SIZE_DIALOG)
        cover = cover.scale_simple(max(0, cover.get_width() // 2),
            max(0, cover.get_height() // 2), gtk.gdk.INTERP_TILES)
        cover = image.add_border(cover, 1, 0xFFFFFFFF)
        cover = image.add_border(cover, 1)
        
        if num_books > 1:
            cover_width = cover.get_width()
            cover_height = cover.get_height()
            pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
                max(30, cover_width + 15), max(30, cover_height + 10))
            pointer.fill(0x00000000)
            cover.composite(pointer, 0, 0, cover_width, cover_height, 0, 0,
            1, 1, gtk.gdk.INTERP_TILES, 255)
            im = Image.new('RGBA', (30, 30), 0x00000000)
            draw = ImageDraw.Draw(im)
            draw.polygon(
                (8, 0, 20, 0, 28, 8, 28, 20, 20, 28, 8, 28, 0, 20, 0, 8),
                fill=(0, 0, 0), outline=(0, 0, 0))
            draw.polygon(
                (8, 1, 20, 1, 27, 8, 27, 20, 20, 27, 8, 27, 1, 20, 1, 8),
                fill=(128, 0, 0), outline=(255, 255, 255))
            text = str(num_books)
            draw.text((15 - (6 * len(text) // 2), 9), text,
                fill=(255, 255, 255))
            circle = image.pil_to_pixbuf(im)
            circle.composite(pointer, max(0, cover_width - 15),
                max(0, cover_height - 20), 30, 30, max(0, cover_width - 15),
                max(0, cover_height - 20), 1, 1, gtk.gdk.INTERP_TILES, 255)
        else:
            pointer = cover

        context.set_icon_pixbuf(pointer, -5, -5)
Beispiel #5
0
def _add_page_number(pixbuf, page):
    """Add page number <page> in a black rectangle in the top left corner of
    <pixbuf>. This is highly dependent on the dimensions of the built-in
    font in PIL (bad). If the PIL font was changed, this function would
    likely produce badly positioned numbers on the pixbuf.
    """
    text = str(page)
    width = min(6 * len(text) + 2, pixbuf.get_width())
    height = min(10, pixbuf.get_height())
    im = Image.new('RGB', (width, height), (0, 0, 0))
    draw = ImageDraw.Draw(im)
    draw.text((1, -1), text, fill=(255, 255, 255))
    num_pixbuf = image.pil_to_pixbuf(im)
    num_pixbuf.copy_area(0, 0, width, height, pixbuf, 0, 0)
Beispiel #6
0
    def _drag_begin(self, iconview, context):
        """Create a cursor image for drag-n-drop from the library.

        This method relies on implementation details regarding PIL's 
        drawing functions and default font to produce good looking results.
        If those are changed in a future release of PIL, this method might
        produce bad looking output (e.g. non-centered text).
        
        It's also used with connect_after() to overwrite the cursor
        automatically created when using enable_model_drag_source(), so in
        essence it's a hack, but at least it works.
        """
        icon_path = iconview.get_cursor()[0]
        num_books = len(iconview.get_selected_items())
        book = self.get_book_at_path(icon_path)

        cover = self._library.backend.get_book_cover(book)
        if cover is None:
            cover = self._library.render_icon(gtk.STOCK_MISSING_IMAGE,
                                              gtk.ICON_SIZE_DIALOG)
        cover = cover.scale_simple(max(0,
                                       cover.get_width() // 2),
                                   max(0,
                                       cover.get_height() // 2),
                                   gtk.gdk.INTERP_TILES)
        cover = image.add_border(cover, 1, 0xFFFFFFFF)
        cover = image.add_border(cover, 1)

        if num_books > 1:
            cover_width = cover.get_width()
            cover_height = cover.get_height()
            pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
                                     max(30, cover_width + 15),
                                     max(30, cover_height + 10))
            pointer.fill(0x00000000)
            cover.composite(pointer, 0, 0, cover_width, cover_height, 0, 0, 1,
                            1, gtk.gdk.INTERP_TILES, 255)
            im = Image.new('RGBA', (30, 30), 0x00000000)
            draw = ImageDraw.Draw(im)
            draw.polygon(
                (8, 0, 20, 0, 28, 8, 28, 20, 20, 28, 8, 28, 0, 20, 0, 8),
                fill=(0, 0, 0),
                outline=(0, 0, 0))
            draw.polygon(
                (8, 1, 20, 1, 27, 8, 27, 20, 20, 27, 8, 27, 1, 20, 1, 8),
                fill=(128, 0, 0),
                outline=(255, 255, 255))
            text = str(num_books)
            draw.text((15 - (6 * len(text) // 2), 9),
                      text,
                      fill=(255, 255, 255))
            circle = image.pil_to_pixbuf(im)
            circle.composite(pointer, max(0, cover_width - 15),
                             max(0, cover_height - 20), 30, 30,
                             max(0,
                                 cover_width - 15), max(0, cover_height - 20),
                             1, 1, gtk.gdk.INTERP_TILES, 255)
        else:
            pointer = cover

        context.set_icon_pixbuf(pointer, -5, -5)