diff --git a/kstars/ekos/align/alignview.h b/kstars/ekos/align/alignview.h --- a/kstars/ekos/align/alignview.h +++ b/kstars/ekos/align/alignview.h @@ -26,7 +26,7 @@ /* Calculate WCS header info and update WCS info */ bool injectWCS(double orientation, double ra, double dec, double pixscale); - void drawOverlay(QPainter *) override; + void drawOverlay(QPainter *, double scale) override; // Correction line void setCorrectionParams(QLineF &line); diff --git a/kstars/ekos/align/alignview.cpp b/kstars/ekos/align/alignview.cpp --- a/kstars/ekos/align/alignview.cpp +++ b/kstars/ekos/align/alignview.cpp @@ -27,10 +27,10 @@ { } -void AlignView::drawOverlay(QPainter *painter) +void AlignView::drawOverlay(QPainter *painter, double scale) { painter->setOpacity(0.5); - FITSView::drawOverlay(painter); + FITSView::drawOverlay(painter, getScale()); painter->setOpacity(1); if (RACircle.isNull() == false) @@ -126,11 +126,12 @@ zoomedLine.translate(offset); - double x1 = zoomedLine.p1().x(); - double y1 = zoomedLine.p1().y(); + const double scale = getScale(); + double x1 = zoomedLine.p1().x() * scale; + double y1 = zoomedLine.p1().y() * scale; - double x2 = zoomedLine.p2().x(); - double y2 = zoomedLine.p2().y(); + double x2 = zoomedLine.p2().x() * scale; + double y2 = zoomedLine.p2().y() * scale; painter->drawLine(x1, y1, x2, y2); @@ -142,9 +143,9 @@ pen.setWidth(2); pen.setColor(Qt::darkRed); painter->setPen(pen); - double x = celestialPolePoint.x(); - double y = celestialPolePoint.y(); - double sr = 3; + double x = celestialPolePoint.x() * scale; + double y = celestialPolePoint.y() * scale; + double sr = 3 * scale; if (KStarsData::Instance()->geo()->lat()->Degrees() > 0) painter->drawText(x + sr, y + sr, i18nc("North Celestial Pole", "NCP")); @@ -161,10 +162,11 @@ painter->setPen(pen); painter->setBrush(Qt::NoBrush); - QPointF center(RACircle.x(), RACircle.y()); + const double scale = getScale(); + QPointF center(RACircle.x() * scale, RACircle.y() * scale); // Big Radius - double r = RACircle.z(); + double r = RACircle.z() * scale; // Small radius double sr = r / 25.0; diff --git a/kstars/fitsviewer/fitsview.h b/kstars/fitsviewer/fitsview.h --- a/kstars/fitsviewer/fitsview.h +++ b/kstars/fitsviewer/fitsview.h @@ -113,16 +113,17 @@ } // Overlay - virtual void drawOverlay(QPainter *); + virtual void drawOverlay(QPainter *, double scale); // Overlay objects - void drawStarCentroid(QPainter *); - void drawTrackingBox(QPainter *); - void drawMarker(QPainter *); - void drawCrosshair(QPainter *); - void drawEQGrid(QPainter *); - void drawObjectNames(QPainter *painter); - void drawPixelGrid(QPainter *painter); + void drawStarFilter(QPainter *, double scale); + void drawStarCentroid(QPainter *, double scale); + void drawTrackingBox(QPainter *, double scale); + void drawMarker(QPainter *, double scale); + void drawCrosshair(QPainter *, double scale); + void drawEQGrid(QPainter *, double scale); + void drawObjectNames(QPainter *painter, double scale); + void drawPixelGrid(QPainter *painter, double scale); bool isImageStretched(); bool isCrosshairShown(); @@ -270,11 +271,13 @@ void calculateMaxPixel(double min, double max); void initDisplayImage(); - QPointF getPointForGridLabel(QPainter *painter, const QString& str); - bool pointIsInImage(QPointF pt); + QPointF getPointForGridLabel(QPainter *painter, const QString& str, double scale); + bool pointIsInImage(QPointF pt, double scale); void loadInFrame(); + double getScale(); + /// WCS Future Watcher QFutureWatcher wcsWatcher; /// FITS Future Watcher @@ -293,6 +296,11 @@ bool processData(); void doStretch(FITSData *data, QImage *outputImage); double scaleSize(double size); + bool isLargeImage(); + void updateFrameLargeImage(); + void updateFrameSmallImage(); + bool drawHFR(QPainter * painter, const QString & hfr, int x, int y); + QLabel *noImageLabel { nullptr }; QPixmap noImage; diff --git a/kstars/fitsviewer/fitsview.cpp b/kstars/fitsviewer/fitsview.cpp --- a/kstars/fitsviewer/fitsview.cpp +++ b/kstars/fitsviewer/fitsview.cpp @@ -661,29 +661,59 @@ starFilter.outerRadius = outerRadius; } -// scaleSize() may increase the line widths or font sizes, as we draw lines and render text on the -// full image and when zoomed out, these sizes may be too small. -double FITSView::scaleSize(double size) -{ - return currentZoom > 100.0 ? size : std::round(size * 100.0 / currentZoom); -} - int FITSView::filterStars() { return starFilter.used() ? imageData->filterStars(starFilter.innerRadius, starFilter.outerRadius) : imageData->getStarCenters().count(); } -void FITSView::updateFrame() +// isImageLarge() returns whether we use the large-image rendering strategy or the small-image strategy. +// See the comment below in getScale() for details. +bool FITSView::isLargeImage() { - bool ok = false; + constexpr int largeImageNumPixels = 1000 * 1000; + return rawImage.width() * rawImage.height() >= largeImageNumPixels; +} + +// getScale() is related to the image and overlay rendering strategy used. +// If we're using a pixmap apprpriate for a large image, where we draw and render on a pixmap that's the image size +// and we let the QLabel deal with scaling and zooming, then the scale is 1.0. +// With smaller images, where memory use is not as severe, we create a pixmap that's the size of the scaled image +// and get scale returns the ratio of that pixmap size to the image size. +double FITSView::getScale() +{ + return isLargeImage() ? 1.0 : currentZoom / ZOOM_DEFAULT; +} + +// scaleSize() is only used with the large-image rendering strategy. It may increase the line +// widths or font sizes, as we draw lines and render text on the full image and when zoomed out, +// these sizes may be too small. +double FITSView::scaleSize(double size) +{ + if (!isLargeImage()) + return size; + return currentZoom > 100.0 ? size : std::round(size * 100.0 / currentZoom); +} +void FITSView::updateFrame() +{ if (toggleStretchAction) toggleStretchAction->setChecked(stretchImage); - ok = displayPixmap.convertFromImage(rawImage); + // We employ two schemes for managing the image and its overlays, depending on the size of the image + // and whether we need to therefore conserve memory. The small-image strategy explicitly scales up + // the image, and writes overlays on the scaled pixmap. The large-image strategy uses a pixmap that's + // the size of the image itself, never scaling that up. + if (isLargeImage()) + updateFrameLargeImage(); + else + updateFrameSmallImage(); +} + - if (!ok) +void FITSView::updateFrameLargeImage() +{ + if (!displayPixmap.convertFromImage(rawImage)) return; QPainter painter(&displayPixmap); @@ -695,29 +725,52 @@ if (sampling == 1) { - drawOverlay(&painter); - - if (starFilter.used()) - { - double const diagonal = std::sqrt(imageData->width() * imageData->width() + imageData->height() * imageData->height()) / 2; - int const innerRadius = std::lround(diagonal * starFilter.innerRadius); - int const outerRadius = std::lround(diagonal * starFilter.outerRadius); - QPoint const center(imageData->width() / 2, imageData->height() / 2); - painter.save(); - painter.setPen(QPen(Qt::blue, scaleSize(1), Qt::DashLine)); - painter.setOpacity(0.7); - painter.setBrush(QBrush(Qt::transparent)); - painter.drawEllipse(center, outerRadius, outerRadius); - painter.setBrush(QBrush(Qt::blue, Qt::FDiagPattern)); - painter.drawEllipse(center, innerRadius, innerRadius); - painter.restore(); - } + drawOverlay(&painter, 1.0); + drawStarFilter(&painter, 1.0); } image_frame->setPixmap(displayPixmap); image_frame->resize(((sampling * currentZoom) / 100.0) * image_frame->pixmap()->size()); } +void FITSView::updateFrameSmallImage() +{ + QImage scaledImage = rawImage.scaled(currentWidth, currentHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); + if (!displayPixmap.convertFromImage(scaledImage)) + return; + + QPainter painter(&displayPixmap); + + if (sampling == 1) + { + drawOverlay(&painter, currentZoom / ZOOM_DEFAULT); + drawStarFilter(&painter, currentZoom / ZOOM_DEFAULT); + } + image_frame->setPixmap(displayPixmap); + + image_frame->resize(currentWidth, currentHeight); +} + +void FITSView::drawStarFilter(QPainter *painter, double scale) +{ + if (!starFilter.used()) + return; + const double w = imageData->width() * scale; + const double h = imageData->height() * scale; + double const diagonal = std::sqrt(w * w + h * h) / 2; + int const innerRadius = std::lround(diagonal * starFilter.innerRadius); + int const outerRadius = std::lround(diagonal * starFilter.outerRadius); + QPoint const center(w / 2, h / 2); + painter->save(); + painter->setPen(QPen(Qt::blue, scaleSize(1), Qt::DashLine)); + painter->setOpacity(0.7); + painter->setBrush(QBrush(Qt::transparent)); + painter->drawEllipse(center, outerRadius, outerRadius); + painter->setBrush(QBrush(Qt::blue, Qt::FDiagPattern)); + painter->drawEllipse(center, innerRadius, innerRadius); + painter->restore(); +} + void FITSView::ZoomDefault() { if (image_frame != nullptr) @@ -737,50 +790,50 @@ } } -void FITSView::drawOverlay(QPainter * painter) +void FITSView::drawOverlay(QPainter * painter, double scale) { painter->setRenderHint(QPainter::Antialiasing, Options::useAntialias()); if (trackingBoxEnabled && getCursorMode() != FITSView::scopeCursor) - drawTrackingBox(painter); + drawTrackingBox(painter, scale); if (!markerCrosshair.isNull()) - drawMarker(painter); + drawMarker(painter, scale); if (showCrosshair) - drawCrosshair(painter); + drawCrosshair(painter, scale); if (showObjects) - drawObjectNames(painter); + drawObjectNames(painter, scale); if (showEQGrid) - drawEQGrid(painter); + drawEQGrid(painter, scale); if (showPixelGrid) - drawPixelGrid(painter); + drawPixelGrid(painter, scale); if (markStars) - drawStarCentroid(painter); + drawStarCentroid(painter, scale); } void FITSView::updateMode(FITSMode fmode) { mode = fmode; } -void FITSView::drawMarker(QPainter * painter) +void FITSView::drawMarker(QPainter * painter, double scale) { painter->setPen(QPen(QColor(KStarsData::Instance()->colorScheme()->colorNamed("TargetColor")), scaleSize(2))); painter->setBrush(Qt::NoBrush); - constexpr float pxperdegree = (57.3 / 1.8); + const float pxperdegree = scale * (57.3 / 1.8); const float s1 = 0.5 * pxperdegree; const float s2 = pxperdegree; const float s3 = 2.0 * pxperdegree; - const float x0 = markerCrosshair.x(); - const float y0 = markerCrosshair.y(); + const float x0 = scale * markerCrosshair.x(); + const float y0 = scale * markerCrosshair.y(); const float x1 = x0 - 0.5 * s1; const float y1 = y0 - 0.5 * s1; const float x2 = x0 - 0.5 * s2; @@ -798,87 +851,110 @@ painter->drawEllipse(QRectF(x2, y2, s2, s2)); } -void FITSView::drawStarCentroid(QPainter * painter) +bool FITSView::drawHFR(QPainter * painter, const QString & hfr, int x, int y) { - if (showStarsHFR) + QRect const boundingRect(0, 0, painter->device()->width(), painter->device()->height()); + QSize const hfrSize = painter->fontMetrics().size(Qt::TextSingleLine, hfr); + + // Store the HFR text in a rect + QPoint const hfrBottomLeft(x, y); + QRect const hfrRect(hfrBottomLeft.x(), hfrBottomLeft.y() - hfrSize.height(), hfrSize.width(), hfrSize.height()); + + // Render the HFR text only if it can be displayed entirely + if (boundingRect.contains(hfrRect)) { - QFont painterFont; + painter->setPen(QPen(Qt::red, scaleSize(3))); + painter->drawText(hfrBottomLeft, hfr); + painter->setPen(QPen(Qt::red, scaleSize(2))); + return true; + } + return false; +} + +void FITSView::drawStarCentroid(QPainter * painter, double scale) +{ + QFont painterFont; + double fontSize = painterFont.pointSizeF() * 2; + if (showStarsHFR) + { // If we need to print the HFR out, give an arbitrarily sized font to the painter - painterFont.setPointSizeF(scaleSize(painterFont.pointSizeF())); + if (isLargeImage()) + fontSize = scaleSize(painterFont.pointSizeF()); + painterFont.setPointSizeF(fontSize); painter->setFont(painterFont); } painter->setPen(QPen(Qt::red, scaleSize(2))); - QFontMetrics const fontMetrics = painter->fontMetrics(); - QRect const boundingRect(0, 0, painter->device()->width(), painter->device()->height()); - foreach (auto const &starCenter, imageData->getStarCenters()) { - int const w = std::round(starCenter->width); + int const w = std::round(starCenter->width) * scale; // Draw a circle around the detected star. // SEP coordinates are in the center of pixels, and Qt at the boundary. const double xCoord = starCenter->x - 0.5; const double yCoord = starCenter->y - 0.5; - const double radius = starCenter->HFR > 0 ? 2.0f * starCenter->HFR : w; - painter->drawEllipse(QPointF(xCoord, yCoord), radius, radius); + const double radius = starCenter->HFR > 0 ? 2.0f * starCenter->HFR * scale : w; + painter->drawEllipse(QPointF(xCoord * scale, yCoord * scale), radius, radius); if (showStarsHFR) { - int const x1 = std::round(xCoord - starCenter->width / 2.0f); - int const y1 = std::round(yCoord - starCenter->width / 2.0f); + int const x1 = std::round((xCoord - starCenter->width / 2.0f) * scale); + int const y1 = std::round((yCoord - starCenter->width / 2.0f) * scale); // Ask the painter how large will the HFR text be QString const hfr = QString("%1").arg(starCenter->HFR, 0, 'f', 2); - QSize const hfrSize = fontMetrics.size(Qt::TextSingleLine, hfr); - - // Store the HFR text in a rect - QPoint const hfrBottomLeft(x1 + w + 5, y1 + w / 2); - QRect const hfrRect(hfrBottomLeft.x(), hfrBottomLeft.y() - hfrSize.height(), hfrSize.width(), hfrSize.height()); - - // Render the HFR text only if it can be displayed entirely - if (boundingRect.contains(hfrRect)) + if (!drawHFR(painter, hfr, x1 + w + 5, y1 + w / 2)) { - painter->setPen(QPen(Qt::red, scaleSize(3))); - painter->drawText(hfrBottomLeft, hfr); - painter->setPen(QPen(Qt::red, scaleSize(2))); + // Try a few more time with smaller fonts; + for (int i = 0; i < 10; ++i) + { + const double tempFontSize = painterFont.pointSizeF() - 2; + if (tempFontSize <= 0) break; + painterFont.setPointSizeF(tempFontSize); + painter->setFont(painterFont); + if (drawHFR(painter, hfr, x1 + w + 5, y1 + w / 2)) + break; + } + // Reset the font size. + painterFont.setPointSize(fontSize); + painter->setFont(painterFont); } } } } -void FITSView::drawTrackingBox(QPainter * painter) +void FITSView::drawTrackingBox(QPainter * painter, double scale) { painter->setPen(QPen(Qt::green, scaleSize(2))); if (trackingBox.isNull()) return; - const int x1 = trackingBox.x(); - const int y1 = trackingBox.y(); - const int w = trackingBox.width(); - const int h = trackingBox.height(); + const int x1 = trackingBox.x() * scale; + const int y1 = trackingBox.y() * scale; + const int w = trackingBox.width() * scale; + const int h = trackingBox.height() * scale; painter->drawRect(x1, y1, w, h); } /** This Method draws a large Crosshair in the center of the image, it is like a set of axes. */ -void FITSView::drawCrosshair(QPainter * painter) +void FITSView::drawCrosshair(QPainter * painter, double scale) { if (!imageData) return; const int image_width = imageData->width(); const int image_height = imageData->height(); - const QPointF c = QPointF((qreal)image_width / 2, (qreal)image_height / 2); - const float midX = (float)image_width / 2; - const float midY = (float)image_height / 2; - const float maxX = (float)image_width; - const float maxY = (float)image_height; - constexpr float r = 50; + const QPointF c = QPointF((qreal)image_width / 2 * scale, (qreal)image_height / 2 * scale); + const float midX = (float)image_width / 2 * scale; + const float midY = (float)image_height / 2 * scale; + const float maxX = (float)image_width * scale; + const float maxY = (float)image_height * scale; + const float r = 50 * scale; painter->setPen(QPen(QColor(KStarsData::Instance()->colorScheme()->colorNamed("TargetColor")), scaleSize(1))); @@ -907,20 +983,20 @@ be in the center of the image. */ -void FITSView::drawPixelGrid(QPainter * painter) +void FITSView::drawPixelGrid(QPainter * painter, double scale) { - const float width = imageData->width(); - const float height = imageData->height(); + const float width = imageData->width() * scale; + const float height = imageData->height() * scale; const float cX = width / 2; const float cY = height / 2; const float deltaX = width / 10; const float deltaY = height / 10; QFontMetrics fm(painter->font()); //draw the Axes painter->setPen(QPen(Qt::red, scaleSize(1))); - painter->drawText(cX - 30, height - 5, QString::number((int)(cX))); - QString str = QString::number((int)(cY)); + painter->drawText(cX - 30, height - 5, QString::number((int)((cX) / scale))); + QString str = QString::number((int)((cY) / scale)); painter->drawText(width - (fm.width(str) + 10), cY - 5, str); if (!showCrosshair) { @@ -931,17 +1007,17 @@ //Start one iteration past the Center and draw 4 lines on either side of 0 for (int x = deltaX; x < cX - deltaX; x += deltaX) { - painter->drawText(cX + x - 30, height - 5, QString::number((int)(cX + x))); - painter->drawText(cX - x - 30, height - 5, QString::number((int)(cX - x))); + painter->drawText(cX + x - 30, height - 5, QString::number((int)(cX + x) / scale)); + painter->drawText(cX - x - 30, height - 5, QString::number((int)(cX - x) / scale)); painter->drawLine(cX - x, 0, cX - x, height); painter->drawLine(cX + x, 0, cX + x, height); } //Start one iteration past the Center and draw 4 lines on either side of 0 for (int y = deltaY; y < cY - deltaY; y += deltaY) { - QString str = QString::number((int)(cY + y)); + QString str = QString::number((int)((cY + y) / scale)); painter->drawText(width - (fm.width(str) + 10), cY + y - 5, str); - str = QString::number((int)(cY - y)); + str = QString::number((int)((cY - y) / scale)); painter->drawText(width - (fm.width(str) + 10), cY - y - 5, str); painter->drawLine(0, cY + y, width, cY + y); painter->drawLine(0, cY - y, width, cY - y); @@ -955,13 +1031,13 @@ return false; } -void FITSView::drawObjectNames(QPainter * painter) +void FITSView::drawObjectNames(QPainter * painter, double scale) { painter->setPen(QPen(QColor(KStarsData::Instance()->colorScheme()->colorNamed("FITSObjectLabelColor")))); foreach (FITSSkyObject * listObject, imageData->getSkyObjects()) { - painter->drawRect(listObject->x() - 5, listObject->y() - 5, 10, 10); - painter->drawText(listObject->x() + 10, listObject->y() + 10, listObject->skyObject()->name()); + painter->drawRect(listObject->x() * scale - 5, listObject->y() * scale - 5, 10, 10); + painter->drawText(listObject->x() * scale + 10, listObject->y() * scale + 10, listObject->skyObject()->name()); } } @@ -972,7 +1048,7 @@ to draw gridlines at those specific RA and Dec values. */ -void FITSView::drawEQGrid(QPainter * painter) +void FITSView::drawEQGrid(QPainter * painter, double scale) { const int image_width = imageData->width(); const int image_height = imageData->height(); @@ -1066,7 +1142,7 @@ bool inImage = imageData->wcsToPixel(pointToGet, pixelPoint, imagePoint); if (inImage) { - QPointF pt(pixelPoint.x(), pixelPoint.y()); + QPointF pt(pixelPoint.x() * scale, pixelPoint.y() * scale); eqGridPoints.append(pt); } } @@ -1079,7 +1155,7 @@ QString::number(dms(target).minute()) + '\''; if (maxDec <= 50 && maxDec >= -50) str = str + " " + QString::number(dms(target).second()) + "''"; - QPointF pt = getPointForGridLabel(painter, str); + QPointF pt = getPointForGridLabel(painter, str, scale); if (pt.x() != -100) painter->drawText(pt.x(), pt.y(), str); } @@ -1111,7 +1187,7 @@ for (int i = 1; i < eqGridPoints.count(); i++) painter->drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i)); QString str = QString::number(dms(target).degree()) + "° " + QString::number(dms(target).arcmin()) + '\''; - QPointF pt = getPointForGridLabel(painter, str); + QPointF pt = getPointForGridLabel(painter, str, scale); if (pt.x() != -100) painter->drawText(pt.x(), pt.y(), str); } @@ -1127,9 +1203,9 @@ (pPoint.x() > 0 && pPoint.x() < image_width) && (pPoint.y() > 0 && pPoint.y() < image_height); if (NCPinImage) { - painter->fillRect(pPoint.x() - 2, pPoint.y() - 2, 4, 4, + painter->fillRect(pPoint.x() * scale - 2, pPoint.y() * scale - 2, 4, 4, KStarsData::Instance()->colorScheme()->colorNamed("TargetColor")); - painter->drawText(pPoint.x() + 15, pPoint.y() + 15, + painter->drawText(pPoint.x() * scale + 15, pPoint.y() * scale + 15, i18nc("North Celestial Pole", "NCP")); } } @@ -1144,88 +1220,88 @@ (pPoint.x() > 0 && pPoint.x() < image_width) && (pPoint.y() > 0 && pPoint.y() < image_height); if (SCPinImage) { - painter->fillRect(pPoint.x() - 2, pPoint.y() - 2, 4, 4, + painter->fillRect(pPoint.x() * scale - 2, pPoint.y() * scale - 2, 4, 4, KStarsData::Instance()->colorScheme()->colorNamed("TargetColor")); - painter->drawText(pPoint.x() + 15, pPoint.y() + 15, + painter->drawText(pPoint.x() * scale + 15, pPoint.y() * scale + 15, i18nc("South Celestial Pole", "SCP")); } } } } } -bool FITSView::pointIsInImage(QPointF pt) +bool FITSView::pointIsInImage(QPointF pt, double scale) { int image_width = imageData->width(); int image_height = imageData->height(); - return pt.x() < image_width && pt.y() < image_height && pt.x() > 0 && pt.y() > 0; + return pt.x() < image_width * scale && pt.y() < image_height * scale && pt.x() > 0 && pt.y() > 0; } -QPointF FITSView::getPointForGridLabel(QPainter *painter, const QString &str) +QPointF FITSView::getPointForGridLabel(QPainter *painter, const QString &str, double scale) { QFontMetrics fm(painter->font()); int strWidth = fm.width(str); int strHeight = fm.height(); int image_width = imageData->width(); int image_height = imageData->height(); //These get the maximum X and Y points in the list that are in the image - QPointF maxXPt(image_width / 2, image_height / 2); + QPointF maxXPt(image_width * scale / 2, image_height * scale / 2); for (auto &p : eqGridPoints) { - if (p.x() > maxXPt.x() && pointIsInImage(p)) + if (p.x() > maxXPt.x() && pointIsInImage(p, scale)) maxXPt = p; } - QPointF maxYPt(image_width / 2, image_height / 2); + QPointF maxYPt(image_width * scale / 2, image_height * scale / 2); for (auto &p : eqGridPoints) { - if (p.y() > maxYPt.y() && pointIsInImage(p)) + if (p.y() > maxYPt.y() && pointIsInImage(p, scale)) maxYPt = p; } - QPointF minXPt(image_width / 2, image_height / 2); + QPointF minXPt(image_width * scale / 2, image_height * scale / 2); for (auto &p : eqGridPoints) { - if (p.x() < minXPt.x() && pointIsInImage(p)) + if (p.x() < minXPt.x() && pointIsInImage(p, scale)) minXPt = p; } - QPointF minYPt(image_width / 2, image_height / 2); + QPointF minYPt(image_width * scale / 2, image_height * scale / 2); for (auto &p : eqGridPoints) { - if (p.y() < minYPt.y() && pointIsInImage(p)) + if (p.y() < minYPt.y() && pointIsInImage(p, scale)) minYPt = p; } //This gives preference to points that are on the right hand side and bottom. //But if the line doesn't intersect the right or bottom, it then tries for the top and left. //If no points are found in the image, it returns a point off the screen //If all else fails, like in the case of a circle on the image, it returns the far right point. - if (image_width - maxXPt.x() < strWidth) + if (image_width * scale - maxXPt.x() < strWidth) { return QPointF( - image_width - (strWidth + 10), + image_width * scale - (strWidth + 10), maxXPt.y() - strHeight); //This will draw the text on the right hand side, up and to the left of the point where the line intersects } - if (image_height - maxYPt.y() < strHeight) + if (image_height * scale - maxYPt.y() < strHeight) return QPointF( maxYPt.x() - (strWidth + 10), - image_height - + image_height * scale - (strHeight + 10)); //This will draw the text on the bottom side, up and to the left of the point where the line intersects if (minYPt.y() < strHeight) return QPointF( - minYPt.x() + 10, + minYPt.x() * scale + 10, strHeight + 20); //This will draw the text on the top side, down and to the right of the point where the line intersects if (minXPt.x() < strWidth) return QPointF( 10, - minXPt.y() + + minXPt.y() * scale + strHeight + 20); //This will draw the text on the left hand side, down and to the right of the point where the line intersects - if (maxXPt.x() == image_width / 2 && maxXPt.y() == image_height / 2) + if (maxXPt.x() == image_width * scale / 2 && maxXPt.y() == image_height * scale / 2) return QPointF(-100, -100); //All of the points were off the screen return QPoint(maxXPt.x() - (strWidth + 10), maxXPt.y() - (strHeight + 10)); @@ -1241,13 +1317,15 @@ if (trackingBox.isNull()) return trackingBoxPixmap; - int x1 = (trackingBox.x() - margin); - int y1 = (trackingBox.y() - margin); - int w = (trackingBox.width() + margin * 2); - int h = (trackingBox.height() + margin * 2); + // We need to know which rendering strategy updateFrame used to determine the scaling. + const float scale = getScale(); - trackingBoxPixmap = image_frame->grab(QRect(x1, y1, w, h)); + int x1 = (trackingBox.x() - margin) * scale; + int y1 = (trackingBox.y() - margin) * scale; + int w = (trackingBox.width() + margin * 2) * scale; + int h = (trackingBox.height() + margin * 2) * scale; + trackingBoxPixmap = image_frame->grab(QRect(x1, y1, w, h)); return trackingBoxPixmap; }