Example #1
0
 def test_fit_in_rectangle_transparent_no_resize(self):
     # And with a transparent test image, check alpha blending.
     image = 'pattern-transparent-rgba.png'
     control = Image.open(get_image_path(image))
     # Create checkerboard background.
     checker_bg = Image.new('RGBA', control.size)
     checker = Image.open(get_image_path('checkerboard.png'))
     for x in range(0, control.size[0], checker.size[0]):
         for y in range(0, control.size[1], checker.size[1]):
             checker_bg.paste(checker, (x, y))
     # Create whhite background.
     white_bg = Image.new('RGBA', control.size, color='white')
     assert control.size == white_bg.size
     width, height = control.size
     for use_checker_bg in (False, True):
         prefs['checkered bg for transparent images'] = use_checker_bg
         expected = Image.alpha_composite(
             checker_bg if use_checker_bg else white_bg, control)
         for scaling_quality in range(4):
             prefs['scaling quality'] = scaling_quality
             result = image_tools.fit_in_rectangle(
                 image_tools.pil_to_pixbuf(control),
                 width,
                 height,
                 scaling_quality=scaling_quality)
             msg = (
                 'fit_in_rectangle("%s", scaling quality=%d, background=%s) failed; '
                 'result %%(diff_type)s differs: %%(diff)s' %
                 (image, scaling_quality,
                  'checker' if checker_bg else 'white'))
             self.assertImagesEqual(result, expected, msg=msg)
Example #2
0
 def test_fit_in_rectangle_transparent_no_resize(self):
     # And with a transparent test image, check alpha blending.
     image = 'pattern-transparent-rgba.png'
     control = Image.open(get_image_path(image))
     # Create checkerboard background.
     checker_bg = Image.new('RGBA', control.size)
     checker = Image.open(get_image_path('checkerboard.png'))
     for x in range(0, control.size[0], checker.size[0]):
         for y in range(0, control.size[1], checker.size[1]):
             checker_bg.paste(checker, (x, y))
     # Create whhite background.
     white_bg = Image.new('RGBA', control.size, color='white')
     assert control.size == white_bg.size
     width, height = control.size
     for use_checker_bg in (False, True):
         prefs['checkered bg for transparent images'] = use_checker_bg
         expected = Image.alpha_composite(
             checker_bg if use_checker_bg else white_bg,
             control
         )
         for scaling_quality in range(4):
             prefs['scaling quality'] = scaling_quality
             result = image_tools.fit_in_rectangle(image_tools.pil_to_pixbuf(control),
                                                   width, height,
                                                   scaling_quality=scaling_quality)
             msg = (
                 'fit_in_rectangle("%s", scaling quality=%d, background=%s) failed; '
                 'result %%(diff_type)s differs: %%(diff)s'
                 % (image, scaling_quality, 'checker' if checker_bg else 'white')
             )
             self.assertImagesEqual(result, expected, msg=msg)
Example #3
0
    def _get_pixbuf(self, uid):
        """ Get or create the thumbnail for the selected book <uid>. """
        assert isinstance(uid, int)
        book = self._library.backend.get_book_by_id(uid)
        if self._cache.exists(book.path):
            pixbuf = self._cache.get(book.path)
        else:
            width, height = self._pixbuf_size(border_size=0)
            pixbuf = self._library.backend.get_book_thumbnail(book.path) or image_tools.MISSING_IMAGE_ICON
            pixbuf = image_tools.fit_in_rectangle(pixbuf, width, height, scale_up=True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(book.path, pixbuf)

        # Display indicator of having finished reading the book.
        # This information isn't cached in the pixbuf cache, as it changes frequently.

        # Anything smaller than 50px means that the status icon will not fit
        if prefs['library cover size'] < 50:
            return pixbuf

        last_read_page = book.get_last_read_page()
        if last_read_page is None or last_read_page != book.pages:
            return pixbuf

        # Composite icon on the lower right corner of the book cover pixbuf.
        book_pixbuf = self.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_LARGE_TOOLBAR)
        translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1
        translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1
        book_pixbuf.composite(pixbuf, translation_x, translation_y,
                              book_pixbuf.get_width(), book_pixbuf.get_height(),
                              translation_x, translation_y,
                              1.0, 1.0, gtk.gdk.INTERP_NEAREST, 0xFF)

        return pixbuf
Example #4
0
    def _get_pixbuf(self, uid):
        ''' Get or create the thumbnail for the selected book <uid>. '''
        assert isinstance(uid, int)
        book = self._library.backend.get_book_by_id(uid)
        if self._cache.exists(book.path):
            pixbuf = self._cache.get(book.path)
        else:
            width, height = self._pixbuf_size(border_size=0)
            # cover thumbnail of book
            cover = self._library.backend.get_book_thumbnail(book.path)
            if not cover:
                cover = image_tools.MISSING_IMAGE_ICON
            cover = image_tools.fit_in_rectangle(cover,
                                                 width - 2,
                                                 height - 2,
                                                 scale_up=True)
            cover = image_tools.add_border(cover, 1, 0xFFFFFFFF)
            src_width, src_height = cover.get_width(), cover.get_height()
            # icon background of book
            pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8,
                                          width, height)
            pixbuf.fill(0x00000000)  # full transparency
            offset_x = (width - src_width) // 2
            offset_y = (height - src_height) // 2
            cover.copy_area(0, 0, src_width, src_height, pixbuf, offset_x,
                            offset_y)
            self._cache.add(book.path, pixbuf)

        # Display indicator of having finished reading the book.
        # This information isn't cached in the pixbuf cache
        # as it changes frequently.

        # Anything smaller than 50px means that the status icon will not fit
        if prefs['library cover size'] < 50:
            return pixbuf

        last_read_page = book.get_last_read_page()
        if last_read_page is None or last_read_page != book.pages:
            return pixbuf

        # Composite icon on the lower right corner of the book cover pixbuf.
        book_pixbuf = self.render_icon(Gtk.STOCK_APPLY,
                                       Gtk.IconSize.LARGE_TOOLBAR)
        translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1
        translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1
        book_pixbuf.composite(pixbuf, translation_x, translation_y,
                              book_pixbuf.get_width(),
                              book_pixbuf.get_height(), translation_x,
                              translation_y, 1.0, 1.0,
                              GdkPixbuf.InterpType.NEAREST, 0xFF)

        return pixbuf
