jfjoch_viewer: Work in (slow) progress

This commit is contained in:
2025-11-07 13:16:04 +01:00
parent d29cc52e64
commit df9f980ea6
7 changed files with 65 additions and 70 deletions
+39 -41
View File
@@ -29,16 +29,21 @@ void JFJochSimpleImage::clear() {
}
void JFJochSimpleImage::setImage(std::shared_ptr<const SimpleImage> img) {
image_ = std::move(img);
has_image_ = true;
renderImage();
updateOverlay();
if (img) {
image_ = std::move(img);
has_image_ = true;
Redraw();
} else {
has_image_ = false;
image_.reset();
if (scene())
scene()->clear();
}
}
void JFJochSimpleImage::Redraw() {
if (has_image_) {
renderImage();
// Preserve current transform while updating
updateOverlay();
}
}
@@ -55,24 +60,23 @@ void JFJochSimpleImage::mousePressEvent(QMouseEvent* event) {
active_handle_ = hitTestROIHandle(scenePos, 4.0 / std::sqrt(std::max(1e-4, scale_factor)));
if (active_handle_ != ResizeHandle::None && active_handle_ != ResizeHandle::Inside) {
mouse_event_type = MouseEventType::ResizingROI;
roi_start_pos_ = roi_box_.topLeft();
roi_end_pos_ = roi_box_.bottomRight();
roiStartPos = roiBox.topLeft();
roiEndPos = roiBox.bottomRight();
setCursor(Qt::SizeAllCursor);
} else if (roi_box_.contains(scenePos)) {
} else if (roiBox.contains(scenePos)) {
mouse_event_type = MouseEventType::MovingROI;
last_mouse_pos_ = event->pos();
lastMousePos = event->pos();
setCursor(Qt::ClosedHandCursor);
} else {
mouse_event_type = MouseEventType::DrawingROI;
roi_start_pos_ = RoundPoint(scenePos);
roi_end_pos_ = roi_start_pos_;
roiStartPos = RoundPoint(scenePos);
roiEndPos = roiStartPos;
setCursor(Qt::CrossCursor);
}
} else {
mouse_event_type = MouseEventType::Panning;
panning_ = true;
setCursor(Qt::ClosedHandCursor);
last_mouse_pos_ = event->pos();
lastMousePos = event->pos();
}
}
@@ -86,27 +90,27 @@ void JFJochSimpleImage::mouseMoveEvent(QMouseEvent* event) {
switch (mouse_event_type) {
case MouseEventType::Panning: {
const QPointF delta = mapToScene(event->pos()) - mapToScene(last_mouse_pos_);
last_mouse_pos_ = event->pos();
const QPointF delta = mapToScene(event->pos()) - mapToScene(lastMousePos);
lastMousePos = event->pos();
translate(delta.x(), delta.y());
updateOverlay();
break;
}
case MouseEventType::DrawingROI: {
roi_end_pos_ = RoundPoint(scenePos);
roiEndPos = RoundPoint(scenePos);
updateROI();
break;
}
case MouseEventType::MovingROI: {
const QPointF delta = mapToScene(event->pos()) - mapToScene(last_mouse_pos_);
last_mouse_pos_ = event->pos();
roi_box_.translate(delta);
const QPointF delta = mapToScene(event->pos()) - mapToScene(lastMousePos);
lastMousePos = event->pos();
roiBox.translate(delta);
updateROI();
break;
}
case MouseEventType::ResizingROI: {
// Modify the corresponding edges based on active_handle_
QRectF r = roi_box_;
QRectF r = roiBox;
switch (active_handle_) {
case ResizeHandle::Left: r.setLeft(scenePos.x()); break;
case ResizeHandle::Right: r.setRight(scenePos.x()); break;
@@ -118,7 +122,7 @@ void JFJochSimpleImage::mouseMoveEvent(QMouseEvent* event) {
case ResizeHandle::BottomRight:r.setBottom(scenePos.y()); r.setRight(scenePos.x()); break;
default: break;
}
roi_box_ = r.normalized();
roiBox = r.normalized();
updateROI();
break;
}
@@ -151,10 +155,9 @@ void JFJochSimpleImage::mouseReleaseEvent(QMouseEvent* event) {
if (event->button() == Qt::LeftButton) {
if (mouse_event_type == MouseEventType::DrawingROI) {
roi_end_pos_ = RoundPoint(mapToScene(event->pos()));
roiEndPos = RoundPoint(mapToScene(event->pos()));
updateROI();
}
panning_ = false;
mouse_event_type = MouseEventType::None;
active_handle_ = ResizeHandle::None;
setCursor(Qt::ArrowCursor);
@@ -331,17 +334,12 @@ void JFJochSimpleImage::renderImage(QImage &qimg, const uint8_t *input) {
}
}
QPointF JFJochSimpleImage::RoundPoint(const QPointF& p) {
return QPointF(qRound(p.x()), qRound(p.y()));
}
JFJochSimpleImage::ResizeHandle
JFJochSimpleImage::hitTestROIHandle(const QPointF& scenePos, qreal tol) const {
if (roi_box_.isNull() || roi_box_.width() <= 0 || roi_box_.height() <= 0)
if (roiBox.isNull() || roiBox.width() <= 0 || roiBox.height() <= 0)
return ResizeHandle::None;
const QRectF r = roi_box_;
const QRectF r = roiBox;
const QPointF tl = r.topLeft();
const QPointF tr = r.topRight();
const QPointF bl = r.bottomLeft();
@@ -372,8 +370,8 @@ JFJochSimpleImage::hitTestROIHandle(const QPointF& scenePos, qreal tol) const {
void JFJochSimpleImage::updateROI() {
// Normalize box if drawing
if (mouse_event_type_ == MouseEventType::DrawingROI) {
roi_box_ = QRectF(roi_start_pos_, roi_end_pos_).normalized();
if (mouse_event_type == MouseEventType::DrawingROI) {
roiBox = QRectF(roiStartPos, roiEndPos).normalized();
}
// Clamp ROI to image bounds
@@ -381,19 +379,19 @@ void JFJochSimpleImage::updateROI() {
const QRectF bounds(0.0, 0.0,
image_->image.GetWidth(),
image_->image.GetHeight());
roi_box_ = roi_box_.intersected(bounds);
roiBox = roiBox.intersected(bounds);
}
scheduleSceneUpdate();
}
void JFJochSimpleImage::drawROI(QGraphicsScene* scn) {
if (roi_box_.isNull() || roi_box_.width() <= 0 || roi_box_.height() <= 0) return;
if (roiBox.isNull() || roiBox.width() <= 0 || roiBox.height() <= 0) return;
QPen pen(feature_color, 2);
pen.setStyle(Qt::DashLine);
pen.setCosmetic(true);
scn->addRect(roi_box_, pen);
scn->addRect(roiBox, pen);
// Small corner handles
const qreal handleSize = 3.0 / std::sqrt(std::max(1e-4, scale_factor));
@@ -401,13 +399,13 @@ void JFJochSimpleImage::drawROI(QGraphicsScene* scn) {
scn->addRect(QRectF(p.x() - handleSize, p.y() - handleSize, 2 * handleSize, 2 * handleSize),
QPen(feature_color, 1), QBrush(feature_color));
};
addHandle(roi_box_.topLeft());
addHandle(roi_box_.topRight());
addHandle(roi_box_.bottomLeft());
addHandle(roi_box_.bottomRight());
addHandle(roiBox.topLeft());
addHandle(roiBox.topRight());
addHandle(roiBox.bottomLeft());
addHandle(roiBox.bottomRight());
// Compute stats inside integer pixel ROI
QRect roi_px = roi_box_.toRect().normalized();
QRect roi_px = roiBox.toRect().normalized();
ROIStats stats = computeROIStats(roi_px);
if (stats.valid()) {
@@ -436,7 +434,7 @@ void JFJochSimpleImage::drawROI(QGraphicsScene* scn) {
t->setZValue(20.0);
// Place near top-left of ROI, slightly above
QPointF pos = roi_box_.topLeft() + QPointF(2.0, -16.0 / std::sqrt(f));
QPointF pos = roiBox.topLeft() + QPointF(2.0, -16.0 / std::sqrt(f));
t->setPos(pos);
}
}