class QtReader(BaseReader):
    """Image reader using Qt's QImageReader implementation under the hood."""
    def __init__(self, path: str, file_format: str):
        super().__init__(path, file_format)
        self._handler = QImageReader(path, file_format.encode())
        self._handler.setAutoTransform(True)
        if not self._handler.canRead():
            # TODO
            raise ValueError(f"'{path}' cannot be read as image")

    @classmethod
    def supports(cls, file_format: str) -> bool:
        return file_format in QImageReader.supportedImageFormats()

    @property
    def is_animation(self) -> bool:
        return self._handler.supportsAnimation()

    def get_pixmap(self) -> QPixmap:
        """Retrieve the pixmap directly from the image reader."""
        pixmap = QPixmap.fromImageReader(self._handler)
        if self._handler.error():
            raise ValueError(
                f"Error reading image '{self.path}': {self._handler.errorString()}"
            )
        return pixmap

    def get_image(self, size: int) -> QImage:
        """Retrieve the down-scaled image directly from the image reader."""
        qsize = self._handler.size()
        qsize.scale(size, size, Qt.KeepAspectRatio)
        self._handler.setScaledSize(qsize)
        return self._handler.read()
Beispiel #2
0
    def _load(self, path: str, reload_only: bool):
        """Load proper displayable QWidget for a path.

        This reads the image using QImageReader and then emits the appropriate
        *_loaded signal to tell the image to display a new object.
        """
        # Pass file format explicitly as imghdr does a much better job at this than the
        # file name based approach of QImageReader
        file_format = files.imghdr.what(path)
        if file_format is None:
            log.error("%s is not a valid image", path)
            return
        reader = QImageReader(path, file_format.encode("utf-8"))
        reader.setAutoTransform(True)  # Automatically apply exif orientation
        if not reader.canRead():
            log.error("Cannot read image %s", path)
            return
        # SVG
        if file_format == "svg" and QSvgWidget:
            # Do not store image and only emit with the path as the
            # VectorGraphic widget needs the path in the constructor
            self.original = None
            api.signals.svg_loaded.emit(path, reload_only)
            self._image_type = ImageType.Svg
        # Gif
        elif reader.supportsAnimation():
            movie = QMovie(path)
            if not movie.isValid() or movie.frameCount() == 0:
                log.error("Error reading animation %s: invalid data", path)
                return
            self.original = movie
            api.signals.movie_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Movie
        # Regular image
        else:
            pixmap = QPixmap.fromImageReader(reader)
            if reader.error():
                log.error("Error reading image %s: %s", path, reader.errorString())
                return
            self.original = pixmap
            api.signals.pixmap_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Pixmap
        self._path = path