Example #5
0
    def add_extra_image(self, path):
        """Add an imported image (at <path>) to the end of the image list."""
        thumbnailer = thumbnail_tools.Thumbnailer()
        thumbnailer.set_store_on_disk(False)
        thumb = thumbnailer.thumbnail(path)

        if thumb is None:
            thumb = self.render_icon(gtk.STOCK_MISSING_IMAGE,
                gtk.ICON_SIZE_DIALOG)

        thumb = image_tools.fit_in_rectangle(thumb, 128, 128)

        self._liststore.append([thumb, os.path.basename(path), path])
Example #6
0
    def _get_pixbuf(self, path, model, model_path):
        """ Get or create the thumbnail for the selected book at <path>. """
        if self._cache.exists(path):
            return self._cache.get(path)
        else:
            pixbuf = self._library.backend.get_book_thumbnail(path) or constants.MISSING_IMAGE_ICON
            # The ratio (0.67) is just above the normal aspect ratio for books.
            pixbuf = image_tools.fit_in_rectangle(pixbuf,
                int(0.67 * prefs['library cover size']),
                prefs['library cover size'], True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(path, pixbuf)

            return pixbuf
Example #7
0
    def _get_pixbuf(self, path):
        """ Get or create the thumbnail for the selected book at <path>. """
        if self._cache.exists(path):
            return self._cache.get(path)
        else:
            pixbuf = self._library.backend.get_book_thumbnail(
                path) or constants.MISSING_IMAGE_ICON
            # The ratio (0.67) is just above the normal aspect ratio for books.
            pixbuf = image_tools.fit_in_rectangle(
                pixbuf, int(0.67 * prefs['library cover size']),
                prefs['library cover size'], True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(path, pixbuf)

            return pixbuf
Example #8
0
 def test_fit_in_rectangle_opaque_no_resize(self):
     # Check opaque image is unchanged when not resizing.
     for image in (
             'pattern-opaque-rgb.png',
             'pattern-opaque-rgba.png',
     ):
         input = image_tools.load_pixbuf(get_image_path(image))
         width, height = input.get_width(), input.get_height()
         for scaling_quality in range(4):
             prefs['scaling quality'] = scaling_quality
             result = image_tools.fit_in_rectangle(
                 input, width, height, scaling_quality=scaling_quality)
             msg = ('fit_in_rectangle("%s", scaling quality=%d) failed; '
                    'result %%(diff_type)s differs: %%(diff)s' %
                    (image, scaling_quality))
             self.assertImagesEqual(result, input, msg=msg)
Example #9
0
 def test_fit_in_rectangle_dimensions(self):
     # Test dimensions handling.
     for input_size, target_size, scale_up, keep_ratio, expected_size in (
         # Exactly the same size.
         ((200, 100), (200, 100), False, False, (200, 100)),
         ((200, 100), (200, 100), False,  True, (200, 100)),
         ((200, 100), (200, 100),  True, False, (200, 100)),
         ((200, 100), (200, 100),  True,  True, (200, 100)),
         # Smaller.
         ((200, 100), (400, 400), False, False, (200, 100)),
         ((200, 100), (400, 400), False,  True, (200, 100)),
         ((200, 100), (400, 400),  True, False, (400, 400)),
         ((200, 100), (400, 400),  True,  True, (400, 200)),
         # Bigger.
         ((800, 600), (200, 200), False, False, (200, 200)),
         ((800, 600), (200, 200), False,  True, (200, 150)),
         ((800, 600), (200, 200),  True, False, (200, 200)),
         ((800, 600), (200, 200),  True,  True, (200, 150)),
         # One dimension bigger, the other smaller.
         ((200, 400), (200, 200), False, False, (200, 200)),
         ((200, 400), (200, 200), False,  True, (100, 200)),
         ((200, 400), (200, 200),  True, False, (200, 200)),
         ((200, 400), (200, 200),  True,  True, (100, 200)),
     ):
         for invert_dimensions in (False, True):
             if invert_dimensions:
                 input_size = input_size[1], input_size[0]
                 target_size = target_size[1], target_size[0]
                 expected_size = expected_size[1], expected_size[0]
             pixbuf = new_pixbuf(input_size, False, 0)
             result = image_tools.fit_in_rectangle(pixbuf,
                                                   target_size[0],
                                                   target_size[1],
                                                   scale_up=scale_up,
                                                   keep_ratio=keep_ratio)
             result_size = result.get_width(), result.get_height()
             msg = (
                 'fit_in_rectangle(%dx%d => %dx%d, scale up=%s, keep ratio=%s) failed; '
                 'result size differs: %dx%d instead of %dx%d' % (
                     input_size + target_size +
                     (scale_up, keep_ratio) +
                     result_size + expected_size
                 )
             )
             self.assertEqual(result_size, expected_size, msg=msg)
Example #10
0
 def test_fit_in_rectangle_dimensions(self):
     # Test dimensions handling.
     for input_size, target_size, scale_up, keep_ratio, expected_size in (
         # Exactly the same size.
         ((200, 100), (200, 100), False, False, (200, 100)),
         ((200, 100), (200, 100), False,  True, (200, 100)),
         ((200, 100), (200, 100),  True, False, (200, 100)),
         ((200, 100), (200, 100),  True,  True, (200, 100)),
         # Smaller.
         ((200, 100), (400, 400), False, False, (200, 100)),
         ((200, 100), (400, 400), False,  True, (200, 100)),
         ((200, 100), (400, 400),  True, False, (400, 400)),
         ((200, 100), (400, 400),  True,  True, (400, 200)),
         # Bigger.
         ((800, 600), (200, 200), False, False, (200, 200)),
         ((800, 600), (200, 200), False,  True, (200, 150)),
         ((800, 600), (200, 200),  True, False, (200, 200)),
         ((800, 600), (200, 200),  True,  True, (200, 150)),
         # One dimension bigger, the other smaller.
         ((200, 400), (200, 200), False, False, (200, 200)),
         ((200, 400), (200, 200), False,  True, (100, 200)),
         ((200, 400), (200, 200),  True, False, (200, 200)),
         ((200, 400), (200, 200),  True,  True, (100, 200)),
     ):
         for invert_dimensions in (False, True):
             if invert_dimensions:
                 input_size = input_size[1], input_size[0]
                 target_size = target_size[1], target_size[0]
                 expected_size = expected_size[1], expected_size[0]
             pixbuf = new_pixbuf(input_size, False, 0)
             result = image_tools.fit_in_rectangle(pixbuf,
                                                   target_size[0],
                                                   target_size[1],
                                                   scale_up=scale_up,
                                                   keep_ratio=keep_ratio)
             result_size = result.get_width(), result.get_height()
             msg = (
                 'fit_in_rectangle(%dx%d => %dx%d, scale up=%s, keep ratio=%s) failed; '
                 'result size differs: %dx%d instead of %dx%d' % (
                     input_size + target_size +
                     (scale_up, keep_ratio) +
                     result_size + expected_size
                 )
             )
             self.assertEqual(result_size, expected_size, msg=msg)
Example #11
0
 def test_fit_in_rectangle_opaque_no_resize(self):
     # Check opaque image is unchanged when not resizing.
     for image in (
         'pattern-opaque-rgb.png',
         'pattern-opaque-rgba.png',
     ):
         input = image_tools.load_pixbuf(get_image_path(image))
         width, height = input.get_width(), input.get_height()
         for scaling_quality in range(4):
             prefs['scaling quality'] = scaling_quality
             result = image_tools.fit_in_rectangle(input, width, height,
                                                   scaling_quality=scaling_quality)
             msg = (
                 'fit_in_rectangle("%s", scaling quality=%d) failed; '
                 'result %%(diff_type)s differs: %%(diff)s'
                 % (image, scaling_quality)
             )
             self.assertImagesEqual(result, input, msg=msg)
Example #12
0
    def _get_pixbuf(self, uid):
        """ Get or create the thumbnail for the selected book <uid>. """
        assert isinstance(uid, int)
        book = self._library.backend.get_book_by_id(uid)
        if self._cache.exists(book.path):
            pixbuf = self._cache.get(book.path)
        else:
            width, height = self._pixbuf_size(border_size=0)
            pixbuf = self._library.backend.get_book_thumbnail(
                book.path) or image_tools.MISSING_IMAGE_ICON
            pixbuf = image_tools.fit_in_rectangle(pixbuf,
                                                  width,
                                                  height,
                                                  scale_up=True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(book.path, pixbuf)

        # Display indicator of having finished reading the book.
        # This information isn't cached in the pixbuf cache, as it changes frequently.

        # Anything smaller than 50px means that the status icon will not fit
        if prefs['library cover size'] < 50:
            return pixbuf

        last_read_page = book.get_last_read_page()
        if last_read_page is None or last_read_page != book.pages:
            return pixbuf

        # Composite icon on the lower right corner of the book cover pixbuf.
        book_pixbuf = self.render_icon(Gtk.STOCK_APPLY,
                                       Gtk.IconSize.LARGE_TOOLBAR)
        translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1
        translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1
        book_pixbuf.composite(pixbuf, translation_x, translation_y,
                              book_pixbuf.get_width(),
                              book_pixbuf.get_height(), translation_x,
                              translation_y, 1.0, 1.0,
                              GdkPixbuf.InterpType.NEAREST, 0xFF)

        return pixbuf
Example #13
0
    def _get_pixbuf(self, path, model, model_path):
        """ Get or create the thumbnail for the selected book at <path>. """
        if self._cache.exists(path):
            pixbuf = self._cache.get(path)
        else:
            pixbuf = self._library.backend.get_book_thumbnail(
                path) or constants.MISSING_IMAGE_ICON
            # The ratio (0.67) is just above the normal aspect ratio for books.
            pixbuf = image_tools.fit_in_rectangle(
                pixbuf, int(0.67 * prefs['library cover size']),
                prefs['library cover size'], True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(path, pixbuf)

        # Display indicator of having finished reading the book.
        # This information isn't cached in the pixbuf cache, as it changes frequently.

        # Anything smaller than 50px means that the status icon will not fit
        if prefs['library cover size'] < 50:
            return pixbuf

        book = self._library.backend.get_book_by_path(path)
        last_read_page = book.get_last_read_page()

        if last_read_page is None or last_read_page != book.pages:
            return pixbuf
        if last_read_page == book.pages:
            book_pixbuf = self.render_icon(gtk.STOCK_APPLY,
                                           gtk.ICON_SIZE_LARGE_TOOLBAR)

        # Composite icon on the lower right corner of the book cover pixbuf.
        translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1
        translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1
        book_pixbuf.composite(pixbuf, translation_x, translation_y,
                              book_pixbuf.get_width(),
                              book_pixbuf.get_height(), translation_x,
                              translation_y, 1.0, 1.0, gtk.gdk.INTERP_NEAREST,
                              0xFF)

        return pixbuf
Example #14
0
    def _get_pixbuf(self, path, model, model_path):
        """ Get or create the thumbnail for the selected book at <path>. """
        if self._cache.exists(path):
            pixbuf = self._cache.get(path)
        else:
            pixbuf = self._library.backend.get_book_thumbnail(path) or constants.MISSING_IMAGE_ICON
            # The ratio (0.67) is just above the normal aspect ratio for books.
            pixbuf = image_tools.fit_in_rectangle(pixbuf,
                int(0.67 * prefs['library cover size']),
                prefs['library cover size'], True)
            pixbuf = image_tools.add_border(pixbuf, 1, 0xFFFFFFFF)
            self._cache.add(path, pixbuf)

        # Display indicator of having finished reading the book.
        # This information isn't cached in the pixbuf cache, as it changes frequently.

        # Anything smaller than 50px means that the status icon will not fit
        if prefs['library cover size'] < 50:
            return pixbuf

        book = self._library.backend.get_book_by_path(path)
        last_read_page = book.get_last_read_page()

        if last_read_page is None or last_read_page != book.pages:
            return pixbuf
        if last_read_page == book.pages:
            book_pixbuf = self.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_LARGE_TOOLBAR)

        # Composite icon on the lower right corner of the book cover pixbuf.
        translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1
        translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1
        book_pixbuf.composite(pixbuf, translation_x, translation_y,
                              book_pixbuf.get_width(), book_pixbuf.get_height(),
                              translation_x, translation_y,
                              1.0, 1.0, gtk.gdk.INTERP_NEAREST, 0xFF)

        return pixbuf
Example #15
0
    def _draw_image(self, at_bottom, scroll):
        self._display_active_widgets()

        while gtk.events_pending():
            gtk.main_iteration(False)

        if not self.filehandler.file_loaded:
            self._waiting_for_redraw = False
            return False

        area_width, area_height = self.get_visible_area_size()

        if prefs['zoom mode'] == constants.ZOOM_MODE_HEIGHT:
            scaled_width = -1
        else:
            scaled_width = area_width

        if prefs['zoom mode'] == constants.ZOOM_MODE_WIDTH:
            scaled_height = -1
        else:
            scaled_height = area_height

        scale_up = prefs['stretch']
        self.is_virtual_double_page = \
            self.imagehandler.get_virtual_double_page()

        skip_pixbuf = not self.imagehandler.page_is_available()

        if self.displayed_double() and not skip_pixbuf:
            left_pixbuf, right_pixbuf = self.imagehandler.get_pixbufs()
            if self.is_manga_mode:
                right_pixbuf, left_pixbuf = left_pixbuf, right_pixbuf
            left_unscaled_x = left_pixbuf.get_width()
            left_unscaled_y = left_pixbuf.get_height()
            right_unscaled_x = right_pixbuf.get_width()
            right_unscaled_y = right_pixbuf.get_height()

            left_rotation = prefs['rotation']
            right_rotation = prefs['rotation']

            if prefs['auto rotate from exif']:
                left_rotation += image_tools.get_implied_rotation(left_pixbuf)
                left_rotation = left_rotation % 360
                right_rotation += image_tools.get_implied_rotation(
                    right_pixbuf)
                right_rotation = right_rotation % 360

            if prefs['zoom mode'] == constants.ZOOM_MODE_MANUAL:

                if left_rotation in (90, 270):
                    total_width = left_unscaled_y
                    total_height = left_unscaled_x
                else:
                    total_width = left_unscaled_x
                    total_height = left_unscaled_y

                if right_rotation in (90, 270):
                    total_width += right_unscaled_y
                    total_height += right_unscaled_x
                else:
                    total_width += right_unscaled_x
                    total_height += right_unscaled_y

                total_width += 2  # For the 2 px gap between images.
                scaled_width = int(self._manual_zoom * total_width / 100)
                scaled_height = int(self._manual_zoom * total_height / 100)
                scale_up = True

            left_pixbuf, right_pixbuf = image_tools.fit_2_in_rectangle(
                left_pixbuf,
                right_pixbuf,
                scaled_width,
                scaled_height,
                scale_up=scale_up,
                rotation1=left_rotation,
                rotation2=right_rotation)

            if prefs['horizontal flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=True)
                right_pixbuf = right_pixbuf.flip(horizontal=True)

            if prefs['vertical flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=False)
                right_pixbuf = right_pixbuf.flip(horizontal=False)

            left_pixbuf = self.enhancer.enhance(left_pixbuf)
            right_pixbuf = self.enhancer.enhance(right_pixbuf)

            self.left_image.set_from_pixbuf(left_pixbuf)
            self.right_image.set_from_pixbuf(right_pixbuf)

            x_padding = (area_width - left_pixbuf.get_width() -
                         right_pixbuf.get_width()) / 2
            y_padding = (area_height - max(left_pixbuf.get_height(),
                                           right_pixbuf.get_height())) / 2

            if left_rotation in (90, 270):
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                                      left_unscaled_y)
            else:
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                                      left_unscaled_x)

            if right_rotation in (90, 270):
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                                       right_unscaled_y)
            else:
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                                       right_unscaled_x)

            self.statusbar.set_resolution(
                (left_unscaled_x, left_unscaled_y, left_scale_percent),
                (right_unscaled_x, right_unscaled_y, right_scale_percent))

        elif not skip_pixbuf:
            pixbuf = self.imagehandler.get_pixbufs(single=True)[0]
            unscaled_x = pixbuf.get_width()
            unscaled_y = pixbuf.get_height()

            rotation = prefs['rotation']
            if prefs['auto rotate from exif']:
                rotation += image_tools.get_implied_rotation(pixbuf)
                rotation = rotation % 360

            if prefs['zoom mode'] == constants.ZOOM_MODE_MANUAL:
                # If 'Scale small images' is true, scale up the image's base size
                scale_x = max(scale_up and scaled_width or unscaled_x,
                              unscaled_x)
                scale_y = max(scale_up and scaled_height or unscaled_y,
                              unscaled_y)
                scaled_width = int(self._manual_zoom * scale_x / 100)
                scaled_height = int(self._manual_zoom * scale_y / 100)

                if rotation in (90, 270):
                    scaled_width, scaled_height = scaled_height, scaled_width

                scale_up = True

            pixbuf = image_tools.fit_in_rectangle(pixbuf,
                                                  scaled_width,
                                                  scaled_height,
                                                  scale_up=scale_up,
                                                  rotation=rotation)

            if prefs['horizontal flip']:
                pixbuf = pixbuf.flip(horizontal=True)
            if prefs['vertical flip']:
                pixbuf = pixbuf.flip(horizontal=False)

            pixbuf = self.enhancer.enhance(pixbuf)

            self.left_image.set_from_pixbuf(pixbuf)
            self.right_image.clear()

            x_padding = (area_width - pixbuf.get_width()) / 2
            y_padding = (area_height - pixbuf.get_height()) / 2

            if rotation in (90, 270):
                scale_percent = 100.0 * pixbuf.get_width() / unscaled_y
            else:
                scale_percent = 100.0 * pixbuf.get_width() / unscaled_x

            self.statusbar.set_resolution(
                (unscaled_x, unscaled_y, scale_percent))

        if prefs['smart bg'] and not skip_pixbuf:

            bg_colour = self.imagehandler.get_pixbuf_auto_background(
                not self.displayed_double())
            self.set_bg_colour(bg_colour)

            if prefs['smart thumb bg'] and prefs['show thumbnails']:
                self.thumbnailsidebar.change_thumbnail_background_color(
                    bg_colour)

        elif prefs['smart thumb bg'] and prefs[
                'show thumbnails'] and not skip_pixbuf:

            bg_colour = image_tools.get_most_common_edge_colour(
                self.left_image.get_pixbuf())

            self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        if not skip_pixbuf:
            self._image_box.window.freeze_updates()
            self._main_layout.move(self._image_box, max(0, x_padding),
                                   max(0, y_padding))

            self.left_image.show()

            if self.displayed_double():
                self.right_image.show()
            else:
                self.right_image.hide()

            self._main_layout.set_size(*self._image_box.size_request())

            if scroll:
                if at_bottom:
                    self.scroll_to_fixed(horiz='endsecond', vert='bottom')
                else:
                    self.scroll_to_fixed(horiz='startfirst', vert='top')

            self._image_box.window.thaw_updates()
        else:
            # If the pixbuf for the current page(s) isn't available,
            # hide both images to clear any old pixbufs.
            self.left_image.hide()
            self.right_image.hide()

        self._update_page_information()
        self._waiting_for_redraw = False

        while gtk.events_pending():
            gtk.main_iteration(False)

        return False
Example #16
0
    def _draw_image(self, at_bottom, scroll):
        self._display_active_widgets()

        if not self.filehandler.file_loaded:
            self._waiting_for_redraw = False
            return False

        self.is_virtual_double_page = \
            self.imagehandler.get_virtual_double_page()

        skip_pixbuf = not self.imagehandler.page_is_available()

        if self.displayed_double() and not skip_pixbuf:
            left_pixbuf, right_pixbuf = self.imagehandler.get_pixbufs()
            if self.is_manga_mode:
                right_pixbuf, left_pixbuf = left_pixbuf, right_pixbuf
            left_unscaled_x = left_pixbuf.get_width()
            left_unscaled_y = left_pixbuf.get_height()
            right_unscaled_x = right_pixbuf.get_width()
            right_unscaled_y = right_pixbuf.get_height()

            left_rotation = self._get_pixbuf_rotation(left_pixbuf, True)
            right_rotation = self._get_pixbuf_rotation(right_pixbuf, True)

            if left_rotation in (90, 270):
                left_width = left_unscaled_y
                left_height = left_unscaled_x
            else:
                left_width = left_unscaled_x
                left_height = left_unscaled_y

            if right_rotation in (90, 270):
                right_width = right_unscaled_y
                right_height = right_unscaled_x
            else:
                right_width = right_unscaled_x
                right_height = right_unscaled_y

            width, height = image_tools.get_double_page_rectangle(
                left_width, left_height, right_width, right_height)

            scaled_width, scaled_height = self.zoom.get_zoomed_size(
                (width, height), self.get_visible_area_size())

            # Visible area size is recomputed depending on scrollbar visibility
            self._show_scrollbars((scaled_width, scaled_height),
                                  self.get_visible_area_size())
            area_width, area_height = self.get_visible_area_size()
            scaled_width, scaled_height = self.zoom.get_zoomed_size(
                (width, height), (area_width, area_height))

            # 100000 just some big enough constant.
            # We need to ensure that images
            #   are limited only by height during scaling
            left_pixbuf = image_tools.fit_in_rectangle(left_pixbuf, 100000,
                                                       scaled_height,
                                                       prefs['stretch'],
                                                       left_rotation)
            right_pixbuf = image_tools.fit_in_rectangle(
                right_pixbuf, 100000, scaled_height, prefs['stretch'],
                right_rotation)

            if prefs['horizontal flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=True)
                right_pixbuf = right_pixbuf.flip(horizontal=True)

            if prefs['vertical flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=False)
                right_pixbuf = right_pixbuf.flip(horizontal=False)

            left_pixbuf = self.enhancer.enhance(left_pixbuf)
            right_pixbuf = self.enhancer.enhance(right_pixbuf)

            self.left_image.set_from_pixbuf(left_pixbuf)
            self.right_image.set_from_pixbuf(right_pixbuf)

            x_padding = int(
                round((area_width - left_pixbuf.get_width() -
                       right_pixbuf.get_width()) / 2.0))
            y_padding = int(
                round((area_height - max(left_pixbuf.get_height(),
                                         right_pixbuf.get_height())) / 2.0))

            if left_rotation in (90, 270):
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                                      left_unscaled_y)
            else:
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                                      left_unscaled_x)

            if right_rotation in (90, 270):
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                                       right_unscaled_y)
            else:
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                                       right_unscaled_x)

            self.statusbar.set_resolution(
                (left_unscaled_x, left_unscaled_y, left_scale_percent),
                (right_unscaled_x, right_unscaled_y, right_scale_percent))

        elif not skip_pixbuf:
            pixbuf = self.imagehandler.get_pixbufs(single=True)[0]
            width, height = pixbuf.get_width(), pixbuf.get_height()

            rotation = self._get_pixbuf_rotation(pixbuf)
            if rotation in (90, 270):
                width, height = height, width

            scaled_width, scaled_height = self.zoom.get_zoomed_size(
                (width, height), self.get_visible_area_size())

            # Visible area size is recomputed depending on scrollbar visibility
            self._show_scrollbars((scaled_width, scaled_height),
                                  self.get_visible_area_size())
            area_width, area_height = self.get_visible_area_size()
            scaled_width, scaled_height = self.zoom.get_zoomed_size(
                (width, height), (area_width, area_height))

            pixbuf = image_tools.fit_in_rectangle(pixbuf,
                                                  scaled_width,
                                                  scaled_height,
                                                  scale_up=True,
                                                  rotation=rotation)

            if prefs['horizontal flip']:
                pixbuf = pixbuf.flip(horizontal=True)
            if prefs['vertical flip']:
                pixbuf = pixbuf.flip(horizontal=False)

            pixbuf = self.enhancer.enhance(pixbuf)

            self.left_image.set_from_pixbuf(pixbuf)
            self.right_image.clear()

            x_padding = int(round((area_width - pixbuf.get_width()) / 2.0))
            y_padding = int(round((area_height - pixbuf.get_height()) / 2.0))

            if rotation in (90, 270):
                scale_percent = 100.0 * pixbuf.get_width() / height
            else:
                scale_percent = 100.0 * pixbuf.get_width() / width

            self.statusbar.set_resolution((width, height, scale_percent))

        if prefs['smart bg'] and not skip_pixbuf:

            bg_colour = self.imagehandler.get_pixbuf_auto_background(
                not self.displayed_double())
            self.set_bg_colour(bg_colour)

            if prefs['smart thumb bg'] and prefs['show thumbnails']:
                self.thumbnailsidebar.change_thumbnail_background_color(
                    bg_colour)

        elif prefs['smart thumb bg'] and prefs[
                'show thumbnails'] and not skip_pixbuf:

            bg_colour = image_tools.get_most_common_edge_colour(
                self.left_image.get_pixbuf())

            self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        if not skip_pixbuf:
            self._image_box.window.freeze_updates()
            self._main_layout.move(self._image_box, max(0, x_padding),
                                   max(0, y_padding))

            self.left_image.show()

            if self.displayed_double():
                self.right_image.show()
            else:
                self.right_image.hide()

            self._main_layout.set_size(*self._image_box.size_request())

            if scroll:
                if at_bottom:
                    self.scroll_to_fixed(horiz='endsecond', vert='bottom')
                else:
                    self.scroll_to_fixed(horiz='startfirst', vert='top')

            self._image_box.window.thaw_updates()
        else:
            # If the pixbuf for the current page(s) isn't available,
            # hide both images to clear any old pixbufs.
            self.left_image.hide()
            self.right_image.hide()

        self._update_page_information()
        self._waiting_for_redraw = False

        return False
