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>
32#include <KLocalizedString>
34#include <QtConcurrent>
37#include <QGraphicsOpacityEffect>
38#include <QApplication>
39#include <QImageReader>
40#include <QGestureEvent>
41#include <QMutexLocker>
42#include <QElapsedTimer>
49#define ZOOM_DEFAULT 100.0f
53#define ZOOM_LOW_INCR 10
54#define ZOOM_HIGH_INCR 50
63void ComputeGBStretchParams(
const StretchParams &newParams, StretchParams* params)
65 float shadow_diff = newParams.grey_red.shadows - params->grey_red.shadows;
66 float highlight_diff = newParams.grey_red.highlights - params->grey_red.highlights;
67 float midtones_diff = newParams.grey_red.midtones - params->grey_red.midtones;
69 params->green.shadows = params->green.shadows + shadow_diff;
70 params->green.shadows = KSUtils::clamp(params->green.shadows, 0.0f, 1.0f);
71 params->green.highlights = params->green.highlights + highlight_diff;
72 params->green.highlights = KSUtils::clamp(params->green.highlights, 0.0f, 1.0f);
73 params->green.midtones = params->green.midtones + midtones_diff;
74 params->green.midtones = std::max(params->green.midtones, 0.0f);
76 params->blue.shadows = params->blue.shadows + shadow_diff;
77 params->blue.shadows = KSUtils::clamp(params->blue.shadows, 0.0f, 1.0f);
78 params->blue.highlights = params->blue.highlights + highlight_diff;
79 params->blue.highlights = KSUtils::clamp(params->blue.highlights, 0.0f, 1.0f);
80 params->blue.midtones = params->blue.midtones + midtones_diff;
81 params->blue.midtones = std::max(params->blue.midtones, 0.0f);
90void FITSView::doStretch(
QImage *outputImage)
94 Stretch stretch(
static_cast<int>(m_ImageData->width()),
95 static_cast<int>(m_ImageData->height()),
96 m_ImageData->channels(), m_ImageData->dataType());
98 StretchParams tempParams;
100 tempParams = StretchParams();
101 else if (autoStretch)
104 stretchParams = stretch.computeParams(m_ImageData->getImageBuffer());
105 emit newStretch(stretchParams);
106 tempParams = stretchParams;
110 tempParams = stretchParams;
112 stretch.setParams(tempParams);
113 stretch.run(m_ImageData->getImageBuffer(), outputImage, m_PreviewSampling);
117void FITSView::setStretchParams(
const StretchParams ¶ms)
119 if (m_ImageData->channels() == 3)
120 ComputeGBStretchParams(params, &stretchParams);
122 stretchParams.grey_red = params.grey_red;
123 stretchParams.grey_red.shadows = std::max(stretchParams.grey_red.shadows, 0.0f);
124 stretchParams.grey_red.highlights = std::max(stretchParams.grey_red.highlights, 0.0f);
125 stretchParams.grey_red.midtones = std::max(stretchParams.grey_red.midtones, 0.0f);
130 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
132 m_QueueUpdate =
true;
138void FITSView::setStretch(
bool onOff)
140 if (stretchImage != onOff)
142 stretchImage = onOff;
143 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
145 m_QueueUpdate =
true;
152void FITSView::setAutoStretchParams()
156 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
158 m_QueueUpdate =
true;
163FITSView::FITSView(
QWidget * parent, FITSMode fitsMode, FITSScale filterType) :
QScrollArea(parent), m_ZoomFactor(1.2)
174 stretchImage = Options::autoStretch();
185#if defined (Q_OS_LINUX) || defined (Q_OS_OSX)
186 const long numPages = sysconf(_SC_PAGESIZE);
187 const long pageSize = sysconf(_SC_PHYS_PAGES);
191 if (numPages > 0 && pageSize > 0)
194 const int memoryMb = numPages * (
static_cast<double>(
pageSize) / 1e6);
197 else if (memoryMb < 4000)
199 else if (memoryMb < 8000)
201 else if (memoryMb < 16000)
215 markerCrosshair.setX(0);
216 markerCrosshair.setY(0);
218 setBaseSize(740, 530);
220 m_ImageFrame =
new FITSLabel(
this);
221 m_ImageFrame->setMouseTracking(
true);
222 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
223 connect(m_ImageFrame, &FITSLabel::mouseOverPixel,
this, &FITSView::mouseOverPixel);
224 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
225 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
226 connect(m_ImageFrame, &FITSLabel::rectangleSelected,
this, &FITSView::processRectangle);
227 connect(
this, &FITSView::setRubberBand, m_ImageFrame, &FITSLabel::setRubberBand);
228 connect(
this, &FITSView::showRubberBand, m_ImageFrame, &FITSLabel::showRubberBand);
229 connect(
this, &FITSView::zoomRubberBand, m_ImageFrame, &FITSLabel::zoomRubberBand);
231 connect(Options::self(), &Options::HIPSOpacityChanged,
this, [
this]()
235 m_QueueUpdate =
true;
239 connect(Options::self(), &Options::HIPSOffsetXChanged,
this, [
this]()
243 m_QueueUpdate =
true;
244 m_HiPSOverlayPixmap =
QPixmap();
248 connect(Options::self(), &Options::HIPSOffsetYChanged,
this, [
this]()
252 m_QueueUpdate =
true;
253 m_HiPSOverlayPixmap =
QPixmap();
260 m_UpdateFrameTimer.setInterval(50);
261 m_UpdateFrameTimer.setSingleShot(
true);
264 this->updateFrame(
true);
272 noImageLabel =
new QLabel();
273 noImage.load(
":/images/noimage.png");
274 noImageLabel->setPixmap(noImage);
276 setWidget(noImageLabel);
290 m_UpdateFrameTimer.
stop();
300void FITSView::updateMouseCursor()
302 if (cursorMode == dragCursor)
306 if (!m_ImageFrame->getMouseButtonDown())
314 else if (cursorMode == selectCursor)
318 else if (cursorMode == scopeCursor)
322 else if (cursorMode == crosshairCursor)
336void FITSView::setCursorMode(CursorMode mode)
341 if (mode == scopeCursor && imageHasWCS())
343 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
353 if (m_ImageData ==
nullptr && noImageLabel !=
nullptr)
355 noImageLabel->setPixmap(
357 noImageLabel->setFixedSize(
width() - 5,
height() - 5);
364void FITSView::loadFile(
const QString &inFilename)
366 if (floatingToolBar !=
nullptr)
371 bool setBayerParams =
false;
374 if ((m_ImageData !=
nullptr) && m_ImageData->hasDebayer())
376 setBayerParams =
true;
377 m_ImageData->getBayerParams(¶m);
389 filterStack.
push(FITS_NONE);
390 if (filter != FITS_NONE)
391 filterStack.
push(filter);
396 m_ImageData->setBayerParams(¶m);
398 fitsWatcher.
setFuture(m_ImageData->loadFromFile(inFilename));
401void FITSView::clearData()
405 noImageLabel =
new QLabel();
406 noImage.
load(
":/images/noimage.png");
407 noImageLabel->setPixmap(noImage);
418 if (floatingToolBar !=
nullptr)
427 filterStack.
push(FITS_NONE);
428 if (filter != FITS_NONE)
429 filterStack.
push(filter);
431 m_HiPSOverlayPixmap =
QPixmap();
436 if (m_ImageMask !=
nullptr)
437 m_ImageMask->setImageGeometry(data->width(), data->height());
446 emit failed(m_LastError);
451bool FITSView::processData()
457 connect(m_ImageData.
data(), &FITSData::dataChanged,
this, [
this]()
459 rescale(ZOOM_KEEP_LEVEL);
463 currentWidth = m_ImageData->width();
464 currentHeight = m_ImageData->height();
466 int image_width = currentWidth;
467 int image_height = currentHeight;
471 m_ImageFrame =
new FITSLabel(
this);
472 m_ImageFrame->setMouseTracking(
true);
473 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
474 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
475 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
477 m_ImageFrame->setSize(image_width, image_height);
483 m_ImageData->applyFilter(filter);
485 double availableRAM = 0;
486 if (Options::adaptiveSampling() && (availableRAM = KSUtils::getAvailableRAM()) > 0)
489 double max_size = image_width * image_height * 4;
491 double ratio = max_size / availableRAM;
495 m_AdaptiveSampling = 1;
496 else if (ratio < 0.2)
497 m_AdaptiveSampling = 2;
499 m_AdaptiveSampling = 4;
501 m_PreviewSampling = m_AdaptiveSampling;
509 if (rescale(ZOOM_FIT_WINDOW) ==
false)
511 m_LastError =
i18n(
"Rescaling image failed.");
519 if (rescale(ZOOM_KEEP_LEVEL) ==
false)
521 m_LastError =
i18n(
"Rescaling image failed.");
529 if ((mode == FITS_NORMAL || mode == FITS_ALIGN) &&
530 m_ImageData->hasWCS() && m_ImageData->getWCSState() == FITSData::Idle &&
531 Options::autoWCS() &&
541 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
545 if(floatingToolBar !=
nullptr)
552 m_QueueUpdate =
true;
557void FITSView::loadInFrame()
559 m_LastError = m_ImageData->getLastError();
562 if (fitsWatcher.
result() ==
false)
564 emit failed(m_LastError);
569 emit debayerToggled(m_ImageData->hasDebayer());
574 emit failed(m_LastError);
577bool FITSView::saveImage(
const QString &newFilename)
586 return m_ImageData->saveImage(newFilename);
589FITSView::CursorMode FITSView::getCursorMode()
594void FITSView::enterEvent(
QEvent * event)
598 if (floatingToolBar && m_ImageData)
604 a->setStartValue(0.2);
611void FITSView::leaveEvent(
QEvent * event)
615 if (floatingToolBar && m_ImageData)
628bool FITSView::rescale(FITSZoom type)
633 int image_width = m_ImageData->width();
634 int image_height = m_ImageData->height();
635 currentWidth = image_width;
636 currentHeight = image_height;
639 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
643 case ZOOM_FIT_WINDOW:
644 if ((image_width >
width() || image_height >
height()))
646 double w =
baseSize().width() - BASE_OFFSET;
647 double h =
baseSize().height() - BASE_OFFSET;
656 double zoomX = (w /
static_cast<double>(currentWidth)) * 100.0;
657 double zoomY = (h /
static_cast<double>(currentHeight)) * 100.0;
659 (zoomX < zoomY) ? currentZoom = zoomX : currentZoom = zoomY;
661 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
662 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
664 if (currentZoom <= ZOOM_MIN)
665 emit actionUpdated(
"view_zoom_out",
false);
670 currentWidth = image_width;
671 currentHeight = image_height;
675 case ZOOM_KEEP_LEVEL:
677 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
678 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
689 m_ImageFrame->setScaledContents(
true);
690 doStretch(&rawImage);
698void FITSView::emitZoom()
701 double zoom = std::round(currentZoom * 100.0) / 100.0;
702 emit newStatus(
i18nc(
"%1 is the value, % is the percent sign",
"%1%", zoom), FITS_ZOOM);
705void FITSView::ZoomIn()
710 if (currentZoom >= ZOOM_DEFAULT && Options::limitedResourcesMode())
712 emit newStatus(
i18n(
"Cannot zoom in further due to active limited resources mode."), FITS_MESSAGE);
716 if (currentZoom < ZOOM_DEFAULT)
717 currentZoom += ZOOM_LOW_INCR;
719 currentZoom += ZOOM_HIGH_INCR;
721 emit actionUpdated(
"view_zoom_out",
true);
722 if (currentZoom >= zoomMax)
724 currentZoom = zoomMax;
725 emit actionUpdated(
"view_zoom_in",
false);
728 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
729 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
736 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
739void FITSView::ZoomOut()
744 if (currentZoom <= ZOOM_DEFAULT)
745 currentZoom -= ZOOM_LOW_INCR;
747 currentZoom -= ZOOM_HIGH_INCR;
749 if (currentZoom <= ZOOM_MIN)
751 currentZoom = ZOOM_MIN;
752 emit actionUpdated(
"view_zoom_out",
false);
755 emit actionUpdated(
"view_zoom_in",
true);
757 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
758 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
765 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
768void FITSView::ZoomToFit()
773 if (rawImage.
isNull() ==
false)
775 rescale(ZOOM_FIT_WINDOW);
778 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
783int FITSView::filterStars()
785 return ((m_ImageMask.
isNull() ==
false
786 && m_ImageMask->active()) ? m_ImageData->filterStars(m_ImageMask) : m_ImageData->getStarCenters().count());
789void FITSView::setImageMask(ImageMask *mask)
791 if (m_ImageMask.
isNull() ==
false)
795 mask->setImageGeometry(m_ImageMask->width(), m_ImageMask->height());
803bool FITSView::isLargeImage()
805 constexpr int largeImageNumPixels = 1000 * 1000;
806 return rawImage.
width() * rawImage.
height() >= largeImageNumPixels;
814double FITSView::getScale()
816 return (isLargeImage() ? 1.0 : currentZoom / ZOOM_DEFAULT) / m_PreviewSampling;
822double FITSView::scaleSize(
double size)
826 return (currentZoom > 100.0 ?
size : std::round(
size * 100.0 / currentZoom)) / m_PreviewSampling;
829void FITSView::updateFrame(
bool now)
843 if (toggleStretchAction)
844 toggleStretchAction->
setChecked(stretchImage);
851 updateFrameLargeImage();
853 updateFrameSmallImage();
855 if (m_QueueUpdate && m_StretchingInProgress ==
false)
857 m_QueueUpdate =
false;
862 m_UpdateFrameTimer.
start();
866bool FITSView::initDisplayPixmap(
QImage &image,
float scale)
868 ImageMosaicMask *
mask =
dynamic_cast<ImageMosaicMask *
>(m_ImageMask.
get());
877 int space =
mask->space();
879 displayPixmap =
QPixmap((3 *
width + 2 * space) * scale, (3 *
width + 2 * space) * scale);
887 const int posx =
pos % 3;
888 const int posy =
pos++ / 3;
889 const int tilewidth =
width * scale;
890 QRectF source(tile.x() * scale, tile.y()*scale, tilewidth, tilewidth);
892 painter.drawImage(target, image, source);
897void FITSView::updateFrameLargeImage()
899 if (!initDisplayPixmap(rawImage, 1.0 / m_PreviewSampling))
905 painter.setFont(
font);
907 drawStarRingFilter(&painter, 1.0 / m_PreviewSampling,
dynamic_cast<ImageRingMask *
>(m_ImageMask.
get()));
908 drawOverlay(&painter, 1.0 / m_PreviewSampling);
909 m_ImageFrame->setPixmap(displayPixmap);
910 m_ImageFrame->resize(((m_PreviewSampling * currentZoom) / 100.0) * displayPixmap.
size());
913void FITSView::updateFrameSmallImage()
916 if (!initDisplayPixmap(scaledImage, currentZoom / ZOOM_DEFAULT))
922 drawStarRingFilter(&painter, currentZoom / ZOOM_DEFAULT,
dynamic_cast<ImageRingMask *
>(m_ImageMask.
get()));
923 drawOverlay(&painter, currentZoom / ZOOM_DEFAULT);
924 m_ImageFrame->setPixmap(displayPixmap);
925 m_ImageFrame->resize(currentWidth, currentHeight);
928void FITSView::drawStarRingFilter(
QPainter *painter,
double scale, ImageRingMask *ringMask)
930 if (ringMask ==
nullptr || !ringMask->active())
933 const double w = m_ImageData->width() * scale;
934 const double h = m_ImageData->height() * scale;
935 double const diagonal = std::sqrt(w * w + h * h) / 2;
936 int const innerRadius = std::lround(diagonal * ringMask->innerRadius());
937 int const outerRadius = std::lround(diagonal * ringMask->outerRadius());
943 painter->
drawEllipse(center, outerRadius, outerRadius);
945 painter->
drawEllipse(center, innerRadius, innerRadius);
953int drawClippingOneChannel(T *inputBuffer,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
958 const T clipping = clipVal;
959 constexpr int timeoutMilliseconds = 3 * 1000;
963 for (
int y = 0; y < height; y++)
965 auto inputLine = inputBuffer + y * width;
967 for (
int x = 0; x < width; x++)
969 if (*inputLine++ > clipping)
979 painter->
drawLine(start, y, width - 1, y);
982 if (*inputLine++ > clipping)
992 painter->
drawLine(start, y, x - 1, y);
998 if (timer.elapsed() > timeoutMilliseconds)
1008template <
typename T>
1009int drawClippingThreeChannels(T *inputBuffer,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
1014 const T clipping = clipVal;
1015 constexpr int timeoutMilliseconds = 3 * 1000;
1019 const int size = width * height;
1020 for (
int y = 0; y < height; y++)
1023 const T * inputLineR = inputBuffer + y * width;
1024 const T * inputLineG = inputLineR + size;
1025 const T * inputLineB = inputLineG + size;
1028 for (
int x = 0; x < width; x++)
1030 T inputR = inputLineR[x];
1031 T inputG = inputLineG[x];
1032 T inputB = inputLineB[x];
1034 if (inputR > clipping || inputG > clipping || inputB > clipping)
1037 const int start = x;
1045 painter->
drawLine(start, y, width - 1, y);
1048 T inputR2 = inputLineR[x];
1049 T inputG2 = inputLineG[x];
1050 T inputB2 = inputLineB[x];
1051 if (inputR2 > clipping || inputG2 > clipping || inputB2 > clipping)
1061 painter->
drawLine(start, y, x - 1, y);
1067 if (timer.elapsed() > timeoutMilliseconds)
1077template <
typename T>
1078int drawClip(T *input_buffer,
int num_channels,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
1080 if (num_channels == 1)
1081 return drawClippingOneChannel(input_buffer, painter, width, height, clipVal, scale);
1082 else if (num_channels == 3)
1083 return drawClippingThreeChannels(input_buffer, painter, width, height, clipVal, scale);
1089void FITSView::drawClipping(
QPainter *painter)
1091 auto input = m_ImageData->getImageBuffer();
1092 const int height = m_ImageData->height();
1093 const int width = m_ImageData->width();
1094 const double FLOAT_CLIP = Options::clipping64KValue();
1095 const double SHORT_CLIP = Options::clipping64KValue();
1096 const double USHORT_CLIP = Options::clipping64KValue();
1097 const double BYTE_CLIP = Options::clipping256Value();
1098 switch (m_ImageData->dataType())
1101 m_NumClipped = drawClip(
reinterpret_cast<uint8_t const*
>(input), m_ImageData->channels(), painter,
width,
height, BYTE_CLIP,
1105 m_NumClipped = drawClip(
reinterpret_cast<short const*
>(input), m_ImageData->channels(), painter,
width,
height, SHORT_CLIP,
1109 m_NumClipped = drawClip(
reinterpret_cast<unsigned short const*
>(input), m_ImageData->channels(), painter,
width,
height,
1114 m_NumClipped = drawClip(
reinterpret_cast<long const*
>(input), m_ImageData->channels(), painter,
width,
height, USHORT_CLIP,
1118 m_NumClipped = drawClip(
reinterpret_cast<float const*
>(input), m_ImageData->channels(), painter,
width,
height, FLOAT_CLIP,
1122 m_NumClipped = drawClip(
reinterpret_cast<long long const*
>(input), m_ImageData->channels(), painter,
width,
height,
1127 m_NumClipped = drawClip(
reinterpret_cast<double const*
>(input), m_ImageData->channels(), painter,
width,
height, FLOAT_CLIP,
1134 if (m_NumClipped < 0)
1135 emit newStatus(
QString(
"Clip:failed"), FITS_CLIP);
1137 emit newStatus(
QString(
"Clip:%1").arg(m_NumClipped), FITS_CLIP);
1140void FITSView::ZoomDefault()
1144 emit actionUpdated(
"view_zoom_out",
true);
1145 emit actionUpdated(
"view_zoom_in",
true);
1147 currentZoom = ZOOM_DEFAULT;
1148 currentWidth = m_ImageData->width();
1149 currentHeight = m_ImageData->height();
1159void FITSView::drawOverlay(
QPainter * painter,
double scale)
1163#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1164 if (showHiPSOverlay)
1165 drawHiPSOverlay(painter, scale);
1168 if (trackingBoxEnabled && getCursorMode() != FITSView::scopeCursor)
1169 drawTrackingBox(painter, scale);
1171 if (!markerCrosshair.
isNull())
1172 drawMarker(painter, scale);
1175 drawCrosshair(painter, scale);
1178 drawObjectNames(painter, scale);
1180#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1182 drawEQGrid(painter, scale);
1186 drawPixelGrid(painter, scale);
1189 drawStarCentroid(painter, scale);
1192 drawClipping(painter);
1194 if (showMagnifyingGlass)
1195 drawMagnifyingGlass(painter, scale);
1199void FITSView::drawMagnifyingGlass(
QPainter *painter,
double scale)
1201 if (magnifyingGlassX >= 0 && magnifyingGlassY >= 0 &&
1202 magnifyingGlassX < m_ImageData->
width() &&
1203 magnifyingGlassY < m_ImageData->
height())
1206 constexpr double magAmount = 8;
1208 constexpr int magWindowSize = 130;
1210 const int winXOffset = magWindowSize * 10.0 / currentZoom;
1211 const int winYOffset = magWindowSize * 10.0 / currentZoom;
1213 const int inputDimension = magWindowSize * 100 / currentZoom;
1216 const int outputDimension = inputDimension * scale + .99;
1219 int imgLeft = magnifyingGlassX - inputDimension / (2 * magAmount);
1220 int imgTop = magnifyingGlassY - inputDimension / (2 * magAmount);
1223 int winLeft = magnifyingGlassX + winXOffset;
1224 int winTop = magnifyingGlassY + winYOffset;
1228 int w = rawImage.
width();
1229 int h = rawImage.
height();
1230 const int rightLimit = std::min(w,
static_cast<int>((
horizontalScrollBar()->value() +
width()) * 100 / currentZoom));
1231 const int bottomLimit = std::min(h,
static_cast<int>((
verticalScrollBar()->value() +
height()) * 100 / currentZoom));
1232 if (winLeft + winXOffset + inputDimension > rightLimit)
1233 winLeft -= (2 * winXOffset + inputDimension);
1234 if (winTop + winYOffset + inputDimension > bottomLimit)
1235 winTop -= (2 * winYOffset + inputDimension);
1238 if ((imgLeft < 0 ) ||
1239 (imgLeft + inputDimension / magAmount >= w) ||
1241 (imgTop + inputDimension / magAmount > h))
1244 painter->
drawRect(winLeft * scale, winTop * scale, outputDimension, outputDimension);
1249 painter->
drawImage(
QRect(winLeft * scale, winTop * scale, outputDimension, outputDimension),
1251 QRect(imgLeft, imgTop, inputDimension / magAmount, inputDimension / magAmount));
1254 painter->
drawRect(winLeft * scale, winTop * scale, outputDimension, outputDimension);
1259void FITSView::updateMagnifyingGlass(
int x,
int y)
1264 magnifyingGlassX =
x;
1265 magnifyingGlassY =
y;
1266 if (magnifyingGlassX == -1 && magnifyingGlassY == -1)
1268 if (showMagnifyingGlass)
1270 showMagnifyingGlass =
false;
1274 showMagnifyingGlass =
true;
1279void FITSView::updateMode(FITSMode fmode)
1284void FITSView::drawMarker(
QPainter * painter,
double scale)
1286 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")),
1289 const float pxperdegree = scale * (57.3 / 1.8);
1291 const float s1 = 0.5 * pxperdegree;
1292 const float s2 = pxperdegree;
1293 const float s3 = 2.0 * pxperdegree;
1295 const float x0 = scale * markerCrosshair.
x();
1296 const float y0 = scale * markerCrosshair.
y();
1297 const float x1 = x0 - 0.5 * s1;
1298 const float y1 = y0 - 0.5 * s1;
1299 const float x2 = x0 - 0.5 * s2;
1300 const float y2 = y0 - 0.5 * s2;
1301 const float x3 = x0 - 0.5 * s3;
1302 const float y3 = y0 - 0.5 * s3;
1314bool FITSView::drawHFR(
QPainter * painter,
const QString &hfr,
int x,
int y)
1321 QRect const hfrRect(hfrBottomLeft.x(), hfrBottomLeft.y() - hfrSize.
height(), hfrSize.
width(), hfrSize.
height());
1324 if (boundingRect.contains(hfrRect))
1327 painter->
drawText(hfrBottomLeft, hfr);
1335void FITSView::drawStarCentroid(
QPainter * painter,
double scale)
1338 double fontSize = painterFont.
pointSizeF() * 2;
1344 fontSize = scaleSize(painterFont.
pointSizeF());
1346 painter->
setFont(painterFont);
1350 ImageMosaicMask *
mask =
dynamic_cast<ImageMosaicMask *
>(m_ImageMask.
get());
1352 for (
auto const &starCenter : m_ImageData->getStarCenters())
1354 int const w = std::round(starCenter->width) * scale;
1361 const double xCoord =
center.x() - 0.5;
1362 const double yCoord =
center.y() - 0.5;
1363 const int xc = std::round((xCoord - starCenter->width / 2.0f) * scale);
1364 const int yc = std::round((yCoord - starCenter->width / 2.0f) * scale);
1365 const int hw = w / 2;
1367 BahtinovEdge* bEdge =
dynamic_cast<BahtinovEdge*
>(starCenter);
1368 if (bEdge !=
nullptr)
1372 painter->
drawLine(bEdge->line[0].x1() * scale, bEdge->line[0].y1() * scale,
1373 bEdge->line[0].x2() * scale, bEdge->line[0].y2() * scale);
1375 painter->
drawLine(bEdge->line[1].x1() * scale, bEdge->line[1].y1() * scale,
1376 bEdge->line[1].x2() * scale, bEdge->line[1].y2() * scale);
1378 painter->
drawLine(bEdge->line[2].x1() * scale, bEdge->line[2].y1() * scale,
1379 bEdge->line[2].x2() * scale, bEdge->line[2].y2() * scale);
1386 double factor = 15.0;
1388 int const xo = std::round((
center.x() + offsetVector.
x() - starCenter->width / 2.0f) * scale);
1389 int const yo = std::round((
center.y() + offsetVector.
y() - starCenter->width / 2.0f) * scale);
1395 painter->
drawLine(xc + hw, yc + hw, xo + hw, yo + hw);
1401 const double radius = starCenter->HFR > 0 ? 2.0f * starCenter->HFR * scale : w;
1410 if (!drawHFR(painter, hfr, xc + w + 5, yc + w / 2))
1413 for (
int i = 0; i < 10; ++i)
1415 const double tempFontSize = painterFont.
pointSizeF() - 2;
1416 if (tempFontSize <= 0)
break;
1418 painter->
setFont(painterFont);
1419 if (drawHFR(painter, hfr, xc + w + 5, yc + w / 2))
1424 painter->
setFont(painterFont);
1430void FITSView::drawTrackingBox(
QPainter * painter,
double scale)
1434 if (trackingBox.
isNull())
1437 const int x1 = trackingBox.
x() * scale;
1438 const int y1 = trackingBox.
y() * scale;
1439 const int w = trackingBox.
width() * scale;
1440 const int h = trackingBox.
height() * scale;
1449void FITSView::drawCrosshair(
QPainter * painter,
double scale)
1451 if (!m_ImageData)
return;
1452 const int image_width = m_ImageData->width();
1453 const int image_height = m_ImageData->height();
1454 const QPointF c =
QPointF((qreal)image_width / 2 * scale, (qreal)image_height / 2 * scale);
1455 const float midX = (float)image_width / 2 * scale;
1456 const float midY = (float)image_height / 2 * scale;
1457 const float maxX = (float)image_width * scale;
1458 const float maxY = (float)image_height * scale;
1459 const float r = 50 * scale;
1461 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")), scaleSize(1)));
1464 painter->
drawLine(0, midY, midX - r, midY);
1467 painter->
drawLine(midX + r, midY, maxX, midY);
1470 painter->
drawLine(midX, 0, midX, midY - r);
1473 painter->
drawLine(midX, midY + r, midX, maxY);
1488void FITSView::drawPixelGrid(
QPainter * painter,
double scale)
1490 const float width = m_ImageData->width() * scale;
1491 const float height = m_ImageData->height() * scale;
1492 const float cX =
width / 2;
1493 const float cY =
height / 2;
1494 const float deltaX =
width / 10;
1495 const float deltaY =
height / 10;
1502#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1503 painter->
drawText(
width - (fm.width(str) + 10), cY - 5, str);
1505 painter->
drawText(
width - (fm.horizontalAdvance(str) + 10), cY - 5, str);
1514 for (
int x = deltaX;
x < cX - deltaX;
x += deltaX)
1522 for (
int y = deltaY;
y < cY - deltaY;
y += deltaY)
1525#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1526 painter->
drawText(
width - (fm.width(str) + 10), cY +
y - 5, str);
1528 painter->
drawText(
width - (fm.horizontalAdvance(str) + 10), cY +
y - 5, str);
1531#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1532 painter->
drawText(
width - (fm.width(str) + 10), cY -
y - 5, str);
1534 painter->
drawText(
width - (fm.horizontalAdvance(str) + 10), cY -
y - 5, str);
1540bool FITSView::imageHasWCS()
1542 if (m_ImageData !=
nullptr)
1543 return m_ImageData->hasWCS();
1547void FITSView::drawObjectNames(
QPainter * painter,
double scale)
1549 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"FITSObjectLabelColor"))));
1550 for (
const auto &listObject : m_ImageData->getSkyObjects())
1552 painter->
drawRect(listObject->x() * scale - 5, listObject->y() * scale - 5, 10, 10);
1553 painter->
drawText(listObject->x() * scale + 10, listObject->y() * scale + 10, listObject->skyObject()->name());
1557#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1558void FITSView::drawHiPSOverlay(
QPainter * painter,
double scale)
1560 if (m_HiPSOverlayPixmap.
isNull())
1562 auto width = m_ImageData->width();
1563 auto height = m_ImageData->height();
1569 m_ImageData->pixelToWCS(
QPointF(0, 0), startPoint);
1571 m_ImageData->pixelToWCS(
QPointF( (
width - Options::hIPSOffsetX()) / 2.0, (
height - Options::hIPSOffsetY()) / 2.0),
1580 m_ImageData->getRecordValue(
"CROTA1", PA);
1582 auto rotation = 180 - PA.toDouble();
1586 if (HIPSFinder::Instance()->renderFOV(¢erPoint, fov_radius, rotation, &image) ==
false)
1593 painter->
drawPixmap(0, 0, m_HiPSOverlayPixmap);
1605#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1606void FITSView::drawEQGrid(
QPainter * painter,
double scale)
1608 const int image_width = m_ImageData->width();
1609 const int image_height = m_ImageData->height();
1611 if (m_ImageData->hasWCS())
1613 double maxRA = -1000;
1614 double minRA = 1000;
1615 double maxDec = -1000;
1616 double minDec = 1000;
1617 m_ImageData->findWCSBounds(minRA, maxRA, minDec, maxDec);
1619 auto minDecMinutes = (int)(minDec * 12);
1620 auto maxDecMinutes = (int)(maxDec * 12);
1623 (int)(minRA / 15.0 *
1625 auto maxRAMinutes = (int)(maxRA / 15.0 * 120.0);
1627 double raConvert = 15 / 120.0;
1628 double decConvert = 1.0 / 12.0;
1630 if (maxDec > 50 || minDec < -50)
1633 (int)(minRA / 15.0 * 60.0);
1634 maxRAMinutes = (int)(maxRA / 15.0 * 60.0);
1635 raConvert = 15 / 60.0;
1638 if (maxDec > 80 || minDec < -80)
1641 (int)(minRA / 15.0 * 30);
1642 maxRAMinutes = (int)(maxRA / 15.0 * 30);
1643 raConvert = 15 / 30.0;
1645 if (maxDec > 85 || minDec < -85)
1648 (int)(minRA / 15.0 * 6);
1649 maxRAMinutes = (int)(maxRA / 15.0 * 6);
1650 raConvert = 15 / 6.0;
1652 if (maxDec >= 89.25 || minDec <= -89.25)
1657 maxRAMinutes = (int)(maxRA / 15);
1663 QPointF pixelPoint, imagePoint, pPoint;
1667 for (
int targetRA = minRAMinutes; targetRA <= maxRAMinutes; targetRA++)
1670 double target = targetRA * raConvert;
1672 if (eqGridPoints.count() != 0)
1673 eqGridPoints.clear();
1675 double increment = std::abs((maxDec - minDec) /
1678 for (
double targetDec = minDec; targetDec <= maxDec; targetDec += increment)
1680 SkyPoint pointToGet(target / 15.0, targetDec);
1681 bool inImage = m_ImageData->wcsToPixel(pointToGet, pixelPoint, imagePoint);
1684 QPointF pt(pixelPoint.
x() * scale, pixelPoint.
y() * scale);
1685 eqGridPoints.append(pt);
1689 if (eqGridPoints.count() > 1)
1691 for (
int i = 1; i < eqGridPoints.count(); i++)
1692 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1695 if (maxDec <= 50 && maxDec >= -50)
1697 QPointF pt = getPointForGridLabel(painter, str, scale);
1705 for (
int targetDec = minDecMinutes; targetDec <= maxDecMinutes; targetDec++)
1707 if (eqGridPoints.count() != 0)
1708 eqGridPoints.clear();
1710 double increment = std::abs((maxRA - minRA) /
1712 double target = targetDec * decConvert;
1714 for (
double targetRA = minRA; targetRA <= maxRA; targetRA += increment)
1716 SkyPoint pointToGet(targetRA / 15, targetDec * decConvert);
1717 bool inImage = m_ImageData->wcsToPixel(pointToGet, pixelPoint, imagePoint);
1720 QPointF pt(pixelPoint.
x() * scale, pixelPoint.
y() * scale);
1721 eqGridPoints.append(pt);
1724 if (eqGridPoints.count() > 1)
1726 for (
int i = 1; i < eqGridPoints.count(); i++)
1727 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1729 QPointF pt = getPointForGridLabel(painter, str, scale);
1738 bool NCPtest = m_ImageData->wcsToPixel(NCP, pPoint, imagePoint);
1742 (pPoint.
x() > 0 && pPoint.
x() < image_width) && (pPoint.
y() > 0 && pPoint.
y() < image_height);
1745 painter->
fillRect(pPoint.
x() * scale - 2, pPoint.
y() * scale - 2, 4, 4,
1747 painter->
drawText(pPoint.
x() * scale + 15, pPoint.
y() * scale + 15,
1748 i18nc(
"North Celestial Pole",
"NCP"));
1755 bool SCPtest = m_ImageData->wcsToPixel(SCP, pPoint, imagePoint);
1759 (pPoint.
x() > 0 && pPoint.
x() < image_width) && (pPoint.
y() > 0 && pPoint.
y() < image_height);
1762 painter->
fillRect(pPoint.
x() * scale - 2, pPoint.
y() * scale - 2, 4, 4,
1764 painter->
drawText(pPoint.
x() * scale + 15, pPoint.
y() * scale + 15,
1765 i18nc(
"South Celestial Pole",
"SCP"));
1772bool FITSView::pointIsInImage(
QPointF pt,
double scale)
1774 int image_width = m_ImageData->width();
1775 int image_height = m_ImageData->height();
1776 return pt.
x() < image_width * scale && pt.
y() < image_height * scale && pt.
x() > 0 && pt.
y() > 0;
1782#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1783 int strWidth = fm.width(str);
1785 int strWidth = fm.horizontalAdvance(str);
1787 int strHeight = fm.height();
1788 int image_width = m_ImageData->width();
1789 int image_height = m_ImageData->height();
1792 QPointF maxXPt(image_width * scale / 2, image_height * scale / 2);
1793 for (
auto &p : eqGridPoints)
1795 if (p.
x() > maxXPt.x() && pointIsInImage(p, scale))
1798 QPointF maxYPt(image_width * scale / 2, image_height * scale / 2);
1800 for (
auto &p : eqGridPoints)
1802 if (p.
y() > maxYPt.y() && pointIsInImage(p, scale))
1805 QPointF minXPt(image_width * scale / 2, image_height * scale / 2);
1807 for (
auto &p : eqGridPoints)
1809 if (p.
x() < minXPt.x() && pointIsInImage(p, scale))
1812 QPointF minYPt(image_width * scale / 2, image_height * scale / 2);
1814 for (
auto &p : eqGridPoints)
1816 if (p.
y() < minYPt.y() && pointIsInImage(p, scale))
1825 if (image_width * scale - maxXPt.x() < strWidth)
1828 image_width * scale - (strWidth + 10),
1832 if (image_height * scale - maxYPt.y() < strHeight)
1834 maxYPt.x() - (strWidth + 10),
1835 image_height * scale -
1837 if (minYPt.y() < strHeight)
1839 minYPt.x() * scale + 10,
1841 if (minXPt.x() < strWidth)
1844 minXPt.y() * scale +
1847 if (maxXPt.x() == image_width * scale / 2 && maxXPt.y() == image_height * scale / 2)
1850 return QPoint(maxXPt.x() - (strWidth + 10), maxXPt.y() - (strHeight + 10));
1853void FITSView::setFirstLoad(
bool value)
1858QPixmap &FITSView::getTrackingBoxPixmap(uint8_t margin)
1860 if (trackingBox.
isNull())
1861 return trackingBoxPixmap;
1864 const float scale = getScale();
1866 int x1 = (trackingBox.
x() - margin) * scale;
1867 int y1 = (trackingBox.
y() - margin) * scale;
1868 int w = (trackingBox.
width() + margin * 2) * scale;
1869 int h = (trackingBox.
height() + margin * 2) * scale;
1871 trackingBoxPixmap = m_ImageFrame->grab(
QRect(x1, y1, w, h));
1872 return trackingBoxPixmap;
1875void FITSView::setTrackingBox(
const QRect &rect)
1877 if (
rect != trackingBox)
1886void FITSView::resizeTrackingBox(
int newSize)
1888 int x = trackingBox.
x() + trackingBox.
width() / 2;
1889 int y = trackingBox.
y() + trackingBox.
height() / 2;
1890 int delta = newSize / 2;
1891 setTrackingBox(
QRect(
x - delta,
y - delta, newSize, newSize));
1894void FITSView::processRectangleFixed(
int s)
1896 int w = m_ImageData->width();
1897 int h = m_ImageData->height();
1900 c.
setX(qMax((
int)round(s / 2.0), c.
x()));
1901 c.
setX(qMin(w - (
int)round(s / 2.0), c.
x()));
1902 c.
setY(qMax((
int)round(s / 2.0), c.
y()));
1903 c.
setY(qMin(h - (
int)round(s / 2.0), c.
y()));
1905 QPoint topLeft, botRight;
1906 topLeft =
QPoint(c.
x() - round(s / 2.0), c.
y() - round(s / 2.0));
1907 botRight =
QPoint(c.
x() + round(s / 2.0), c.
y() + round(s / 2.0));
1909 emit setRubberBand(
QRect(topLeft, botRight));
1910 processRectangle(topLeft, botRight,
true);
1913void FITSView::processRectangle(
QPoint p1,
QPoint p2,
bool calculate)
1915 if(!isSelectionRectShown())
1929 topLeft.
setX(qMax(1, topLeft.
x()));
1930 topLeft.
setY(qMax(1, topLeft.
y()));
1931 botRight.
setX(qMin((
int)m_ImageData->width(), botRight.
x()));
1932 botRight.
setY(qMin((
int)m_ImageData->height(), botRight.
y()));
1941 m_ImageData->makeRoiBuffer(selectionRectangleRaw);
1942 emit rectangleUpdated(selectionRectangleRaw);
1951bool FITSView::isImageStretched()
1953 return stretchImage;
1956bool FITSView::isClippingShown()
1958 return showClipping;
1961bool FITSView::isCrosshairShown()
1963 return showCrosshair;
1966bool FITSView::isEQGridShown()
1971bool FITSView::isSelectionRectShown()
1973 return showSelectionRect;
1975bool FITSView::areObjectsShown()
1980bool FITSView::isPixelGridShown()
1982 return showPixelGrid;
1985bool FITSView::isHiPSOverlayShown()
1987 return showHiPSOverlay;
1990void FITSView::toggleCrosshair()
1992 showCrosshair = !showCrosshair;
1996void FITSView::toggleClipping()
1998 showClipping = !showClipping;
2002void FITSView::toggleEQGrid()
2004 showEQGrid = !showEQGrid;
2006 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2017void FITSView::toggleHiPSOverlay()
2019 showHiPSOverlay = !showHiPSOverlay;
2021 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2030 m_QueueUpdate =
true;
2035void FITSView::toggleSelectionMode()
2037 showSelectionRect = !showSelectionRect;
2038 if (!showSelectionRect)
2039 emit rectangleUpdated(
QRect());
2040 else if (m_ImageData)
2042 m_ImageData->makeRoiBuffer(selectionRectangleRaw);
2043 emit rectangleUpdated(selectionRectangleRaw);
2046 emit showRubberBand(showSelectionRect);
2051void FITSView::toggleObjects()
2053 showObjects = !showObjects;
2055 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.
isRunning())
2064#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
2065 m_ImageData->searchObjects();
2071void FITSView::toggleStars()
2073 toggleStars(!markStars);
2078void FITSView::toggleStretch()
2080 stretchImage = !stretchImage;
2081 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
2085void FITSView::toggleStarProfile()
2087#ifdef HAVE_DATAVISUALIZATION
2088 showStarProfile = !showStarProfile;
2089 if(showStarProfile && trackingBoxEnabled)
2091 if(toggleProfileAction)
2092 toggleProfileAction->
setChecked(showStarProfile);
2098 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
2100 setCursorMode(selectCursor);
2101 connect(
this, SIGNAL(trackingStarSelected(
int,
int)),
this, SLOT(move3DTrackingBox(
int,
int)));
2102 trackingBox =
QRect(0, 0, 128, 128);
2103 setTrackingBoxEnabled(
true);
2104 if(starProfileWidget)
2105 connect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
2107 if(starProfileWidget)
2108 connect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
2114 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
2116 if(getCursorMode() == selectCursor)
2117 setCursorMode(dragCursor);
2118 disconnect(
this, SIGNAL(trackingStarSelected(
int,
int)),
this, SLOT(move3DTrackingBox(
int,
int)));
2119 setTrackingBoxEnabled(
false);
2120 if(starProfileWidget)
2121 disconnect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
2123 if(starProfileWidget)
2125 disconnect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
2126 starProfileWidget->close();
2127 starProfileWidget =
nullptr;
2129 emit starProfileWindowClosed();
2135void FITSView::move3DTrackingBox(
int x,
int y)
2137 int boxSize = trackingBox.
width();
2138 QRect starRect =
QRect(
x - boxSize / 2,
y - boxSize / 2, boxSize, boxSize);
2139 setTrackingBox(starRect);
2142void FITSView::viewStarProfile()
2144#ifdef HAVE_DATAVISUALIZATION
2145 if(!trackingBoxEnabled)
2147 setTrackingBoxEnabled(
true);
2148 setTrackingBox(
QRect(0, 0, 128, 128));
2150 if(!starProfileWidget)
2152 starProfileWidget =
new StarProfileViewer(
this);
2163 connect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
2164 if(mode == FITS_ALIGN || mode == FITS_NORMAL)
2166 starProfileWidget->enableTrackingBox(
true);
2167 m_ImageData->setStarAlgorithm(ALGORITHM_CENTROID);
2168 connect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
2171 QList<Edge *> starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
2172 if(starCenters.
size() == 0)
2177 m_ImageData->findStars(ALGORITHM_CENTROID, trackingBox).waitForFinished();
2178 starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
2181 starProfileWidget->loadData(m_ImageData, trackingBox, starCenters);
2182 starProfileWidget->show();
2183 starProfileWidget->raise();
2190void FITSView::togglePixelGrid()
2192 showPixelGrid = !showPixelGrid;
2198 if(trackingBoxEnabled)
2199 return m_ImageData->findStars(algorithm, trackingBox);
2201 return m_ImageData->findStars(algorithm, searchBox);
2204void FITSView::toggleStars(
bool enable)
2212void FITSView::searchStars()
2215 if (m_ImageData->areStarsSearched() || !m_ImageData || (m_ImageData->getRecordValue(
"FRAME", frameType)
2216 && frameType.
toString() !=
"Light"))
2220 emit newStatus(
i18n(
"Finding stars..."), FITS_MESSAGE);
2221 qApp->processEvents();
2223#ifdef HAVE_STELLARSOLVER
2224 QVariantMap extractionSettings;
2225 extractionSettings[
"optionsProfileIndex"] = Options::hFROptionsProfile();
2226 extractionSettings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::HFRProfiles);
2227 imageData()->setSourceExtractorSettings(extractionSettings);
2234 emit newStatus(
"", FITS_MESSAGE);
2239void FITSView::processPointSelection(
int x,
int y)
2241 emit trackingStarSelected(
x,
y);
2244void FITSView::processMarkerSelection(
int x,
int y)
2246 markerCrosshair.
setX(
x);
2247 markerCrosshair.
setY(
y);
2252void FITSView::setTrackingBoxEnabled(
bool enable)
2254 if (enable != trackingBoxEnabled)
2256 trackingBoxEnabled = enable;
2271#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2274 QPoint mouseCenter = getImagePoint(
event->position().toPoint());
2276 if (
event->angleDelta().y() > 0)
2281 cleanUpZoom(mouseCenter);
2283 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
2292void FITSView::cleanUpZoom(
QPoint viewCenter)
2296 double scale = (currentZoom / ZOOM_DEFAULT);
2297 if (!markerCrosshair.
isNull())
2299 x0 = markerCrosshair.
x() * scale;
2300 y0 = markerCrosshair.
y() * scale;
2302 else if (trackingBoxEnabled)
2304 x0 = trackingBox.
center().
x() * scale;
2305 y0 = trackingBox.
center().
y() * scale;
2307 else if (!viewCenter.
isNull())
2309 x0 = viewCenter.
x() * scale;
2310 y0 = viewCenter.
y() * scale;
2312 if ((x0 != 0) || (y0 != 0))
2314 updateMouseCursor();
2329 double scale = (currentZoom / ZOOM_DEFAULT);
2331 QPoint imagePoint =
QPoint(widgetPoint.
x() / scale, widgetPoint.
y() / scale);
2335void FITSView::initDisplayImage()
2339 int w = (m_ImageData->width() + m_PreviewSampling - 1) / m_PreviewSampling;
2340 int h = (m_ImageData->height() + m_PreviewSampling - 1) / m_PreviewSampling;
2342 if (m_ImageData->channels() == 1)
2347 for (
int i = 0; i < 256; i++)
2348 rawImage.
setColor(i, qRgb(i, i, i));
2363bool FITSView::event(
QEvent * event)
2394 if (zoomTime > 10000)
2396 if (zooming && (zoomTime % 10 == 0))
2403 cleanUpZoom(zoomLocation);
2414void FITSView::syncWCSState()
2416 bool hasWCS = m_ImageData->hasWCS();
2417 bool wcsLoaded = m_ImageData->getWCSState() == FITSData::Success;
2419#if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
2421 m_ImageData->searchObjects();
2424 if (hasWCS && wcsLoaded)
2425 this->updateFrame();
2427 emit wcsToggled(hasWCS);
2429 if (toggleEQGridAction !=
nullptr)
2431 if (toggleObjectsAction !=
nullptr)
2433 if (centerTelescopeAction !=
nullptr)
2435 if (toggleHiPSOverlayAction !=
nullptr)
2439void FITSView::createFloatingToolBar()
2441 if (floatingToolBar !=
nullptr)
2444 floatingToolBar =
new QToolBar(
this);
2447 eff->setOpacity(0.2);
2450 "QToolBar{background: rgba(150, 150, 150, 210); border:none; color: yellow}"
2451 "QToolButton{background: transparent; border:none; color: yellow}"
2452 "QToolButton:hover{background: rgba(200, 200, 200, 255);border:solid; color: yellow}"
2453 "QToolButton:checked{background: rgba(110, 110, 110, 255);border:solid; color: yellow}");
2461 i18n(
"Zoom In"),
this, SLOT(ZoomIn()));
2464 i18n(
"Zoom Out"),
this, SLOT(ZoomOut()));
2467 i18n(
"Default Zoom"),
this, SLOT(ZoomDefault()));
2470 i18n(
"Zoom to Fit"),
this, SLOT(ZoomToFit()));
2473 i18n(
"Toggle Stretch"),
2474 this, SLOT(toggleStretch()));
2481 i18n(
"Show Cross Hairs"),
this, SLOT(toggleCrosshair()));
2485 i18n(
"Show Pixel Gridlines"),
this, SLOT(togglePixelGrid()));
2490 i18n(
"Detect Stars in Image"),
this, SLOT(toggleStars()));
2493#ifdef HAVE_DATAVISUALIZATION
2494 toggleProfileAction =
2496 i18n(
"View Star Profile..."),
this, SLOT(toggleStarProfile()));
2500 if (mode == FITS_NORMAL || mode == FITS_ALIGN)
2504 toggleEQGridAction =
2506 i18n(
"Show Equatorial Gridlines"),
this, &FITSView::toggleEQGrid);
2510 toggleObjectsAction =
2512 i18n(
"Show Objects in Image"),
this, &FITSView::toggleObjects);
2516 centerTelescopeAction =
2518 i18n(
"Center Telescope"),
this, &FITSView::centerTelescope);
2522 toggleHiPSOverlayAction =
2524 i18n(
"Show HiPS Overlay"),
this, &FITSView::toggleHiPSOverlay);
2535void FITSView::centerTelescope()
2539 if (getCursorMode() == FITSView::scopeCursor)
2541 setCursorMode(lastMouseMode);
2545 lastMouseMode = getCursorMode();
2546 setCursorMode(FITSView::scopeCursor);
2550 updateScopeButton();
2553void FITSView::updateScopeButton()
2555 if (centerTelescopeAction !=
nullptr)
2557 if (getCursorMode() == FITSView::scopeCursor)
2572bool FITSView::isTelescopeActive()
2575 if (INDIListener::Instance()->
size() == 0)
2582 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE))
2584 return oneDevice->isConnected();
2592void FITSView::setStarsEnabled(
bool enable)
2595 if (floatingToolBar !=
nullptr)
2599 if (action->
text() ==
i18n(
"Detect Stars in Image"))
2608void FITSView::setStarsHFREnabled(
bool enable)
2610 showStarsHFR = enable;
2613void FITSView::setStretchValues(
double shadows,
double midtones,
double highlights)
2615 StretchParams params = getStretchParams();
2616 params.grey_red.shadows = shadows;
2617 params.grey_red.midtones = midtones;
2618 params.grey_red.highlights = highlights;
2620 setStretchParams(params);
2623void FITSView::setAutoStretch()
2625 if (!getAutoStretch())
2626 setAutoStretchParams();
QColor colorNamed(const QString &name) const
Retrieve a color by name.
INDIListener is responsible for creating ISD::GDInterface generic devices as new devices arrive from ...
ColorScheme * colorScheme()
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)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
const char * constData() const const
QString suffix() const const
qreal pointSizeF() const const
void setPixelSize(int pixelSize)
void setPointSize(int pointSize)
void setPointSizeF(qreal pointSize)
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)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
bool inherits(const char *className) const const
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)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QByteArray toLatin1() const const
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(StringFormat mode) const const
QString toString() const const