8#include "config-kstars.h"
13#include "hips/hipsfinder.h"
14#include "kstarsdata.h"
22#ifdef HAVE_STELLARSOLVER
23#include "ekos/auxiliary/stellarsolverprofileeditor.h"
27#include "basedevice.h"
28#include "indi/indilistener.h"
31#include <KActionCollection>
33#include <QtConcurrent>
36#include <QGraphicsOpacityEffect>
37#include <QApplication>
38#include <QImageReader>
39#include <QGestureEvent>
40#include <QMutexLocker>
41#include <QElapsedTimer>
48#define ZOOM_DEFAULT 100.0f
52#define ZOOM_LOW_INCR 10
53#define ZOOM_HIGH_INCR 50
68 params->green.shadows = params->green.shadows +
shadow_diff;
69 params->green.shadows = KSUtils::clamp(params->green.shadows, 0.0f, 1.0f);
70 params->green.highlights = params->green.highlights +
highlight_diff;
71 params->green.highlights = KSUtils::clamp(params->green.highlights, 0.0f, 1.0f);
72 params->green.midtones = params->green.midtones +
midtones_diff;
73 params->green.midtones = std::max(params->green.midtones, 0.0f);
75 params->blue.shadows = params->blue.shadows +
shadow_diff;
76 params->blue.shadows = KSUtils::clamp(params->blue.shadows, 0.0f, 1.0f);
77 params->blue.highlights = params->blue.highlights +
highlight_diff;
78 params->blue.highlights = KSUtils::clamp(params->blue.highlights, 0.0f, 1.0f);
79 params->blue.midtones = params->blue.midtones +
midtones_diff;
80 params->blue.midtones = std::max(params->blue.midtones, 0.0f);
93 Stretch stretch(
static_cast<int>(m_ImageData->width()),
94 static_cast<int>(m_ImageData->height()),
95 m_ImageData->channels(), m_ImageData->dataType());
100 else if (autoStretch)
103 stretchParams = stretch.computeParams(m_ImageData->getImageBuffer());
104 emit newStretch(stretchParams);
112 stretch.run(m_ImageData->getImageBuffer(),
outputImage, m_PreviewSampling);
116void FITSView::setStretchParams(
const StretchParams ¶ms)
118 if (m_ImageData->channels() == 3)
121 stretchParams.grey_red = params.grey_red;
122 stretchParams.grey_red.shadows = std::max(stretchParams.grey_red.shadows, 0.0f);
123 stretchParams.grey_red.highlights = std::max(stretchParams.grey_red.highlights, 0.0f);
124 stretchParams.grey_red.midtones = std::max(stretchParams.grey_red.midtones, 0.0f);
129 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
131 m_QueueUpdate =
true;
137void FITSView::setStretch(
bool onOff)
139 if (stretchImage !=
onOff)
141 stretchImage =
onOff;
142 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
144 m_QueueUpdate =
true;
151void FITSView::setAutoStretchParams()
155 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
157 m_QueueUpdate =
true;
166 stretchImage = Options::autoStretch();
177#if defined (Q_OS_LINUX) || defined (Q_OS_OSX)
207 markerCrosshair.setX(0);
208 markerCrosshair.setY(0);
210 setBaseSize(740, 530);
212 m_ImageFrame =
new FITSLabel(
this);
213 m_ImageFrame->setMouseTracking(
true);
214 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
215 connect(m_ImageFrame, &FITSLabel::mouseOverPixel,
this, &FITSView::mouseOverPixel);
216 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
217 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
218 connect(m_ImageFrame, &FITSLabel::rectangleSelected,
this, &FITSView::processRectangle);
219 connect(
this, &FITSView::setRubberBand, m_ImageFrame, &FITSLabel::setRubberBand);
220 connect(
this, &FITSView::showRubberBand, m_ImageFrame, &FITSLabel::showRubberBand);
221 connect(
this, &FITSView::zoomRubberBand, m_ImageFrame, &FITSLabel::zoomRubberBand);
223 connect(Options::self(), &Options::HIPSOpacityChanged,
this, [
this]()
227 m_QueueUpdate =
true;
231 connect(Options::self(), &Options::HIPSOffsetXChanged,
this, [
this]()
235 m_QueueUpdate =
true;
236 m_HiPSOverlayPixmap =
QPixmap();
240 connect(Options::self(), &Options::HIPSOffsetYChanged,
this, [
this]()
244 m_QueueUpdate =
true;
245 m_HiPSOverlayPixmap =
QPixmap();
252 m_UpdateFrameTimer.setInterval(50);
253 m_UpdateFrameTimer.setSingleShot(
true);
256 this->updateFrame(
true);
264 noImageLabel =
new QLabel();
265 noImage.load(
":/images/noimage.png");
266 noImageLabel->setPixmap(noImage);
268 setWidget(noImageLabel);
282 m_UpdateFrameTimer.
stop();
292void FITSView::updateMouseCursor()
294 if (cursorMode == dragCursor)
298 if (!m_ImageFrame->getMouseButtonDown())
306 else if (cursorMode == selectCursor)
310 else if (cursorMode == scopeCursor)
314 else if (cursorMode == crosshairCursor)
328void FITSView::setCursorMode(CursorMode mode)
333 if (mode == scopeCursor && imageHasWCS())
335 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
345 if (m_ImageData ==
nullptr && noImageLabel !=
nullptr)
347 noImageLabel->setPixmap(
349 noImageLabel->setFixedSize(
width() - 5,
height() - 5);
358 if (floatingToolBar !=
nullptr)
363 bool setBayerParams =
false;
366 if ((m_ImageData !=
nullptr) && m_ImageData->hasDebayer())
368 setBayerParams =
true;
369 m_ImageData->getBayerParams(&
param);
381 filterStack.
push(FITS_NONE);
382 if (filter != FITS_NONE)
383 filterStack.
push(filter);
388 m_ImageData->setBayerParams(&
param);
393void FITSView::clearData()
397 noImageLabel =
new QLabel();
398 noImage.
load(
":/images/noimage.png");
399 noImageLabel->setPixmap(noImage);
410 if (floatingToolBar !=
nullptr)
419 filterStack.
push(FITS_NONE);
420 if (filter != FITS_NONE)
421 filterStack.
push(filter);
423 m_HiPSOverlayPixmap =
QPixmap();
428 if (m_ImageMask !=
nullptr)
429 m_ImageMask->setImageGeometry(data->width(), data->height());
438 emit failed(m_LastError);
443bool FITSView::processData()
449 connect(m_ImageData.
data(), &FITSData::dataChanged,
this, [
this]()
451 rescale(ZOOM_KEEP_LEVEL);
455 currentWidth = m_ImageData->width();
456 currentHeight = m_ImageData->height();
458 int image_width = currentWidth;
459 int image_height = currentHeight;
463 m_ImageFrame =
new FITSLabel(
this);
464 m_ImageFrame->setMouseTracking(
true);
465 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
466 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
467 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
469 m_ImageFrame->setSize(image_width, image_height);
475 m_ImageData->applyFilter(filter);
478 if (Options::adaptiveSampling() && (
availableRAM = KSUtils::getAvailableRAM()) > 0)
481 double max_size = image_width * image_height * 4;
487 m_AdaptiveSampling = 1;
488 else if (ratio < 0.2)
489 m_AdaptiveSampling = 2;
491 m_AdaptiveSampling = 4;
493 m_PreviewSampling = m_AdaptiveSampling;
501 if (rescale(ZOOM_FIT_WINDOW) ==
false)
503 m_LastError =
i18n(
"Rescaling image failed.");
511 if (rescale(ZOOM_KEEP_LEVEL) ==
false)
513 m_LastError =
i18n(
"Rescaling image failed.");
521 if ((mode == FITS_NORMAL || mode == FITS_ALIGN) &&
522 m_ImageData->hasWCS() && m_ImageData->getWCSState() == FITSData::Idle &&
523 Options::autoWCS() &&
533 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
537 if(floatingToolBar !=
nullptr)
544 m_QueueUpdate =
true;
549void FITSView::loadInFrame()
551 m_LastError = m_ImageData->getLastError();
554 if (fitsWatcher.
result() ==
false)
556 emit failed(m_LastError);
561 emit debayerToggled(m_ImageData->hasDebayer());
566 emit failed(m_LastError);
581FITSView::CursorMode FITSView::getCursorMode()
586void FITSView::enterEvent(
QEvent * event)
590 if (floatingToolBar && m_ImageData)
596 a->setStartValue(0.2);
603void FITSView::leaveEvent(
QEvent * event)
607 if (floatingToolBar && m_ImageData)
620bool FITSView::rescale(FITSZoom type)
625 int image_width = m_ImageData->width();
626 int image_height = m_ImageData->height();
627 currentWidth = image_width;
628 currentHeight = image_height;
631 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
635 case ZOOM_FIT_WINDOW:
636 if ((image_width >
width() || image_height >
height()))
638 double w =
baseSize().width() - BASE_OFFSET;
639 double h =
baseSize().height() - BASE_OFFSET;
648 double zoomX = floor((w /
static_cast<double>(currentWidth)) * 100.);
649 double zoomY = floor((h /
static_cast<double>(currentHeight)) * 100.);
650 (zoomX <
zoomY) ? currentZoom = zoomX : currentZoom =
zoomY;
652 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
653 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
655 if (currentZoom <= ZOOM_MIN)
656 emit actionUpdated(
"view_zoom_out",
false);
661 currentWidth = image_width;
662 currentHeight = image_height;
666 case ZOOM_KEEP_LEVEL:
668 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
669 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
680 m_ImageFrame->setScaledContents(
true);
681 doStretch(&rawImage);
685 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
689void FITSView::ZoomIn()
694 if (currentZoom >= ZOOM_DEFAULT && Options::limitedResourcesMode())
696 emit newStatus(
i18n(
"Cannot zoom in further due to active limited resources mode."), FITS_MESSAGE);
700 if (currentZoom < ZOOM_DEFAULT)
701 currentZoom += ZOOM_LOW_INCR;
703 currentZoom += ZOOM_HIGH_INCR;
705 emit actionUpdated(
"view_zoom_out",
true);
706 if (currentZoom >= zoomMax)
708 currentZoom = zoomMax;
709 emit actionUpdated(
"view_zoom_in",
false);
712 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
713 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
719 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
720 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
723void FITSView::ZoomOut()
728 if (currentZoom <= ZOOM_DEFAULT)
729 currentZoom -= ZOOM_LOW_INCR;
731 currentZoom -= ZOOM_HIGH_INCR;
733 if (currentZoom <= ZOOM_MIN)
735 currentZoom = ZOOM_MIN;
736 emit actionUpdated(
"view_zoom_out",
false);
739 emit actionUpdated(
"view_zoom_in",
true);
741 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
742 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
748 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
749 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
752void FITSView::ZoomToFit()
757 if (rawImage.
isNull() ==
false)
759 rescale(ZOOM_FIT_WINDOW);
762 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
767int FITSView::filterStars()
769 return ((m_ImageMask.
isNull() ==
false
770 && m_ImageMask->active()) ? m_ImageData->filterStars(m_ImageMask) : m_ImageData->getStarCenters().count());
773void FITSView::setImageMask(ImageMask *mask)
775 if (m_ImageMask.
isNull() ==
false)
779 mask->setImageGeometry(m_ImageMask->width(), m_ImageMask->height());
787bool FITSView::isLargeImage()
798double FITSView::getScale()
800 return (isLargeImage() ? 1.0 : currentZoom / ZOOM_DEFAULT) / m_PreviewSampling;
806double FITSView::scaleSize(
double size)
810 return (currentZoom > 100.0 ?
size :
std::round(
size * 100.0 / currentZoom)) / m_PreviewSampling;
813void FITSView::updateFrame(
bool now)
827 if (toggleStretchAction)
828 toggleStretchAction->
setChecked(stretchImage);
835 updateFrameLargeImage();
837 updateFrameSmallImage();
839 if (m_QueueUpdate && m_StretchingInProgress ==
false)
841 m_QueueUpdate =
false;
846 m_UpdateFrameTimer.
start();
850bool FITSView::initDisplayPixmap(
QImage &image,
float scale)
852 ImageMosaicMask *
mask =
dynamic_cast<ImageMosaicMask *
>(m_ImageMask.
get());
861 int space =
mask->space();
863 displayPixmap =
QPixmap((3 *
width + 2 * space) * scale, (3 *
width + 2 * space) * scale);
876 painter.drawImage(target, image, source);
881void FITSView::updateFrameLargeImage()
883 if (!initDisplayPixmap(rawImage, 1.0 / m_PreviewSampling))
889 painter.setFont(
font);
891 drawStarRingFilter(&painter, 1.0 / m_PreviewSampling,
dynamic_cast<ImageRingMask *
>(m_ImageMask.
get()));
892 drawOverlay(&painter, 1.0 / m_PreviewSampling);
893 m_ImageFrame->setPixmap(displayPixmap);
894 m_ImageFrame->resize(((m_PreviewSampling * currentZoom) / 100.0) * displayPixmap.
size());
897void FITSView::updateFrameSmallImage()
900 if (!initDisplayPixmap(
scaledImage, currentZoom / ZOOM_DEFAULT))
906 drawStarRingFilter(&painter, currentZoom / ZOOM_DEFAULT,
dynamic_cast<ImageRingMask *
>(m_ImageMask.
get()));
907 drawOverlay(&painter, currentZoom / ZOOM_DEFAULT);
908 m_ImageFrame->setPixmap(displayPixmap);
909 m_ImageFrame->resize(currentWidth, currentHeight);
912void FITSView::drawStarRingFilter(
QPainter *painter,
double scale, ImageRingMask *
ringMask)
917 const double w = m_ImageData->width() * scale;
918 const double h = m_ImageData->height() * scale;
919 double const diagonal = std::sqrt(w * w + h * h) / 2;
927 painter->
drawEllipse(center, outerRadius, outerRadius);
929 painter->
drawEllipse(center, innerRadius, innerRadius);
947 for (
int y = 0; y < height; y++)
951 for (
int x = 0; x < width; x++)
963 painter->
drawLine(start, y, width - 1, y);
976 painter->
drawLine(start, y, x - 1, y);
1003 const int size = width * height;
1004 for (
int y = 0; y < height; y++)
1012 for (
int x = 0; x < width; x++)
1021 const int start = x;
1029 painter->
drawLine(start, y, width - 1, y);
1045 painter->
drawLine(start, y, x - 1, y);
1061template <
typename T>
1073void FITSView::drawClipping(
QPainter *painter)
1075 auto input = m_ImageData->getImageBuffer();
1076 const int height = m_ImageData->height();
1077 const int width = m_ImageData->width();
1078 const double FLOAT_CLIP = Options::clipping64KValue();
1079 const double SHORT_CLIP = Options::clipping64KValue();
1080 const double USHORT_CLIP = Options::clipping64KValue();
1081 const double BYTE_CLIP = Options::clipping256Value();
1082 switch (m_ImageData->dataType())
1093 m_NumClipped =
drawClip(
reinterpret_cast<unsigned short const*
>(input), m_ImageData->channels(), painter,
width,
height,
1106 m_NumClipped =
drawClip(
reinterpret_cast<long long const*
>(input), m_ImageData->channels(), painter,
width,
height,
1118 if (m_NumClipped < 0)
1119 emit newStatus(
QString(
"Clip:failed"), FITS_CLIP);
1121 emit newStatus(
QString(
"Clip:%1").arg(m_NumClipped), FITS_CLIP);
1124void FITSView::ZoomDefault()
1128 emit actionUpdated(
"view_zoom_out",
true);
1129 emit actionUpdated(
"view_zoom_in",
true);
1131 currentZoom = ZOOM_DEFAULT;
1132 currentWidth = m_ImageData->width();
1133 currentHeight = m_ImageData->height();
1137 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
1143void FITSView::drawOverlay(
QPainter * painter,
double scale)
1147#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1148 if (showHiPSOverlay)
1152 if (trackingBoxEnabled && getCursorMode() != FITSView::scopeCursor)
1153 drawTrackingBox(painter, scale);
1155 if (!markerCrosshair.
isNull())
1156 drawMarker(painter, scale);
1159 drawCrosshair(painter, scale);
1162 drawObjectNames(painter, scale);
1164#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1170 drawPixelGrid(painter, scale);
1173 drawStarCentroid(painter, scale);
1176 drawClipping(painter);
1178 if (showMagnifyingGlass)
1179 drawMagnifyingGlass(painter, scale);
1183void FITSView::drawMagnifyingGlass(
QPainter *painter,
double scale)
1185 if (magnifyingGlassX >= 0 && magnifyingGlassY >= 0 &&
1212 int w = rawImage.
width();
1213 int h = rawImage.
height();
1243void FITSView::updateMagnifyingGlass(
int x,
int y)
1248 magnifyingGlassX =
x;
1249 magnifyingGlassY =
y;
1250 if (magnifyingGlassX == -1 && magnifyingGlassY == -1)
1252 if (showMagnifyingGlass)
1254 showMagnifyingGlass =
false;
1258 showMagnifyingGlass =
true;
1263void FITSView::updateMode(FITSMode
fmode)
1268void FITSView::drawMarker(
QPainter * painter,
double scale)
1270 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")),
1279 const float x0 = scale * markerCrosshair.
x();
1280 const float y0 = scale * markerCrosshair.
y();
1281 const float x1 =
x0 - 0.5 *
s1;
1282 const float y1 = y0 - 0.5 *
s1;
1283 const float x2 =
x0 - 0.5 *
s2;
1284 const float y2 = y0 - 0.5 *
s2;
1285 const float x3 =
x0 - 0.5 *
s3;
1286 const float y3 = y0 - 0.5 *
s3;
1298bool FITSView::drawHFR(
QPainter * painter,
const QString &hfr,
int x,
int y)
1308 if (boundingRect.contains(
hfrRect))
1319void FITSView::drawStarCentroid(
QPainter * painter,
double scale)
1334 ImageMosaicMask *
mask =
dynamic_cast<ImageMosaicMask *
>(m_ImageMask.
get());
1336 for (
auto const &starCenter : m_ImageData->getStarCenters())
1338 int const w = std::round(starCenter->width) * scale;
1347 const int xc = std::round((
xCoord - starCenter->width / 2.0f) * scale);
1348 const int yc = std::round((
yCoord - starCenter->width / 2.0f) * scale);
1349 const int hw = w / 2;
1351 BahtinovEdge*
bEdge =
dynamic_cast<BahtinovEdge*
>(starCenter);
1352 if (
bEdge !=
nullptr)
1357 bEdge->line[0].x2() * scale,
bEdge->line[0].y2() * scale);
1360 bEdge->line[1].x2() * scale,
bEdge->line[1].y2() * scale);
1363 bEdge->line[2].x2() * scale,
bEdge->line[2].y2() * scale);
1370 double factor = 15.0;
1385 const double radius = starCenter->HFR > 0 ? 2.0f * starCenter->HFR * scale : w;
1394 if (!drawHFR(painter, hfr,
xc + w + 5, yc + w / 2))
1397 for (
int i = 0; i < 10; ++i)
1403 if (drawHFR(painter, hfr,
xc + w + 5, yc + w / 2))
1414void FITSView::drawTrackingBox(
QPainter * painter,
double scale)
1418 if (trackingBox.
isNull())
1421 const int x1 = trackingBox.
x() * scale;
1422 const int y1 = trackingBox.
y() * scale;
1423 const int w = trackingBox.
width() * scale;
1424 const int h = trackingBox.
height() * scale;
1433void FITSView::drawCrosshair(
QPainter * painter,
double scale)
1435 if (!m_ImageData)
return;
1436 const int image_width = m_ImageData->width();
1437 const int image_height = m_ImageData->height();
1438 const QPointF c =
QPointF((qreal)image_width / 2 * scale, (qreal)image_height / 2 * scale);
1439 const float midX = (float)image_width / 2 * scale;
1440 const float midY = (float)image_height / 2 * scale;
1441 const float maxX = (float)image_width * scale;
1442 const float maxY = (float)image_height * scale;
1443 const float r = 50 * scale;
1445 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")), scaleSize(1)));
1472void FITSView::drawPixelGrid(
QPainter * painter,
double scale)
1474 const float width = m_ImageData->width() * scale;
1475 const float height = m_ImageData->height() * scale;
1486#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1509#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1515#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1524bool FITSView::imageHasWCS()
1526 if (m_ImageData !=
nullptr)
1527 return m_ImageData->hasWCS();
1531void FITSView::drawObjectNames(
QPainter * painter,
double scale)
1533 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"FITSObjectLabelColor"))));
1534 for (
const auto &
listObject : m_ImageData->getSkyObjects())
1541#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1542void FITSView::drawHiPSOverlay(
QPainter * painter,
double scale)
1544 if (m_HiPSOverlayPixmap.
isNull())
1546 auto width = m_ImageData->width();
1547 auto height = m_ImageData->height();
1553 m_ImageData->pixelToWCS(
QPointF(0, 0), startPoint);
1555 m_ImageData->pixelToWCS(
QPointF( (
width - Options::hIPSOffsetX()) / 2.0, (
height - Options::hIPSOffsetY()) / 2.0),
1564 m_ImageData->getRecordValue(
"CROTA1", PA);
1566 auto rotation = 180 - PA.toDouble();
1570 if (HIPSFinder::Instance()->renderFOV(¢erPoint,
fov_radius, rotation, &image) ==
false)
1577 painter->
drawPixmap(0, 0, m_HiPSOverlayPixmap);
1589#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1590void FITSView::drawEQGrid(
QPainter * painter,
double scale)
1592 const int image_width = m_ImageData->width();
1593 const int image_height = m_ImageData->height();
1595 if (m_ImageData->hasWCS())
1597 double maxRA = -1000;
1598 double minRA = 1000;
1607 (int)(
minRA / 15.0 *
1617 (int)(
minRA / 15.0 * 60.0);
1625 (int)(
minRA / 15.0 * 30);
1632 (int)(
minRA / 15.0 * 6);
1656 if (eqGridPoints.count() != 0)
1657 eqGridPoints.clear();
1669 eqGridPoints.append(pt);
1673 if (eqGridPoints.count() > 1)
1675 for (
int i = 1; i < eqGridPoints.count(); i++)
1676 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1681 QPointF pt = getPointForGridLabel(painter, str, scale);
1691 if (eqGridPoints.count() != 0)
1692 eqGridPoints.clear();
1694 double increment = std::abs((
maxRA -
minRA) /
1705 eqGridPoints.append(pt);
1708 if (eqGridPoints.count() > 1)
1710 for (
int i = 1; i < eqGridPoints.count(); i++)
1711 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1713 QPointF pt = getPointForGridLabel(painter, str, scale);
1730 KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor"));
1732 i18nc(
"North Celestial Pole",
"NCP"));
1747 KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor"));
1749 i18nc(
"South Celestial Pole",
"SCP"));
1756bool FITSView::pointIsInImage(
QPointF pt,
double scale)
1758 int image_width = m_ImageData->width();
1759 int image_height = m_ImageData->height();
1760 return pt.
x() < image_width * scale && pt.
y() < image_height * scale && pt.
x() > 0 && pt.
y() > 0;
1766#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1772 int image_width = m_ImageData->width();
1773 int image_height = m_ImageData->height();
1776 QPointF maxXPt(image_width * scale / 2, image_height * scale / 2);
1777 for (
auto &p : eqGridPoints)
1779 if (p.
x() >
maxXPt.x() && pointIsInImage(p, scale))
1782 QPointF maxYPt(image_width * scale / 2, image_height * scale / 2);
1784 for (
auto &p : eqGridPoints)
1786 if (p.
y() >
maxYPt.y() && pointIsInImage(p, scale))
1789 QPointF minXPt(image_width * scale / 2, image_height * scale / 2);
1791 for (
auto &p : eqGridPoints)
1793 if (p.
x() <
minXPt.x() && pointIsInImage(p, scale))
1796 QPointF minYPt(image_width * scale / 2, image_height * scale / 2);
1798 for (
auto &p : eqGridPoints)
1800 if (p.
y() <
minYPt.y() && pointIsInImage(p, scale))
1812 image_width * scale - (
strWidth + 10),
1819 image_height * scale -
1831 if (
maxXPt.x() == image_width * scale / 2 &&
maxXPt.y() == image_height * scale / 2)
1837void FITSView::setFirstLoad(
bool value)
1842QPixmap &FITSView::getTrackingBoxPixmap(uint8_t margin)
1844 if (trackingBox.
isNull())
1845 return trackingBoxPixmap;
1848 const float scale = getScale();
1850 int x1 = (trackingBox.
x() - margin) * scale;
1851 int y1 = (trackingBox.
y() - margin) * scale;
1852 int w = (trackingBox.
width() + margin * 2) * scale;
1853 int h = (trackingBox.
height() + margin * 2) * scale;
1855 trackingBoxPixmap = m_ImageFrame->grab(
QRect(x1, y1, w, h));
1856 return trackingBoxPixmap;
1859void FITSView::setTrackingBox(
const QRect &rect)
1861 if (
rect != trackingBox)
1870void FITSView::resizeTrackingBox(
int newSize)
1872 int x = trackingBox.
x() + trackingBox.
width() / 2;
1873 int y = trackingBox.
y() + trackingBox.
height() / 2;
1874 int delta = newSize / 2;
1875 setTrackingBox(
QRect(
x - delta,
y - delta, newSize, newSize));
1878void FITSView::processRectangleFixed(
int s)
1880 int w = m_ImageData->width();
1881 int h = m_ImageData->height();
1884 c.
setX(
qMax((
int)round(s / 2.0), c.
x()));
1885 c.
setX(
qMin(w - (
int)round(s / 2.0), c.
x()));
1886 c.
setY(
qMax((
int)round(s / 2.0), c.
y()));
1887 c.
setY(
qMin(h - (
int)round(s / 2.0), c.
y()));
1890 topLeft =
QPoint(c.
x() - round(s / 2.0), c.
y() - round(s / 2.0));
1894 processRectangle(topLeft,
botRight,
true);
1899 if(!isSelectionRectShown())
1925 m_ImageData->makeRoiBuffer(selectionRectangleRaw);
1926 emit rectangleUpdated(selectionRectangleRaw);
1935bool FITSView::isImageStretched()
1937 return stretchImage;
1940bool FITSView::isClippingShown()
1942 return showClipping;
1945bool FITSView::isCrosshairShown()
1947 return showCrosshair;
1950bool FITSView::isEQGridShown()
1955bool FITSView::isSelectionRectShown()
1957 return showSelectionRect;
1959bool FITSView::areObjectsShown()
1964bool FITSView::isPixelGridShown()
1966 return showPixelGrid;
1969bool FITSView::isHiPSOverlayShown()
1971 return showHiPSOverlay;
1974void FITSView::toggleCrosshair()
1976 showCrosshair = !showCrosshair;
1980void FITSView::toggleClipping()
1982 showClipping = !showClipping;
1986void FITSView::toggleEQGrid()
1988 showEQGrid = !showEQGrid;
1990 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2001void FITSView::toggleHiPSOverlay()
2003 showHiPSOverlay = !showHiPSOverlay;
2005 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2014 m_QueueUpdate =
true;
2019void FITSView::toggleSelectionMode()
2021 showSelectionRect = !showSelectionRect;
2022 if (!showSelectionRect)
2024 else if (m_ImageData)
2026 m_ImageData->makeRoiBuffer(selectionRectangleRaw);
2027 emit rectangleUpdated(selectionRectangleRaw);
2030 emit showRubberBand(showSelectionRect);
2035void FITSView::toggleObjects()
2037 showObjects = !showObjects;
2039 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2048#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
2049 m_ImageData->searchObjects();
2055void FITSView::toggleStars()
2057 toggleStars(!markStars);
2062void FITSView::toggleStretch()
2064 stretchImage = !stretchImage;
2065 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
2069void FITSView::toggleStarProfile()
2071#ifdef HAVE_DATAVISUALIZATION
2072 showStarProfile = !showStarProfile;
2073 if(showStarProfile && trackingBoxEnabled)
2075 if(toggleProfileAction)
2076 toggleProfileAction->
setChecked(showStarProfile);
2082 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
2084 setCursorMode(selectCursor);
2085 connect(
this,
SIGNAL(trackingStarSelected(
int,
int)),
this,
SLOT(move3DTrackingBox(
int,
int)));
2086 trackingBox =
QRect(0, 0, 128, 128);
2087 setTrackingBoxEnabled(
true);
2098 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
2100 if(getCursorMode() == selectCursor)
2101 setCursorMode(dragCursor);
2102 disconnect(
this,
SIGNAL(trackingStarSelected(
int,
int)),
this,
SLOT(move3DTrackingBox(
int,
int)));
2103 setTrackingBoxEnabled(
false);
2113 emit starProfileWindowClosed();
2119void FITSView::move3DTrackingBox(
int x,
int y)
2126void FITSView::viewStarProfile()
2128#ifdef HAVE_DATAVISUALIZATION
2129 if(!trackingBoxEnabled)
2131 setTrackingBoxEnabled(
true);
2132 setTrackingBox(
QRect(0, 0, 128, 128));
2148 if(mode == FITS_ALIGN || mode == FITS_NORMAL)
2151 m_ImageData->setStarAlgorithm(ALGORITHM_CENTROID);
2155 QList<Edge *> starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
2156 if(starCenters.size() == 0)
2161 m_ImageData->findStars(ALGORITHM_CENTROID, trackingBox).waitForFinished();
2162 starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
2174void FITSView::togglePixelGrid()
2176 showPixelGrid = !showPixelGrid;
2182 if(trackingBoxEnabled)
2183 return m_ImageData->findStars(algorithm, trackingBox);
2185 return m_ImageData->findStars(algorithm,
searchBox);
2188void FITSView::toggleStars(
bool enable)
2196void FITSView::searchStars()
2199 if (m_ImageData->areStarsSearched() || !m_ImageData || (m_ImageData->getRecordValue(
"FRAME", frameType)
2200 && frameType.
toString() !=
"Light"))
2204 emit newStatus(
i18n(
"Finding stars..."), FITS_MESSAGE);
2205 qApp->processEvents();
2207#ifdef HAVE_STELLARSOLVER
2215 result.waitForFinished();
2218 emit newStatus(
"", FITS_MESSAGE);
2223void FITSView::processPointSelection(
int x,
int y)
2225 emit trackingStarSelected(
x,
y);
2228void FITSView::processMarkerSelection(
int x,
int y)
2230 markerCrosshair.
setX(
x);
2231 markerCrosshair.
setY(
y);
2236void FITSView::setTrackingBoxEnabled(
bool enable)
2238 if (enable != trackingBoxEnabled)
2240 trackingBoxEnabled = enable;
2255#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2260 if (
event->angleDelta().y() > 0)
2267 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
2276void FITSView::cleanUpZoom(
QPoint viewCenter)
2280 double scale = (currentZoom / ZOOM_DEFAULT);
2281 if (!markerCrosshair.
isNull())
2283 x0 = markerCrosshair.
x() * scale;
2284 y0 = markerCrosshair.
y() * scale;
2286 else if (trackingBoxEnabled)
2289 y0 = trackingBox.
center().
y() * scale;
2291 else if (!viewCenter.
isNull())
2293 x0 = viewCenter.
x() * scale;
2294 y0 = viewCenter.
y() * scale;
2296 if ((
x0 != 0) || (y0 != 0))
2298 updateMouseCursor();
2313 double scale = (currentZoom / ZOOM_DEFAULT);
2319void FITSView::initDisplayImage()
2323 int w = (m_ImageData->width() + m_PreviewSampling - 1) / m_PreviewSampling;
2324 int h = (m_ImageData->height() + m_PreviewSampling - 1) / m_PreviewSampling;
2326 if (m_ImageData->channels() == 1)
2331 for (
int i = 0; i < 256; i++)
2332 rawImage.
setColor(i, qRgb(i, i, i));
2347bool FITSView::event(
QEvent * event)
2378 if (zoomTime > 10000)
2380 if (zooming && (zoomTime % 10 == 0))
2387 cleanUpZoom(zoomLocation);
2398void FITSView::syncWCSState()
2400 bool hasWCS = m_ImageData->hasWCS();
2401 bool wcsLoaded = m_ImageData->getWCSState() == FITSData::Success;
2403#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
2405 m_ImageData->searchObjects();
2409 this->updateFrame();
2411 emit wcsToggled(hasWCS);
2413 if (toggleEQGridAction !=
nullptr)
2415 if (toggleObjectsAction !=
nullptr)
2417 if (centerTelescopeAction !=
nullptr)
2419 if (toggleHiPSOverlayAction !=
nullptr)
2423void FITSView::createFloatingToolBar()
2425 if (floatingToolBar !=
nullptr)
2428 floatingToolBar =
new QToolBar(
this);
2431 eff->setOpacity(0.2);
2434 "QToolBar{background: rgba(150, 150, 150, 210); border:none; color: yellow}"
2435 "QToolButton{background: transparent; border:none; color: yellow}"
2436 "QToolButton:hover{background: rgba(200, 200, 200, 255);border:solid; color: yellow}"
2437 "QToolButton:checked{background: rgba(110, 110, 110, 255);border:solid; color: yellow}");
2445 i18n(
"Zoom In"),
this,
SLOT(ZoomIn()));
2448 i18n(
"Zoom Out"),
this,
SLOT(ZoomOut()));
2451 i18n(
"Default Zoom"),
this,
SLOT(ZoomDefault()));
2454 i18n(
"Zoom to Fit"),
this,
SLOT(ZoomToFit()));
2457 i18n(
"Toggle Stretch"),
2458 this,
SLOT(toggleStretch()));
2465 i18n(
"Show Cross Hairs"),
this,
SLOT(toggleCrosshair()));
2469 i18n(
"Show Pixel Gridlines"),
this,
SLOT(togglePixelGrid()));
2474 i18n(
"Detect Stars in Image"),
this,
SLOT(toggleStars()));
2477#ifdef HAVE_DATAVISUALIZATION
2478 toggleProfileAction =
2480 i18n(
"View Star Profile..."),
this,
SLOT(toggleStarProfile()));
2484 if (mode == FITS_NORMAL || mode == FITS_ALIGN)
2488 toggleEQGridAction =
2490 i18n(
"Show Equatorial Gridlines"),
this, &FITSView::toggleEQGrid);
2494 toggleObjectsAction =
2496 i18n(
"Show Objects in Image"),
this, &FITSView::toggleObjects);
2500 centerTelescopeAction =
2502 i18n(
"Center Telescope"),
this, &FITSView::centerTelescope);
2506 toggleHiPSOverlayAction =
2508 i18n(
"Show HiPS Overlay"),
this, &FITSView::toggleHiPSOverlay);
2519void FITSView::centerTelescope()
2523 if (getCursorMode() == FITSView::scopeCursor)
2525 setCursorMode(lastMouseMode);
2529 lastMouseMode = getCursorMode();
2530 setCursorMode(FITSView::scopeCursor);
2534 updateScopeButton();
2537void FITSView::updateScopeButton()
2539 if (centerTelescopeAction !=
nullptr)
2541 if (getCursorMode() == FITSView::scopeCursor)
2556bool FITSView::isTelescopeActive()
2559 if (INDIListener::Instance()->
size() == 0)
2566 if (!(
oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE))
2576void FITSView::setStarsEnabled(
bool enable)
2579 if (floatingToolBar !=
nullptr)
2583 if (action->
text() ==
i18n(
"Detect Stars in Image"))
2592void FITSView::setStarsHFREnabled(
bool enable)
2594 showStarsHFR = enable;
INDIListener is responsible for creating ISD::GDInterface generic devices as new devices arrive from ...
The sky coordinates of a point in the sky.
virtual void updateCoordsNow(const KSNumbers *num)
updateCoordsNow Shortcut for updateCoords( const KSNumbers *num, false, nullptr, nullptr,...
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
An angle, stored as degrees, but expressible in many ways.
const double & Degrees() const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
KREPORT_EXPORT QPageSize::PageSizeId pageSize(const QString &key)
QString suffix() const const
void setPixelSize(int pixelSize)
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
bool isRunning() const const
void setFuture(const QFuture< T > &future)
void restoreOverrideCursor()
void setOverrideCursor(const QCursor &cursor)
QIcon fromTheme(const QString &name)
bool isNull() const const
bool save(QIODevice *device, const char *format, int quality) const const
QImage scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
void setColor(int index, QRgb colorValue)
void setColorCount(int colorCount)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QPaintDevice * device() const const
void drawEllipse(const QPoint ¢er, int rx, int ry)
void drawImage(const QPoint &point, const QImage &image)
void drawLine(const QLine &line)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void drawPoints(const QPoint *points, int pointCount)
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
void fillRect(const QRect &rectangle, QGradient::Preset preset)
const QFont & font() const const
QFontMetrics fontMetrics() const const
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setOpacity(qreal opacity)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
bool convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
void fill(const QColor &color)
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
bool isNull() const const
bool load(const QString &fileName, const char *format, Qt::ImageConversionFlags flags)
QPixmap scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
bool isNull() const const
bool isNull() const const
QPoint bottomRight() const const
QPoint center() const const
bool isNull() const const
QRect normalized() const const
void setBottomRight(const QPoint &position)
void setTopLeft(const QPoint &position)
QPoint topLeft() const const
void translate(const QPoint &point)
bool isNull() const const
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
MouseEventSynthesizedBySystem
QTextStream & center(QTextStream &stream)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const