Fixes mirrored slice exports by making orientation explicit: - PhotoSlice.swapped flag persists a user left/right swap - swap_left_right() mirrors [TL,TR,BR,BL] -> [TR,TL,BL,BR] - normalize_top_left() honors the flag so squarize/reset_rotation no longer overwrite manual orientation - Swap L/R toolbar button wired through canvas state + controller - Color-code left (orange) vs right (cyan) corners and edges
82 lines
3.3 KiB
Python
82 lines
3.3 KiB
Python
import numpy as np
|
|
from PySide6.QtCore import QRectF, Qt
|
|
from PySide6.QtGui import QColor, QFont, QPainter, QPen
|
|
|
|
|
|
# CanvasRenderMixin: class definition for ScanSlicer behavior.
|
|
class CanvasRenderMixin:
|
|
# paintEvent: function definition for ScanSlicer behavior.
|
|
def paintEvent(self, event):
|
|
painter = QPainter(self)
|
|
painter.fillRect(self.rect(), self.OFF_CANVAS_COLOR)
|
|
|
|
if self.image is None:
|
|
return
|
|
|
|
img_rect = self._image_rect_view()
|
|
painter.drawImage(img_rect, self.image)
|
|
|
|
label_font = QFont(painter.font())
|
|
label_font.setPointSize(18)
|
|
label_font.setBold(True)
|
|
|
|
for si, s in enumerate(self.slices):
|
|
points = [self._image_to_view(p) for p in s.bbox]
|
|
|
|
for i in range(4):
|
|
a = points[i]
|
|
b = points[(i + 1) % 4]
|
|
if i == 0:
|
|
color = QColor("red")
|
|
elif i == 1:
|
|
color = QColor("green")
|
|
elif i == 2:
|
|
color = QColor("orange")
|
|
else:
|
|
color = QColor("blue") if s.locked else QColor("lightgreen")
|
|
painter.setPen(QPen(color, 3))
|
|
painter.drawLine(a, b)
|
|
|
|
# Corners are color-coded: left = orange, right = cyan.
|
|
# Edge 0 (top, red) runs TL->TR, so corners 0 and 3 are the left
|
|
# side and corners 1 and 2 are the right side.
|
|
corner_colors = (QColor("orange"), QColor("cyan"), QColor("cyan"), QColor("orange"))
|
|
for p, color in zip(points, corner_colors):
|
|
painter.setPen(QPen(QColor("blue"), 2))
|
|
painter.setBrush(color)
|
|
painter.drawRect(QRectF(p.x() - 5, p.y() - 5, 10, 10))
|
|
|
|
center = np.mean(s.bbox, axis=0)
|
|
center_view = self._image_to_view(center)
|
|
if si == self.active_slice_index:
|
|
text_color = QColor("gold")
|
|
else:
|
|
text_color = QColor("blue") if s.locked else QColor("lightgreen")
|
|
painter.setPen(QPen(text_color, 1))
|
|
painter.setFont(label_font)
|
|
painter.drawText(
|
|
QRectF(center_view.x() - 20, center_view.y() - 16, 40, 32),
|
|
Qt.AlignCenter,
|
|
str(si),
|
|
)
|
|
|
|
if s.side_handles_enabled and s.is_perfect_rectangle():
|
|
handle_color = QColor("orange") if si == self.active_slice_index else QColor(255, 170, 0)
|
|
painter.setPen(QPen(handle_color, 2))
|
|
painter.setBrush(QColor(handle_color.red(), handle_color.green(), handle_color.blue(), 170))
|
|
handle_size = (
|
|
float(getattr(self, "SIDE_HANDLE_SIZE_ACTIVE", 11.0))
|
|
if si == self.active_slice_index
|
|
else float(getattr(self, "SIDE_HANDLE_SIZE_INACTIVE", 9.0))
|
|
)
|
|
for ei in range(4):
|
|
mid = (s.bbox[ei] + s.bbox[(ei + 1) % 4]) / 2.0
|
|
mid_view = self._image_to_view(mid)
|
|
painter.drawRect(
|
|
QRectF(
|
|
mid_view.x() - handle_size / 2.0,
|
|
mid_view.y() - handle_size / 2.0,
|
|
handle_size,
|
|
handle_size,
|
|
)
|
|
)
|