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()
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