From ab39926d45a2f7e49258c0334fe00ef2d575e0a1 Mon Sep 17 00:00:00 2001 From: Tom Gouville Date: Fri, 16 Jan 2026 23:17:26 +0100 Subject: [PATCH] Supporting image orientation to rotate the images in the preview --- RawRefinery/application/ModelHandler.py | 32 ++++++++++++++++++++ RawRefinery/application/RawRefineryApp.py | 37 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/RawRefinery/application/ModelHandler.py b/RawRefinery/application/ModelHandler.py index 235f06d..e1851b3 100644 --- a/RawRefinery/application/ModelHandler.py +++ b/RawRefinery/application/ModelHandler.py @@ -180,6 +180,8 @@ def __init__(self): self.model = None self.rh = None self.iso = 100 + self.orientation = 0. + self.mirrored = False self.colorspace = 'lin_rec2020' # Manage devices @@ -208,6 +210,36 @@ def load_rh(self, path): self.iso = int(self.rh.full_metadata['EXIF ISOSpeedRatings'].values[0]) else: self.iso = 100 + if 'Image Orientation' in self.rh.full_metadata: + orientation_value = int(self.rh.full_metadata['Image Orientation'].values[0]) + match orientation_value : + case 1: + self.mirrored=False + self.orientation=0. + case 2: + self.mirrored=True + self.orientation=0. + case 3: + self.mirrored=False + self.orientation = 180. + case 4: + self.mirrored=True + self.orientation = 180. + case 5: + self.mirrored=True + self.orientation= 90. + case 6: + self.mirrored=False + self.orientation= 90. + case 7: + self.mirrored=True + self.orientation = 270. + case 8: + self.mirrored=False + self.orientation = 270. + else: + self.orientation = 0. + self.mirrored = False return self.iso def load_model(self, model_key): diff --git a/RawRefinery/application/RawRefineryApp.py b/RawRefinery/application/RawRefineryApp.py index 5983f7c..7444eca 100644 --- a/RawRefinery/application/RawRefineryApp.py +++ b/RawRefinery/application/RawRefineryApp.py @@ -6,7 +6,7 @@ QFileDialog, QListWidget, QLabel, QSlider, QSpinBox, QHBoxLayout, QFormLayout, QComboBox, QProgressBar, QMessageBox ) -from PySide6.QtGui import QPixmap, QIcon +from PySide6.QtGui import QPixmap, QIcon, QTransform from PySide6.QtCore import Qt, Slot # Import utils @@ -192,7 +192,14 @@ def on_file_selected(self, item): # Show thumbnail thumb_rgb = self.controller.generate_thumbnail() qimg = numpy_to_qimage_rgb(thumb_rgb, exposure=self.exposure_slider.get_natural_value()) - self.thumb_label.set_image(qimg) + + # Show image accordingly to EXIF orientation + transform = QTransform().rotate(self.controller.orientation) + if self.controller.mirrored: + transform = QTransform().scale(-1,1).rotate(self.controller.orientation) + rot = qimg.transformed(transform) + + self.thumb_label.set_image(rot) self.dims = None self.preview_label.setText("Click thumbnail to preview region") @@ -205,6 +212,21 @@ def on_thumbnail_click(self, x_ratio, y_ratio): rh = self.controller.rh H_full, W_full = rh.raw.shape + + # Retrieve the original coordinate from non-rotated media + match self.controller.orientation: + case 0: + pass + case 90: + x_ratio, y_ratio = y_ratio, x_ratio + case 180: + x_ratio, y_ratio = 1.0 - x_ratio, 1.0 - y_ratio + case 270: + x_ratio, y_ratio = 1.0- y_ratio, x_ratio + + if self.controller.mirrored: + x_ratio = 1.0 - x_ratio + # Center of click in raw coords c_x = int(x_ratio * W_full) c_y = int(y_ratio * H_full) @@ -288,7 +310,14 @@ def display_result(self, img_rgb, denoised): # Convert output to QImage qimg = numpy_to_qimage_rgb(denoised, exposure=self.exposure_slider.get_natural_value()) - pix = QPixmap.fromImage(qimg) + + # Show image accordingly to EXIF orientation + transform = QTransform().rotate(self.controller.orientation) + if self.controller.mirrored: + transform = QTransform().scale(-1,1).rotate(self.controller.orientation) + rot = qimg.transformed(transform) + + pix = QPixmap.fromImage(rot) # Scale for display scaled = pix.scaled(self.preview_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) @@ -322,4 +351,4 @@ def display_device(self, device): window = RawRefineryApp() window.show() window.loading_popup() - sys.exit(app.exec()) \ No newline at end of file + sys.exit(app.exec())