Example #17
0
File: main.py Project: Gosha/mcomix
    def _draw_image(self, at_bottom, scroll):
        self._display_active_widgets()

        if not self.filehandler.file_loaded:
            self._waiting_for_redraw = False
            return False

        self.is_virtual_double_page = self.imagehandler.get_virtual_double_page()

        skip_pixbuf = not self.imagehandler.page_is_available()

        if self.displayed_double() and not skip_pixbuf:
            left_pixbuf, right_pixbuf = self.imagehandler.get_pixbufs()
            if self.is_manga_mode:
                right_pixbuf, left_pixbuf = left_pixbuf, right_pixbuf
            left_unscaled_x = left_pixbuf.get_width()
            left_unscaled_y = left_pixbuf.get_height()
            right_unscaled_x = right_pixbuf.get_width()
            right_unscaled_y = right_pixbuf.get_height()

            left_rotation = self._get_pixbuf_rotation(left_pixbuf, True)
            right_rotation = self._get_pixbuf_rotation(right_pixbuf, True)

            if left_rotation in (90, 270):
                left_width = left_unscaled_y
                left_height = left_unscaled_x
            else:
                left_width = left_unscaled_x
                left_height = left_unscaled_y

            if right_rotation in (90, 270):
                right_width = right_unscaled_y
                right_height = right_unscaled_x
            else:
                right_width = right_unscaled_x
                right_height = right_unscaled_y

            width, height = image_tools.get_double_page_rectangle(left_width, left_height, right_width, right_height)

            scaled_width, scaled_height = self.zoom.get_zoomed_size((width, height), self.get_visible_area_size())

            # Visible area size is recomputed depending on scrollbar visibility
            self._show_scrollbars((scaled_width, scaled_height), self.get_visible_area_size())
            area_width, area_height = self.get_visible_area_size()
            scaled_width, scaled_height = self.zoom.get_zoomed_size((width, height), (area_width, area_height))

            # 100000 just some big enough constant.
            # We need to ensure that images
            #   are limited only by height during scaling
            left_pixbuf = image_tools.fit_in_rectangle(
                left_pixbuf, 100000, scaled_height, prefs["stretch"], left_rotation
            )
            right_pixbuf = image_tools.fit_in_rectangle(
                right_pixbuf, 100000, scaled_height, prefs["stretch"], right_rotation
            )

            if prefs["horizontal flip"]:
                left_pixbuf = left_pixbuf.flip(horizontal=True)
                right_pixbuf = right_pixbuf.flip(horizontal=True)

            if prefs["vertical flip"]:
                left_pixbuf = left_pixbuf.flip(horizontal=False)
                right_pixbuf = right_pixbuf.flip(horizontal=False)

            left_pixbuf = self.enhancer.enhance(left_pixbuf)
            right_pixbuf = self.enhancer.enhance(right_pixbuf)

            self.left_image.set_from_pixbuf(left_pixbuf)
            self.right_image.set_from_pixbuf(right_pixbuf)

            x_padding = int(round((area_width - left_pixbuf.get_width() - right_pixbuf.get_width()) / 2.0))
            y_padding = int(round((area_height - max(left_pixbuf.get_height(), right_pixbuf.get_height())) / 2.0))

            if left_rotation in (90, 270):
                left_scale_percent = 100.0 * left_pixbuf.get_width() / left_unscaled_y
            else:
                left_scale_percent = 100.0 * left_pixbuf.get_width() / left_unscaled_x

            if right_rotation in (90, 270):
                right_scale_percent = 100.0 * right_pixbuf.get_width() / right_unscaled_y
            else:
                right_scale_percent = 100.0 * right_pixbuf.get_width() / right_unscaled_x

            self.statusbar.set_resolution(
                (left_unscaled_x, left_unscaled_y, left_scale_percent),
                (right_unscaled_x, right_unscaled_y, right_scale_percent),
            )

        elif not skip_pixbuf:
            pixbuf = self.imagehandler.get_pixbufs(single=True)[0]
            width, height = pixbuf.get_width(), pixbuf.get_height()

            rotation = self._get_pixbuf_rotation(pixbuf)
            if rotation in (90, 270):
                width, height = height, width

            scaled_width, scaled_height = self.zoom.get_zoomed_size((width, height), self.get_visible_area_size())

            # Visible area size is recomputed depending on scrollbar visibility
            self._show_scrollbars((scaled_width, scaled_height), self.get_visible_area_size())
            area_width, area_height = self.get_visible_area_size()
            scaled_width, scaled_height = self.zoom.get_zoomed_size((width, height), (area_width, area_height))

            pixbuf = image_tools.fit_in_rectangle(pixbuf, scaled_width, scaled_height, scale_up=True, rotation=rotation)

            if prefs["horizontal flip"]:
                pixbuf = pixbuf.flip(horizontal=True)
            if prefs["vertical flip"]:
                pixbuf = pixbuf.flip(horizontal=False)

            pixbuf = self.enhancer.enhance(pixbuf)

            self.left_image.set_from_pixbuf(pixbuf)
            self.right_image.clear()

            x_padding = int(round((area_width - pixbuf.get_width()) / 2.0))
            y_padding = int(round((area_height - pixbuf.get_height()) / 2.0))

            if rotation in (90, 270):
                scale_percent = 100.0 * pixbuf.get_width() / height
            else:
                scale_percent = 100.0 * pixbuf.get_width() / width

            self.statusbar.set_resolution((width, height, scale_percent))

        if prefs["smart bg"] and not skip_pixbuf:

            bg_colour = self.imagehandler.get_pixbuf_auto_background(not self.displayed_double())
            self.set_bg_colour(bg_colour)

            if prefs["smart thumb bg"] and prefs["show thumbnails"]:
                self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        elif prefs["smart thumb bg"] and prefs["show thumbnails"] and not skip_pixbuf:

            bg_colour = image_tools.get_most_common_edge_colour(self.left_image.get_pixbuf())

            self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        if not skip_pixbuf:
            self._image_box.window.freeze_updates()
            self._main_layout.move(self._image_box, max(0, x_padding), max(0, y_padding))

            self.left_image.show()

            if self.displayed_double():
                self.right_image.show()
            else:
                self.right_image.hide()

            self._main_layout.set_size(*self._image_box.size_request())

            if scroll:
                if at_bottom:
                    self.scroll_to_fixed(horiz="endsecond", vert="bottom")
                else:
                    self.scroll_to_fixed(horiz="startfirst", vert="top")

            self._image_box.window.thaw_updates()
        else:
            # If the pixbuf for the current page(s) isn't available,
            # hide both images to clear any old pixbufs.
            self.left_image.hide()
            self.right_image.hide()

        self._update_page_information()
        self._waiting_for_redraw = False

        return False
