def enhance(self, pixbuf):
        """
        Return an "enhanced" version of <pixbuf>
        """

        if (self.brightness != 1.0 or self.contrast != 1.0 or
                self.saturation != 1.0 or self.sharpness != 1.0 or
                self.autocontrast):
            return ImageTools.enhance(pixbuf, self.brightness, self.contrast,
                                      self.saturation, self.sharpness, self.autocontrast)
        return pixbuf
Esempio n. 2
0
    def _draw_image(self, scroll_to: int):
        # hides old images before showing new ones
        # also if in double page mode and only a single
        # image is going to be shown, prevents a ghost second image
        for i in self.__images:
            i.clear()

        if not self.__file_handler.get_file_loaded():
            self.__thumbnailsidebar.hide()
            self.__waiting_for_redraw = False
            return

        self.__thumbnailsidebar.show()

        if not self.__image_handler.page_is_available():
            # Save scroll destination for when the page becomes available.
            self.__last_scroll_destination = scroll_to
            self.__waiting_for_redraw = False
            return

        distribution_axis = ZoomAxis.DISTRIBUTION.value
        alignment_axis = ZoomAxis.ALIGNMENT.value
        # XXX limited to at most 2 pages
        pixbuf_count = 2 if ViewState.is_displaying_double else 1
        pixbuf_count_iter = range(pixbuf_count)
        pixbuf_list = list(self.__image_handler.get_pixbufs(pixbuf_count))
        do_not_transform = [ImageTools.disable_transform(x) for x in pixbuf_list]
        size_list = [[pixbuf.get_width(), pixbuf.get_height()] for pixbuf in pixbuf_list]

        # Rotation handling:
        # - apply Exif rotation on individual images
        # - apply manual rotation on whole page
        orientation = self.__page_orientation
        if config['AUTO_ROTATE_FROM_EXIF']:
            rotation_list = [ImageTools.get_implied_rotation(pixbuf) for pixbuf in pixbuf_list]
            for i in pixbuf_count_iter:
                if rotation_list[i] in (90, 270):
                    size_list[i].reverse()
        else:
            # no auto rotation
            rotation_list = [0] * len(pixbuf_list)

        rotation = config['ROTATION'] % 360
        match rotation:
            case (90 | 270):
                distribution_axis, alignment_axis = alignment_axis, distribution_axis
                orientation.reverse()
                for i in pixbuf_count_iter:
                    size_list[i].reverse()
            case 180:
                orientation.reverse()

        # Recompute the visible area size
        viewport_size = self.get_visible_area_size()
        zoom_dummy_size = list(viewport_size)
        scaled_sizes = self.__zoom.get_zoomed_size(size_list, zoom_dummy_size, distribution_axis, do_not_transform)

        self.__layout = FiniteLayout(scaled_sizes, viewport_size, orientation, distribution_axis, alignment_axis)

        self.__main_layout.set_size(*self.__layout.get_union_box().get_size())

        content_boxes = self.__layout.get_content_boxes()

        for i in pixbuf_count_iter:
            rotation_list[i] = (rotation_list[i] + rotation) % 360

            pixbuf_list[i] = ImageTools.fit_pixbuf_to_rectangle(pixbuf_list[i], scaled_sizes[i], rotation_list[i])
            pixbuf_list[i] = ImageTools.enhance(pixbuf_list[i])

            ImageTools.set_from_pixbuf(self.__images[i], pixbuf_list[i])

            self.__main_layout.move(self.__images[i], *content_boxes[i].get_position())
            self.__images[i].show()

        # Reset orientation so scrolling behaviour is sane.
        self.__layout.set_orientation(self.__page_orientation)

        if scroll_to is not None:
            destination = (scroll_to,) * 2
            self.scroll_to_predefined(destination)

        # update statusbar
        resolutions = [(*size, scaled_size[0] / size[0]) for scaled_size, size in zip(scaled_sizes, size_list, strict=True)]
        if ViewState.is_manga_mode:
            resolutions.reverse()
        self.__statusbar.set_resolution(resolutions)
        self.__statusbar.update()

        self.__waiting_for_redraw = False
Esempio n. 3
0
    def _add_subpixbuf(self, canvas, x: int, y: int, image_size: tuple, source_pixbuf):
        """
        Copy a subpixbuf from <source_pixbuf> to <canvas> as it should
        be in the lens if the coordinates <x>, <y> are the mouse pointer
        position on the main window layout area.
        The displayed image (scaled from the <source_pixbuf>) must have
        size <image_size>
        """

        # Prevent division by zero exceptions further down
        if not image_size[0]:
            return

        # FIXME This merely prevents Errors being raised if source_pixbuf is an
        # animation. The result might be broken, though, since animation,
        # rotation etc. might not match or will be ignored:
        source_pixbuf = ImageTools.static_image(source_pixbuf)

        rotation = config['ROTATION']
        if config['AUTO_ROTATE_FROM_EXIF']:
            rotation += ImageTools.get_implied_rotation(source_pixbuf)
            rotation %= 360

        if rotation in (90, 270):
            scale = source_pixbuf.get_height() / image_size[0]
        else:
            scale = source_pixbuf.get_width() / image_size[0]

        x *= scale
        y *= scale

        source_mag = config['LENS_MAGNIFICATION'] / scale
        width = height = config['LENS_SIZE'] / source_mag

        paste_left = x > width / 2
        paste_top = y > height / 2
        dest_x = max(0, int(math.ceil((width / 2 - x) * source_mag)))
        dest_y = max(0, int(math.ceil((height / 2 - y) * source_mag)))

        match rotation:
            case 90:
                x, y = y, source_pixbuf.get_height() - x
            case 180:
                x = source_pixbuf.get_width() - x
                y = source_pixbuf.get_height() - y
            case 270:
                x, y = source_pixbuf.get_width() - y, x

        src_x = x - width / 2
        src_y = y - height / 2
        if src_x < 0:
            width += src_x
            src_x = 0
        if src_y < 0:
            height += src_y
            src_y = 0
        width = max(0, min(source_pixbuf.get_width() - src_x, width))
        height = max(0, min(source_pixbuf.get_height() - src_y, height))
        if width < 1 or height < 1:
            return

        subpixbuf = source_pixbuf.new_subpixbuf(int(src_x), int(src_y), int(width), int(height))
        subpixbuf = subpixbuf.scale_simple(
            int(math.ceil(source_mag * subpixbuf.get_width())),
            int(math.ceil(source_mag * subpixbuf.get_height())),
            config['GDK_SCALING_FILTER'])

        subpixbuf = ImageTools.rotate_pixbuf(subpixbuf, rotation)
        subpixbuf = ImageTools.enhance(subpixbuf)

        if paste_left:
            dest_x = 0
        else:
            dest_x = min(canvas.get_width() - subpixbuf.get_width(), dest_x)
        if paste_top:
            dest_y = 0
        else:
            dest_y = min(canvas.get_height() - subpixbuf.get_height(), dest_y)

        if subpixbuf.get_has_alpha():
            subpixbuf = ImageTools.add_alpha_background(subpixbuf, subpixbuf.get_width(), subpixbuf.get_height())

        subpixbuf.copy_area(0, 0, subpixbuf.get_width(), subpixbuf.get_height(), canvas, dest_x, dest_y)