Example #18
0
 def test_fit_in_rectangle_rotation(self):
     image_size = 128
     rect_size = 32
     # Start with a black image.
     im = Image.new('RGB', (image_size, image_size), color='black')
     draw = ImageDraw.Draw(im)
     # Paint top-left corner white.
     draw.rectangle((0, 0, rect_size, rect_size), fill='white')
     # Corner colors, starting top-left, rotating clock-wise.
     corners_colors = ('white', 'black', 'black', 'black')
     pixbuf = image_tools.pil_to_pixbuf(im)
     for rotation in (0, 90, 180, 270, -90, -180, -270, 90 * 5, -90 * 7):
         for target_size in (
             (image_size, image_size),
             (image_size / 2, image_size / 2),
         ):
             result = image_tools.fit_in_rectangle(pixbuf,
                                                   target_size[0],
                                                   target_size[1],
                                                   rotation=rotation)
             # First check size.
             input_size = (image_size, image_size)
             result_size = result.get_width(), result.get_height()
             msg = ('fit_in_rectangle(%dx%d => %dx%d, rotation=%d) failed; '
                    'result size: %dx%d' % (input_size + target_size +
                                            (rotation, ) + result_size))
             self.assertEqual(result_size, target_size, msg=msg)
             # And then check corners.
             expected_corners_colors = list(corners_colors)
             for _ in range(1, 1 + (rotation % 360) / 90):
                 expected_corners_colors.insert(
                     0, expected_corners_colors.pop(-1))
             result_corners_colors = []
             corner = new_pixbuf((1, 1), False, 0x888888)
             corners_positions = [
                 0, 0, target_size[0] - 1, target_size[0] - 1
             ]
             for _ in range(4):
                 x, y = corners_positions[0:2]
                 result.copy_area(x, y, 1, 1, corner, 0, 0)
                 color = corner.get_pixels()[0:3]
                 color = binascii.hexlify(color)
                 if 'ffffff' == color:
                     color = 'white'
                 elif '000000' == color:
                     color = 'black'
                 result_corners_colors.append(color)
                 corners_positions.insert(0, corners_positions.pop(-1))
             # Swap bottom corners for spatial display.
             result_corners_colors.append(result_corners_colors.pop(-2))
             expected_corners_colors.append(expected_corners_colors.pop(-2))
             msg = ('fit_in_rectangle(%dx%d => %dx%d, rotation=%d) failed; '
                    'result corners differs:\n'
                    '%s\t%s\n'
                    '%s\t%s\n'
                    'instead of:\n'
                    '%s\t%s\n'
                    '%s\t%s\n' %
                    (input_size + target_size +
                     (rotation, ) + tuple(result_corners_colors) +
                     tuple(expected_corners_colors)))
             self.assertEqual(result_corners_colors,
                              expected_corners_colors,
                              msg=msg)
Example #19
0
    def _draw_image(self, at_bottom, scroll):
        self._display_active_widgets()

        while gtk.events_pending():
            gtk.main_iteration(False)

        if not self.filehandler.file_loaded:
            self._waiting_for_redraw = False
            return False

        area_width, area_height = self.get_visible_area_size()

        if prefs['zoom mode'] == constants.ZOOM_MODE_HEIGHT:
            scaled_width = -1
        else:
            scaled_width = area_width

        if prefs['zoom mode'] == constants.ZOOM_MODE_WIDTH:
            scaled_height = -1
        else:
            scaled_height = area_height

        scale_up = prefs['stretch']
        self.is_virtual_double_page = \
            self.imagehandler.get_virtual_double_page()

        skip_pixbuf = not self.imagehandler.page_is_available()

        if self.displayed_double() and not skip_pixbuf:
            left_pixbuf, right_pixbuf = self.imagehandler.get_pixbufs()
            if self.is_manga_mode:
                right_pixbuf, left_pixbuf = left_pixbuf, right_pixbuf
            left_unscaled_x = left_pixbuf.get_width()
            left_unscaled_y = left_pixbuf.get_height()
            right_unscaled_x = right_pixbuf.get_width()
            right_unscaled_y = right_pixbuf.get_height()

            left_rotation = prefs['rotation']
            right_rotation = prefs['rotation']

            if prefs['auto rotate from exif']:
                left_rotation += image_tools.get_implied_rotation(left_pixbuf)
                left_rotation = left_rotation % 360
                right_rotation += image_tools.get_implied_rotation(right_pixbuf)
                right_rotation = right_rotation % 360

            if prefs['zoom mode'] == constants.ZOOM_MODE_MANUAL:

                if left_rotation in (90, 270):
                    total_width = left_unscaled_y
                    total_height = left_unscaled_x
                else:
                    total_width = left_unscaled_x
                    total_height = left_unscaled_y

                if right_rotation in (90, 270):
                    total_width += right_unscaled_y
                    total_height += right_unscaled_x
                else:
                    total_width += right_unscaled_x
                    total_height += right_unscaled_y

                total_width += 2  # For the 2 px gap between images.
                scaled_width = int(self._manual_zoom * total_width / 100)
                scaled_height = int(self._manual_zoom * total_height / 100)
                scale_up = True

            left_pixbuf, right_pixbuf = image_tools.fit_2_in_rectangle(
                left_pixbuf, right_pixbuf, scaled_width, scaled_height,
                scale_up=scale_up, rotation1=left_rotation,
                rotation2=right_rotation)

            if prefs['horizontal flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=True)
                right_pixbuf = right_pixbuf.flip(horizontal=True)

            if prefs['vertical flip']:
                left_pixbuf = left_pixbuf.flip(horizontal=False)
                right_pixbuf = right_pixbuf.flip(horizontal=False)

            left_pixbuf = self.enhancer.enhance(left_pixbuf)
            right_pixbuf = self.enhancer.enhance(right_pixbuf)

            self.left_image.set_from_pixbuf(left_pixbuf)
            self.right_image.set_from_pixbuf(right_pixbuf)

            x_padding = (area_width - left_pixbuf.get_width() -
                right_pixbuf.get_width()) / 2
            y_padding = (area_height - max(left_pixbuf.get_height(),
                right_pixbuf.get_height())) / 2

            if left_rotation in (90, 270):
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                    left_unscaled_y)
            else:
                left_scale_percent = (100.0 * left_pixbuf.get_width() /
                    left_unscaled_x)

            if right_rotation in (90, 270):
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                    right_unscaled_y)
            else:
                right_scale_percent = (100.0 * right_pixbuf.get_width() /
                    right_unscaled_x)

            self.statusbar.set_resolution(
                (left_unscaled_x, left_unscaled_y, left_scale_percent),
                (right_unscaled_x, right_unscaled_y, right_scale_percent))

        elif not skip_pixbuf:
            pixbuf = self.imagehandler.get_pixbufs(single=True)[ 0 ]
            unscaled_x = pixbuf.get_width()
            unscaled_y = pixbuf.get_height()

            rotation = prefs['rotation']
            if prefs['auto rotate from exif']:
                rotation += image_tools.get_implied_rotation(pixbuf)
                rotation = rotation % 360

            if prefs['zoom mode'] == constants.ZOOM_MODE_MANUAL:
                # If 'Scale small images' is true, scale up the image's base size
                scale_x = max(scale_up and scaled_width or unscaled_x, unscaled_x)
                scale_y = max(scale_up and scaled_height or unscaled_y, unscaled_y)
                scaled_width = int(self._manual_zoom * scale_x / 100)
                scaled_height = int(self._manual_zoom * scale_y / 100)

                if rotation in (90, 270):
                    scaled_width, scaled_height = scaled_height, scaled_width

                scale_up = True

            pixbuf = image_tools.fit_in_rectangle(pixbuf, scaled_width,
                scaled_height, scale_up=scale_up, rotation=rotation)

            if prefs['horizontal flip']:
                pixbuf = pixbuf.flip(horizontal=True)
            if prefs['vertical flip']:
                pixbuf = pixbuf.flip(horizontal=False)

            pixbuf = self.enhancer.enhance(pixbuf)

            self.left_image.set_from_pixbuf(pixbuf)
            self.right_image.clear()

            x_padding = (area_width - pixbuf.get_width()) / 2
            y_padding = (area_height - pixbuf.get_height()) / 2

            if rotation in (90, 270):
                scale_percent = 100.0 * pixbuf.get_width() / unscaled_y
            else:
                scale_percent = 100.0 * pixbuf.get_width() / unscaled_x

            self.statusbar.set_resolution((unscaled_x, unscaled_y,
                scale_percent))

        if prefs['smart bg'] and not skip_pixbuf:

            bg_colour = self.imagehandler.get_pixbuf_auto_background(
                    not self.displayed_double())
            self.set_bg_colour(bg_colour)

            if prefs['smart thumb bg'] and prefs['show thumbnails']:
                self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        elif prefs['smart thumb bg'] and prefs['show thumbnails'] and not skip_pixbuf:

            bg_colour = image_tools.get_most_common_edge_colour(
                            self.left_image.get_pixbuf())

            self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

        if not skip_pixbuf:
            self._image_box.window.freeze_updates()
            self._main_layout.move(self._image_box, max(0, x_padding),
                max(0, y_padding))

            self.left_image.show()

            if self.displayed_double():
                self.right_image.show()
            else:
                self.right_image.hide()

            self._main_layout.set_size(*self._image_box.size_request())

            if scroll:
                if at_bottom:
                    self.scroll_to_fixed(horiz='endsecond', vert='bottom')
                else:
                    self.scroll_to_fixed(horiz='startfirst', vert='top')

            self._image_box.window.thaw_updates()
        else:
            # If the pixbuf for the current page(s) isn't available,
            # hide both images to clear any old pixbufs.
            self.left_image.hide()
            self.right_image.hide()

        self._update_page_information()
        self._waiting_for_redraw = False

        while gtk.events_pending():
            gtk.main_iteration(False)

        return False
Example #20
0
 def test_fit_in_rectangle_rotation(self):
     image_size = 128
     rect_size = 32
     # Start with a black image.
     im = Image.new('RGB', (image_size, image_size), color='black')
     draw = ImageDraw.Draw(im)
     # Paint top-left corner white.
     draw.rectangle((0, 0, rect_size, rect_size), fill='white')
     # Corner colors, starting top-left, rotating clock-wise.
     corners_colors = ('white', 'black', 'black', 'black')
     pixbuf = image_tools.pil_to_pixbuf(im)
     for rotation in (
         0, 90, 180, 270,
         -90, -180, -270,
         90 * 5, -90 * 7
     ):
         for target_size in (
             (image_size, image_size),
             (image_size / 2, image_size / 2),
         ):
             result = image_tools.fit_in_rectangle(pixbuf,
                                                   target_size[0],
                                                   target_size[1],
                                                   rotation=rotation)
             # First check size.
             input_size = (image_size, image_size)
             result_size = result.get_width(), result.get_height()
             msg = (
                 'fit_in_rectangle(%dx%d => %dx%d, rotation=%d) failed; '
                 'result size: %dx%d' % (
                     input_size + target_size + (rotation,) + result_size
                 )
             )
             self.assertEqual(result_size, target_size, msg=msg)
             # And then check corners.
             expected_corners_colors = list(corners_colors)
             for _ in range(1, 1 + (rotation % 360) / 90):
                 expected_corners_colors.insert(0, expected_corners_colors.pop(-1))
             result_corners_colors = []
             corner = new_pixbuf((1, 1), False, 0x888888)
             corners_positions = [0, 0, target_size[0] - 1, target_size[0] - 1]
             for _ in range(4):
                 x, y = corners_positions[0:2]
                 result.copy_area(x, y, 1, 1, corner, 0, 0)
                 color = corner.get_pixels()[0:3]
                 color = binascii.hexlify(color)
                 if 'ffffff' == color:
                     color = 'white'
                 elif '000000' == color:
                     color = 'black'
                 result_corners_colors.append(color)
                 corners_positions.insert(0, corners_positions.pop(-1))
             # Swap bottom corners for spatial display.
             result_corners_colors.append(result_corners_colors.pop(-2))
             expected_corners_colors.append(expected_corners_colors.pop(-2))
             msg = (
                 'fit_in_rectangle(%dx%d => %dx%d, rotation=%d) failed; '
                 'result corners differs:\n'
                 '%s\t%s\n'
                 '%s\t%s\n'
                 'instead of:\n'
                 '%s\t%s\n'
                 '%s\t%s\n' % (
                     input_size + target_size + (rotation, ) +
                     tuple(result_corners_colors) +
                     tuple(expected_corners_colors)
                 )
             )
             self.assertEqual(result_corners_colors,
                              expected_corners_colors,
                              msg=msg)