8 #include "config-kstars.h"
12 #include "fitslabel.h"
13 #include "kspopupmenu.h"
14 #include "kstarsdata.h"
18 #include "fits_debug.h"
21 #ifdef HAVE_STELLARSOLVER
22 #include "ekos/auxiliary/stellarsolverprofileeditor.h"
26 #include "basedevice.h"
27 #include "indi/indilistener.h"
30 #include <KActionCollection>
32 #include <QtConcurrent>
35 #include <QGraphicsOpacityEffect>
36 #include <QApplication>
37 #include <QImageReader>
38 #include <QGestureEvent>
39 #include <QMutexLocker>
45 #define BASE_OFFSET 50
46 #define ZOOM_DEFAULT 100.0f
50 #define ZOOM_LOW_INCR 10
51 #define ZOOM_HIGH_INCR 50
60 void ComputeGBStretchParams(
const StretchParams &newParams, StretchParams* params)
62 float shadow_diff = newParams.grey_red.shadows - params->grey_red.shadows;
63 float highlight_diff = newParams.grey_red.highlights - params->grey_red.highlights;
64 float midtones_diff = newParams.grey_red.midtones - params->grey_red.midtones;
66 params->green.shadows = params->green.shadows + shadow_diff;
67 params->green.shadows = KSUtils::clamp(params->green.shadows, 0.0f, 1.0f);
68 params->green.highlights = params->green.highlights + highlight_diff;
69 params->green.highlights = KSUtils::clamp(params->green.highlights, 0.0f, 1.0f);
70 params->green.midtones = params->green.midtones + midtones_diff;
71 params->green.midtones = std::max(params->green.midtones, 0.0f);
73 params->blue.shadows = params->blue.shadows + shadow_diff;
74 params->blue.shadows = KSUtils::clamp(params->blue.shadows, 0.0f, 1.0f);
75 params->blue.highlights = params->blue.highlights + highlight_diff;
76 params->blue.highlights = KSUtils::clamp(params->blue.highlights, 0.0f, 1.0f);
77 params->blue.midtones = params->blue.midtones + midtones_diff;
78 params->blue.midtones = std::max(params->blue.midtones, 0.0f);
87 void FITSView::doStretch(
QImage *outputImage)
89 if (outputImage->
isNull() || m_ImageData.isNull())
91 Stretch stretch(
static_cast<int>(m_ImageData->width()),
92 static_cast<int>(m_ImageData->height()),
93 m_ImageData->channels(), m_ImageData->dataType());
95 StretchParams tempParams;
97 tempParams = StretchParams();
101 stretchParams = stretch.computeParams(m_ImageData->getImageBuffer());
102 tempParams = stretchParams;
106 tempParams = stretchParams;
108 stretch.setParams(tempParams);
109 stretch.run(m_ImageData->getImageBuffer(), outputImage, m_PreviewSampling);
113 void FITSView::setStretchParams(
const StretchParams ¶ms)
115 if (m_ImageData->channels() == 3)
116 ComputeGBStretchParams(params, &stretchParams);
118 stretchParams.grey_red = params.grey_red;
119 stretchParams.grey_red.shadows = std::max(stretchParams.grey_red.shadows, 0.0f);
120 stretchParams.grey_red.highlights = std::max(stretchParams.grey_red.highlights, 0.0f);
121 stretchParams.grey_red.midtones = std::max(stretchParams.grey_red.midtones, 0.0f);
126 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
131 void FITSView::setStretch(
bool onOff)
133 if (stretchImage != onOff)
135 stretchImage = onOff;
136 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
142 void FITSView::setAutoStretchParams()
146 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
150 FITSView::FITSView(
QWidget * parent, FITSMode fitsMode, FITSScale filterType) :
QScrollArea(parent), m_ZoomFactor(1.2)
154 stretchImage = Options::autoStretch();
165 #if defined (Q_OS_LINUX) || defined (Q_OS_OSX)
166 const long numPages = sysconf(_SC_PAGESIZE);
167 const long pageSize = sysconf(_SC_PHYS_PAGES);
171 if (numPages > 0 && pageSize > 0)
174 const int memoryMb = numPages * (
static_cast<double>(
pageSize) / 1e6);
177 else if (memoryMb < 4000)
179 else if (memoryMb < 8000)
181 else if (memoryMb < 16000)
195 markerCrosshair.setX(0);
196 markerCrosshair.setY(0);
200 m_ImageFrame =
new FITSLabel(
this);
201 m_ImageFrame->setMouseTracking(
true);
202 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
203 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
204 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
205 connect(m_ImageFrame, &FITSLabel::rectangleSelected,
this, &FITSView::processRectangle);
206 connect(
this, &FITSView::setRubberBand, m_ImageFrame, &FITSLabel::setRubberBand);
207 connect(
this, &FITSView::showRubberBand, m_ImageFrame, &FITSLabel::showRubberBand);
208 connect(
this, &FITSView::zoomRubberBand, m_ImageFrame, &FITSLabel::zoomRubberBand);
214 m_UpdateFrameTimer.setInterval(50);
215 m_UpdateFrameTimer.setSingleShot(
true);
218 this->updateFrame(
true);
226 noImageLabel =
new QLabel();
227 noImage.load(
":/images/noimage.png");
228 noImageLabel->setPixmap(noImage);
230 setWidget(noImageLabel);
237 FITSView::~FITSView()
240 m_UpdateFrameTimer.stop();
242 fitsWatcher.waitForFinished();
243 wcsWatcher.waitForFinished();
250 void FITSView::updateMouseCursor()
252 if (cursorMode == dragCursor)
254 if (horizontalScrollBar()->maximum() > 0 || verticalScrollBar()->maximum() > 0)
256 if (!m_ImageFrame->getMouseButtonDown())
264 else if (cursorMode == selectCursor)
268 else if (cursorMode == scopeCursor)
270 viewport()->setCursor(
QCursor(redScopePixmap, 10, 10));
272 else if (cursorMode == crosshairCursor)
274 viewport()->setCursor(
QCursor(magentaScopePixmap, 10, 10));
286 void FITSView::setCursorMode(CursorMode mode)
291 if (mode == scopeCursor && imageHasWCS())
293 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.isRunning())
296 wcsWatcher.setFuture(future);
303 if (m_ImageData ==
nullptr && noImageLabel !=
nullptr)
305 noImageLabel->setPixmap(
307 noImageLabel->setFixedSize(width() - 5, height() - 5);
314 void FITSView::loadFile(
const QString &inFilename)
316 if (floatingToolBar !=
nullptr)
318 floatingToolBar->setVisible(
true);
321 bool setBayerParams =
false;
324 if ((m_ImageData !=
nullptr) && m_ImageData->hasDebayer())
326 setBayerParams =
true;
327 m_ImageData->getBayerParams(¶m);
331 fitsWatcher.waitForFinished();
333 wcsWatcher.waitForFinished();
339 filterStack.push(FITS_NONE);
340 if (filter != FITS_NONE)
341 filterStack.push(filter);
346 m_ImageData->setBayerParams(¶m);
348 fitsWatcher.setFuture(m_ImageData->loadFromFile(inFilename));
351 void FITSView::clearData()
355 noImageLabel =
new QLabel();
356 noImage.load(
":/images/noimage.png");
357 noImageLabel->setPixmap(noImage);
361 setWidget(noImageLabel);
368 if (floatingToolBar !=
nullptr)
370 floatingToolBar->setVisible(
true);
374 wcsWatcher.waitForFinished();
377 filterStack.push(FITS_NONE);
378 if (filter != FITS_NONE)
379 filterStack.push(filter);
385 return processData();
388 bool FITSView::processData()
394 connect(m_ImageData.data(), &FITSData::dataChanged,
this, [
this]()
396 rescale(ZOOM_KEEP_LEVEL);
400 connect(
this, &FITSView::rectangleUpdated,
this, [
this](
const QRect roi)
404 m_ImageData->makeRoiBuffer(roi);
407 currentWidth = m_ImageData->width();
408 currentHeight = m_ImageData->height();
410 int image_width = currentWidth;
411 int image_height = currentHeight;
415 m_ImageFrame =
new FITSLabel(
this);
416 m_ImageFrame->setMouseTracking(
true);
417 connect(m_ImageFrame, &FITSLabel::newStatus,
this, &FITSView::newStatus);
418 connect(m_ImageFrame, &FITSLabel::pointSelected,
this, &FITSView::processPointSelection);
419 connect(m_ImageFrame, &FITSLabel::markerSelected,
this, &FITSView::processMarkerSelection);
421 m_ImageFrame->setSize(image_width, image_height);
427 m_ImageData->applyFilter(filter);
429 double availableRAM = 0;
430 if (Options::adaptiveSampling() && (availableRAM = KSUtils::getAvailableRAM()) > 0)
433 double max_size = image_width * image_height * 4;
435 double ratio = max_size / availableRAM;
439 m_AdaptiveSampling = 1;
440 else if (ratio < 0.2)
441 m_AdaptiveSampling = 2;
443 m_AdaptiveSampling = 4;
445 m_PreviewSampling = m_AdaptiveSampling;
453 if (rescale(ZOOM_FIT_WINDOW) ==
false)
455 m_LastError =
i18n(
"Rescaling image failed.");
463 if (rescale(ZOOM_KEEP_LEVEL) ==
false)
465 m_LastError =
i18n(
"Rescaling image failed.");
473 if ((mode == FITS_NORMAL || mode == FITS_ALIGN) &&
474 m_ImageData->hasWCS() && m_ImageData->getWCSState() == FITSData::Idle &&
475 Options::autoWCS() &&
476 !wcsWatcher.isRunning())
479 wcsWatcher.setFuture(future);
485 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
489 if(floatingToolBar !=
nullptr)
490 toggleProfileAction->setChecked(
true);
500 void FITSView::loadInFrame()
502 m_LastError = m_ImageData->getLastError();
505 if (fitsWatcher.result() ==
false)
507 emit failed(m_LastError);
512 emit debayerToggled(m_ImageData->hasDebayer());
517 emit failed(m_LastError);
520 bool FITSView::saveImage(
const QString &newFilename)
529 return m_ImageData->saveImage(newFilename);
532 FITSView::CursorMode FITSView::getCursorMode()
537 void FITSView::enterEvent(
QEvent * event)
541 if (floatingToolBar && m_ImageData)
544 floatingToolBar->setGraphicsEffect(eff);
547 a->setStartValue(0.2);
554 void FITSView::leaveEvent(
QEvent * event)
558 if (floatingToolBar && m_ImageData)
561 floatingToolBar->setGraphicsEffect(eff);
571 bool FITSView::rescale(FITSZoom type)
576 int image_width = m_ImageData->width();
577 int image_height = m_ImageData->height();
578 currentWidth = image_width;
579 currentHeight = image_height;
582 emit newStatus(
QString(
"%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION);
586 case ZOOM_FIT_WINDOW:
587 if ((image_width > width() || image_height > height()))
589 double w = baseSize().width() - BASE_OFFSET;
590 double h = baseSize().height() - BASE_OFFSET;
594 w = viewport()->rect().width() - BASE_OFFSET;
595 h = viewport()->rect().height() - BASE_OFFSET;
599 double zoomX = floor((w /
static_cast<double>(currentWidth)) * 100.);
600 double zoomY = floor((h /
static_cast<double>(currentHeight)) * 100.);
601 (zoomX < zoomY) ? currentZoom = zoomX : currentZoom = zoomY;
603 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
604 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
606 if (currentZoom <= ZOOM_MIN)
607 emit actionUpdated(
"view_zoom_out",
false);
612 currentWidth = image_width;
613 currentHeight = image_height;
617 case ZOOM_KEEP_LEVEL:
619 currentWidth = image_width * (currentZoom / ZOOM_DEFAULT);
620 currentHeight = image_height * (currentZoom / ZOOM_DEFAULT);
631 m_ImageFrame->setScaledContents(
true);
632 doStretch(&rawImage);
633 setWidget(m_ImageFrame);
636 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
640 void FITSView::ZoomIn()
645 if (currentZoom >= ZOOM_DEFAULT && Options::limitedResourcesMode())
647 emit newStatus(
i18n(
"Cannot zoom in further due to active limited resources mode."), FITS_MESSAGE);
651 if (currentZoom < ZOOM_DEFAULT)
652 currentZoom += ZOOM_LOW_INCR;
654 currentZoom += ZOOM_HIGH_INCR;
656 emit actionUpdated(
"view_zoom_out",
true);
657 if (currentZoom >= zoomMax)
659 currentZoom = zoomMax;
660 emit actionUpdated(
"view_zoom_in",
false);
663 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
664 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
670 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
671 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
674 void FITSView::ZoomOut()
679 if (currentZoom <= ZOOM_DEFAULT)
680 currentZoom -= ZOOM_LOW_INCR;
682 currentZoom -= ZOOM_HIGH_INCR;
684 if (currentZoom <= ZOOM_MIN)
686 currentZoom = ZOOM_MIN;
687 emit actionUpdated(
"view_zoom_out",
false);
690 emit actionUpdated(
"view_zoom_in",
true);
692 currentWidth = m_ImageData->width() * (currentZoom / ZOOM_DEFAULT);
693 currentHeight = m_ImageData->height() * (currentZoom / ZOOM_DEFAULT);
699 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
700 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
703 void FITSView::ZoomToFit()
708 if (rawImage.isNull() ==
false)
710 rescale(ZOOM_FIT_WINDOW);
713 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
716 void FITSView::setStarFilterRange(
float const innerRadius,
float const outerRadius)
718 starFilter.innerRadius = innerRadius;
719 starFilter.outerRadius = outerRadius;
722 int FITSView::filterStars()
724 return starFilter.used() ? m_ImageData->filterStars(starFilter.innerRadius,
725 starFilter.outerRadius) : m_ImageData->getStarCenters().count();
730 bool FITSView::isLargeImage()
732 constexpr
int largeImageNumPixels = 1000 * 1000;
733 return rawImage.width() * rawImage.height() >= largeImageNumPixels;
741 double FITSView::getScale()
743 return (isLargeImage() ? 1.0 : currentZoom / ZOOM_DEFAULT) / m_PreviewSampling;
749 double FITSView::scaleSize(
double size)
753 return (currentZoom > 100.0 ? size : std::round(size * 100.0 / currentZoom)) / m_PreviewSampling;
756 void FITSView::updateFrame(
bool now)
770 if (toggleStretchAction)
771 toggleStretchAction->setChecked(stretchImage);
778 updateFrameLargeImage();
780 updateFrameSmallImage();
783 m_UpdateFrameTimer.start();
787 void FITSView::updateFrameLargeImage()
789 if (!displayPixmap.convertFromImage(rawImage))
795 QFont font = painter.font();
797 painter.setFont(font);
799 drawOverlay(&painter, 1.0 / m_PreviewSampling);
800 drawStarFilter(&painter, 1.0 / m_PreviewSampling);
801 m_ImageFrame->setPixmap(displayPixmap);
802 m_ImageFrame->resize(((m_PreviewSampling * currentZoom) / 100.0) * displayPixmap.size());
805 void FITSView::updateFrameSmallImage()
808 if (!displayPixmap.convertFromImage(scaledImage))
815 drawOverlay(&painter, currentZoom / ZOOM_DEFAULT);
816 drawStarFilter(&painter, currentZoom / ZOOM_DEFAULT);
818 m_ImageFrame->setPixmap(displayPixmap);
819 m_ImageFrame->resize(currentWidth, currentHeight);
823 void FITSView::drawStarFilter(
QPainter *painter,
double scale)
825 if (!starFilter.used())
827 const double w = m_ImageData->width() * scale;
828 const double h = m_ImageData->height() * scale;
829 double const diagonal = std::sqrt(w * w + h * h) / 2;
830 int const innerRadius = std::lround(diagonal * starFilter.innerRadius);
831 int const outerRadius = std::lround(diagonal * starFilter.outerRadius);
837 painter->
drawEllipse(center, outerRadius, outerRadius);
839 painter->
drawEllipse(center, innerRadius, innerRadius);
846 template <
typename T>
847 int drawClippingOneChannel(T *inputBuffer,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
852 const T clipping = clipVal;
853 for (
int y = 0; y < height; y++)
855 const auto inputLine = inputBuffer + y * width;
856 for (
int x = 0; x < width; x++)
858 if (inputLine[x] > clipping)
865 fprintf(stderr,
"%d of %d clipped (%.2f%%)\n", numClipped, width * height, numClipped * 100.0 / (width * height));
870 template <
typename T>
871 int drawClippingThreeChannels(T *inputBuffer,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
875 const int size = width * height;
876 const T clipping = clipVal;
878 for (
int y = 0; y < height; y++)
881 const T * inputLineR = inputBuffer + y * width;
882 const T * inputLineG = inputLineR + size;
883 const T * inputLineB = inputLineG + size;
885 for (
int x = 0; x < width; x++)
887 const T inputR = inputLineR[x];
888 const T inputG = inputLineG[x];
889 const T inputB = inputLineB[x];
890 if (inputR > clipping || inputG > clipping || inputB > clipping)
897 fprintf(stderr,
"%d of %d clipped (%.2f%%)\n", numClipped, width * height, numClipped * 100.0 / (width * height));
902 template <
typename T>
903 int drawClip(T *input_buffer,
int num_channels,
QPainter *painter,
int width,
int height,
double clipVal,
double scale)
905 if (num_channels == 1)
906 return drawClippingOneChannel(input_buffer, painter, width, height, clipVal, scale);
907 else if (num_channels == 3)
908 return drawClippingThreeChannels(input_buffer, painter, width, height, clipVal, scale);
914 void FITSView::drawClipping(
QPainter *painter)
916 auto input = m_ImageData->getImageBuffer();
917 const int height = m_ImageData->height();
918 const int width = m_ImageData->width();
919 constexpr
double FLOAT_CLIP = 60000;
920 constexpr
double SHORT_CLIP = 30000;
921 constexpr
double USHORT_CLIP = 60000;
922 constexpr
double BYTE_CLIP = 250;
923 switch (m_ImageData->dataType())
926 m_NumClipped = drawClip(
reinterpret_cast<uint8_t const*
>(input), m_ImageData->channels(), painter, width, height, BYTE_CLIP,
930 m_NumClipped = drawClip(
reinterpret_cast<short const*
>(input), m_ImageData->channels(), painter, width, height, SHORT_CLIP,
934 m_NumClipped = drawClip(
reinterpret_cast<unsigned short const*
>(input), m_ImageData->channels(), painter, width, height,
939 m_NumClipped = drawClip(
reinterpret_cast<long const*
>(input), m_ImageData->channels(), painter, width, height, USHORT_CLIP,
943 m_NumClipped = drawClip(
reinterpret_cast<float const*
>(input), m_ImageData->channels(), painter, width, height, FLOAT_CLIP,
947 m_NumClipped = drawClip(
reinterpret_cast<long long const*
>(input), m_ImageData->channels(), painter, width, height,
952 m_NumClipped = drawClip(
reinterpret_cast<double const*
>(input), m_ImageData->channels(), painter, width, height, FLOAT_CLIP,
959 emit newStatus(
QString(
"Clip:%1").arg(m_NumClipped), FITS_CLIP);
963 void FITSView::ZoomDefault()
967 emit actionUpdated(
"view_zoom_out",
true);
968 emit actionUpdated(
"view_zoom_in",
true);
970 currentZoom = ZOOM_DEFAULT;
971 currentWidth = m_ImageData->width();
972 currentHeight = m_ImageData->height();
976 emit newStatus(
QString(
"%1%").arg(currentZoom), FITS_ZOOM);
982 void FITSView::drawOverlay(
QPainter * painter,
double scale)
986 if (trackingBoxEnabled && getCursorMode() != FITSView::scopeCursor)
987 drawTrackingBox(painter, scale);
989 if (!markerCrosshair.isNull())
990 drawMarker(painter, scale);
993 drawCrosshair(painter, scale);
996 drawObjectNames(painter, scale);
998 #if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1000 drawEQGrid(painter, scale);
1004 drawPixelGrid(painter, scale);
1007 drawStarCentroid(painter, scale);
1010 drawClipping(painter);
1012 if (showMagnifyingGlass)
1013 drawMagnifyingGlass(painter, scale);
1018 void FITSView::drawMagnifyingGlass(
QPainter *painter,
double scale)
1020 if (magnifyingGlassX >= 0 && magnifyingGlassY >= 0 &&
1021 magnifyingGlassX < m_ImageData->width() &&
1022 magnifyingGlassY < m_ImageData->height())
1025 constexpr
double magAmount = 8;
1027 constexpr
int magWindowSize = 130;
1029 const int winXOffset = magWindowSize * 10.0 / currentZoom;
1030 const int winYOffset = magWindowSize * 10.0 / currentZoom;
1032 const int inputDimension = magWindowSize * 100 / currentZoom;
1035 const int outputDimension = inputDimension * scale + .99;
1038 int imgLeft = magnifyingGlassX - inputDimension / (2 * magAmount);
1039 int imgTop = magnifyingGlassY - inputDimension / (2 * magAmount);
1042 int winLeft = magnifyingGlassX + winXOffset;
1043 int winTop = magnifyingGlassY + winYOffset;
1047 int w = rawImage.width();
1048 int h = rawImage.height();
1049 const int rightLimit = std::min(w,
static_cast<int>((horizontalScrollBar()->value() + width()) * 100 / currentZoom));
1050 const int bottomLimit = std::min(h,
static_cast<int>((verticalScrollBar()->value() + height()) * 100 / currentZoom));
1051 if (winLeft + winXOffset + inputDimension > rightLimit)
1052 winLeft -= (2 * winXOffset + inputDimension);
1053 if (winTop + winYOffset + inputDimension > bottomLimit)
1054 winTop -= (2 * winYOffset + inputDimension);
1057 if ((imgLeft < 0 ) ||
1058 (imgLeft + inputDimension / magAmount >= w) ||
1060 (imgTop + inputDimension / magAmount > h))
1063 painter->
drawRect(winLeft * scale, winTop * scale, outputDimension, outputDimension);
1068 painter->
drawImage(
QRect(winLeft * scale, winTop * scale, outputDimension, outputDimension),
1070 QRect(imgLeft, imgTop, inputDimension / magAmount, inputDimension / magAmount));
1073 painter->
drawRect(winLeft * scale, winTop * scale, outputDimension, outputDimension);
1078 void FITSView::updateMagnifyingGlass(
int x,
int y)
1083 magnifyingGlassX = x;
1084 magnifyingGlassY = y;
1085 if (magnifyingGlassX == -1 && magnifyingGlassY == -1)
1087 if (showMagnifyingGlass)
1089 showMagnifyingGlass =
false;
1093 showMagnifyingGlass =
true;
1098 void FITSView::updateMode(FITSMode fmode)
1103 void FITSView::drawMarker(
QPainter * painter,
double scale)
1105 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")),
1108 const float pxperdegree = scale * (57.3 / 1.8);
1110 const float s1 = 0.5 * pxperdegree;
1111 const float s2 = pxperdegree;
1112 const float s3 = 2.0 * pxperdegree;
1114 const float x0 = scale * markerCrosshair.x();
1115 const float y0 = scale * markerCrosshair.y();
1116 const float x1 = x0 - 0.5 * s1;
1117 const float y1 = y0 - 0.5 * s1;
1118 const float x2 = x0 - 0.5 * s2;
1119 const float y2 = y0 - 0.5 * s2;
1120 const float x3 = x0 - 0.5 * s3;
1121 const float y3 = y0 - 0.5 * s3;
1133 bool FITSView::drawHFR(
QPainter * painter,
const QString &hfr,
int x,
int y)
1139 QPoint const hfrBottomLeft(x, y);
1140 QRect const hfrRect(hfrBottomLeft.x(), hfrBottomLeft.y() - hfrSize.
height(), hfrSize.
width(), hfrSize.
height());
1143 if (boundingRect.contains(hfrRect))
1146 painter->
drawText(hfrBottomLeft, hfr);
1154 void FITSView::drawStarCentroid(
QPainter * painter,
double scale)
1157 double fontSize = painterFont.
pointSizeF() * 2;
1163 fontSize = scaleSize(painterFont.
pointSizeF());
1165 painter->
setFont(painterFont);
1170 for (
auto const &starCenter : m_ImageData->getStarCenters())
1172 int const w = std::round(starCenter->width) * scale;
1176 const double xCoord = starCenter->x - 0.5;
1177 const double yCoord = starCenter->y - 0.5;
1178 const int xc = std::round((xCoord - starCenter->width / 2.0f) * scale);
1179 const int yc = std::round((yCoord - starCenter->width / 2.0f) * scale);
1180 const int hw = w / 2;
1182 BahtinovEdge* bEdge =
dynamic_cast<BahtinovEdge*
>(starCenter);
1183 if (bEdge !=
nullptr)
1187 painter->
drawLine(bEdge->line[0].x1() * scale, bEdge->line[0].y1() * scale,
1188 bEdge->line[0].x2() * scale, bEdge->line[0].y2() * scale);
1190 painter->
drawLine(bEdge->line[1].x1() * scale, bEdge->line[1].y1() * scale,
1191 bEdge->line[1].x2() * scale, bEdge->line[1].y2() * scale);
1193 painter->
drawLine(bEdge->line[2].x1() * scale, bEdge->line[2].y1() * scale,
1194 bEdge->line[2].x2() * scale, bEdge->line[2].y2() * scale);
1201 double factor = 15.0;
1202 QPointF offsetVector = (bEdge->offset -
QPointF(starCenter->x, starCenter->y)) * factor;
1203 int const xo = std::round((starCenter->x + offsetVector.
x() - starCenter->width / 2.0f) * scale);
1204 int const yo = std::round((starCenter->y + offsetVector.
y() - starCenter->width / 2.0f) * scale);
1210 painter->
drawLine(xc + hw, yc + hw, xo + hw, yo + hw);
1214 const double radius = starCenter->HFR > 0 ? 2.0f * starCenter->HFR * scale : w;
1222 if (!drawHFR(painter, hfr, xc + w + 5, yc + w / 2))
1225 for (
int i = 0; i < 10; ++i)
1227 const double tempFontSize = painterFont.
pointSizeF() - 2;
1228 if (tempFontSize <= 0)
break;
1230 painter->
setFont(painterFont);
1231 if (drawHFR(painter, hfr, xc + w + 5, yc + w / 2))
1236 painter->
setFont(painterFont);
1242 void FITSView::drawTrackingBox(
QPainter * painter,
double scale)
1246 if (trackingBox.isNull())
1249 const int x1 = trackingBox.x() * scale;
1250 const int y1 = trackingBox.y() * scale;
1251 const int w = trackingBox.width() * scale;
1252 const int h = trackingBox.height() * scale;
1261 void FITSView::drawCrosshair(
QPainter * painter,
double scale)
1263 if (!m_ImageData)
return;
1264 const int image_width = m_ImageData->width();
1265 const int image_height = m_ImageData->height();
1266 const QPointF c =
QPointF((qreal)image_width / 2 * scale, (qreal)image_height / 2 * scale);
1267 const float midX = (float)image_width / 2 * scale;
1268 const float midY = (float)image_height / 2 * scale;
1269 const float maxX = (float)image_width * scale;
1270 const float maxY = (float)image_height * scale;
1271 const float r = 50 * scale;
1273 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"TargetColor")), scaleSize(1)));
1276 painter->
drawLine(0, midY, midX - r, midY);
1279 painter->
drawLine(midX + r, midY, maxX, midY);
1282 painter->
drawLine(midX, 0, midX, midY - r);
1285 painter->
drawLine(midX, midY + r, midX, maxY);
1300 void FITSView::drawPixelGrid(
QPainter * painter,
double scale)
1302 const float width = m_ImageData->width() * scale;
1303 const float height = m_ImageData->height() * scale;
1304 const float cX = width / 2;
1305 const float cY = height / 2;
1306 const float deltaX = width / 10;
1307 const float deltaY = height / 10;
1314 #if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1315 painter->
drawText(width - (fm.width(str) + 10), cY - 5, str);
1317 painter->
drawText(width - (fm.horizontalAdvance(str) + 10), cY - 5, str);
1321 painter->
drawLine(cX, 0, cX, height);
1322 painter->
drawLine(0, cY, width, cY);
1326 for (
int x = deltaX; x < cX - deltaX; x += deltaX)
1330 painter->
drawLine(cX - x, 0, cX - x, height);
1331 painter->
drawLine(cX + x, 0, cX + x, height);
1334 for (
int y = deltaY; y < cY - deltaY; y += deltaY)
1337 #if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1338 painter->
drawText(width - (fm.width(str) + 10), cY + y - 5, str);
1340 painter->
drawText(width - (fm.horizontalAdvance(str) + 10), cY + y - 5, str);
1343 #if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1344 painter->
drawText(width - (fm.width(str) + 10), cY - y - 5, str);
1346 painter->
drawText(width - (fm.horizontalAdvance(str) + 10), cY - y - 5, str);
1348 painter->
drawLine(0, cY + y, width, cY + y);
1349 painter->
drawLine(0, cY - y, width, cY - y);
1352 bool FITSView::imageHasWCS()
1354 if (m_ImageData !=
nullptr)
1355 return m_ImageData->hasWCS();
1359 void FITSView::drawObjectNames(
QPainter * painter,
double scale)
1361 painter->
setPen(
QPen(
QColor(KStarsData::Instance()->colorScheme()->colorNamed(
"FITSObjectLabelColor"))));
1362 for (
const auto &listObject : m_ImageData->getSkyObjects())
1364 painter->
drawRect(listObject->x() * scale - 5, listObject->y() * scale - 5, 10, 10);
1365 painter->
drawText(listObject->x() * scale + 10, listObject->y() * scale + 10, listObject->skyObject()->name());
1376 #if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1377 void FITSView::drawEQGrid(
QPainter * painter,
double scale)
1379 const int image_width = m_ImageData->width();
1380 const int image_height = m_ImageData->height();
1382 if (m_ImageData->hasWCS() && m_ImageData->fullWCS())
1384 double maxRA = -1000;
1385 double minRA = 1000;
1386 double maxDec = -1000;
1387 double minDec = 1000;
1388 m_ImageData->findWCSBounds(minRA, maxRA, minDec, maxDec);
1390 auto minDecMinutes = (int)(minDec * 12);
1391 auto maxDecMinutes = (int)(maxDec * 12);
1394 (int)(minRA / 15.0 *
1396 auto maxRAMinutes = (int)(maxRA / 15.0 * 120.0);
1398 double raConvert = 15 / 120.0;
1399 double decConvert = 1.0 / 12.0;
1401 if (maxDec > 50 || minDec < -50)
1404 (int)(minRA / 15.0 * 60.0);
1405 maxRAMinutes = (int)(maxRA / 15.0 * 60.0);
1406 raConvert = 15 / 60.0;
1409 if (maxDec > 80 || minDec < -80)
1412 (int)(minRA / 15.0 * 30);
1413 maxRAMinutes = (int)(maxRA / 15.0 * 30);
1414 raConvert = 15 / 30.0;
1416 if (maxDec > 85 || minDec < -85)
1419 (int)(minRA / 15.0 * 6);
1420 maxRAMinutes = (int)(maxRA / 15.0 * 6);
1421 raConvert = 15 / 6.0;
1423 if (maxDec >= 89.25 || minDec <= -89.25)
1428 maxRAMinutes = (int)(maxRA / 15);
1434 QPointF pixelPoint, imagePoint, pPoint;
1438 for (
int targetRA = minRAMinutes; targetRA <= maxRAMinutes; targetRA++)
1441 double target = targetRA * raConvert;
1443 if (eqGridPoints.count() != 0)
1444 eqGridPoints.clear();
1446 double increment = std::abs((maxDec - minDec) /
1449 for (
double targetDec = minDec; targetDec <= maxDec; targetDec += increment)
1451 SkyPoint pointToGet(target / 15.0, targetDec);
1452 bool inImage = m_ImageData->wcsToPixel(pointToGet, pixelPoint, imagePoint);
1455 QPointF pt(pixelPoint.
x() * scale, pixelPoint.
y() * scale);
1456 eqGridPoints.append(pt);
1460 if (eqGridPoints.count() > 1)
1462 for (
int i = 1; i < eqGridPoints.count(); i++)
1463 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1466 if (maxDec <= 50 && maxDec >= -50)
1468 QPointF pt = getPointForGridLabel(painter, str, scale);
1476 for (
int targetDec = minDecMinutes; targetDec <= maxDecMinutes; targetDec++)
1478 if (eqGridPoints.count() != 0)
1479 eqGridPoints.clear();
1481 double increment = std::abs((maxRA - minRA) /
1483 double target = targetDec * decConvert;
1485 for (
double targetRA = minRA; targetRA <= maxRA; targetRA += increment)
1487 SkyPoint pointToGet(targetRA / 15, targetDec * decConvert);
1488 bool inImage = m_ImageData->wcsToPixel(pointToGet, pixelPoint, imagePoint);
1491 QPointF pt(pixelPoint.
x() * scale, pixelPoint.
y() * scale);
1492 eqGridPoints.append(pt);
1495 if (eqGridPoints.count() > 1)
1497 for (
int i = 1; i < eqGridPoints.count(); i++)
1498 painter->
drawLine(eqGridPoints.value(i - 1), eqGridPoints.value(i));
1500 QPointF pt = getPointForGridLabel(painter, str, scale);
1509 bool NCPtest = m_ImageData->wcsToPixel(NCP, pPoint, imagePoint);
1513 (pPoint.
x() > 0 && pPoint.
x() < image_width) && (pPoint.
y() > 0 && pPoint.
y() < image_height);
1516 painter->
fillRect(pPoint.
x() * scale - 2, pPoint.
y() * scale - 2, 4, 4,
1518 painter->
drawText(pPoint.
x() * scale + 15, pPoint.
y() * scale + 15,
1519 i18nc(
"North Celestial Pole",
"NCP"));
1526 bool SCPtest = m_ImageData->wcsToPixel(SCP, pPoint, imagePoint);
1530 (pPoint.
x() > 0 && pPoint.
x() < image_width) && (pPoint.
y() > 0 && pPoint.
y() < image_height);
1533 painter->
fillRect(pPoint.
x() * scale - 2, pPoint.
y() * scale - 2, 4, 4,
1535 painter->
drawText(pPoint.
x() * scale + 15, pPoint.
y() * scale + 15,
1536 i18nc(
"South Celestial Pole",
"SCP"));
1543 bool FITSView::pointIsInImage(
QPointF pt,
double scale)
1545 int image_width = m_ImageData->width();
1546 int image_height = m_ImageData->height();
1547 return pt.
x() < image_width * scale && pt.
y() < image_height * scale && pt.
x() > 0 && pt.
y() > 0;
1553 #if QT_VERSION < QT_VERSION_CHECK(5,11,0)
1554 int strWidth = fm.width(str);
1556 int strWidth = fm.horizontalAdvance(str);
1558 int strHeight = fm.height();
1559 int image_width = m_ImageData->width();
1560 int image_height = m_ImageData->height();
1563 QPointF maxXPt(image_width * scale / 2, image_height * scale / 2);
1564 for (
auto &p : eqGridPoints)
1566 if (p.x() > maxXPt.x() && pointIsInImage(p, scale))
1569 QPointF maxYPt(image_width * scale / 2, image_height * scale / 2);
1571 for (
auto &p : eqGridPoints)
1573 if (p.y() > maxYPt.y() && pointIsInImage(p, scale))
1576 QPointF minXPt(image_width * scale / 2, image_height * scale / 2);
1578 for (
auto &p : eqGridPoints)
1580 if (p.x() < minXPt.x() && pointIsInImage(p, scale))
1583 QPointF minYPt(image_width * scale / 2, image_height * scale / 2);
1585 for (
auto &p : eqGridPoints)
1587 if (p.y() < minYPt.y() && pointIsInImage(p, scale))
1596 if (image_width * scale - maxXPt.x() < strWidth)
1599 image_width * scale - (strWidth + 10),
1603 if (image_height * scale - maxYPt.y() < strHeight)
1605 maxYPt.x() - (strWidth + 10),
1606 image_height * scale -
1608 if (minYPt.y() < strHeight)
1610 minYPt.x() * scale + 10,
1612 if (minXPt.x() < strWidth)
1615 minXPt.y() * scale +
1618 if (maxXPt.x() == image_width * scale / 2 && maxXPt.y() == image_height * scale / 2)
1621 return QPoint(maxXPt.x() - (strWidth + 10), maxXPt.y() - (strHeight + 10));
1624 void FITSView::setFirstLoad(
bool value)
1629 QPixmap &FITSView::getTrackingBoxPixmap(uint8_t margin)
1631 if (trackingBox.isNull())
1632 return trackingBoxPixmap;
1635 const float scale = getScale();
1637 int x1 = (trackingBox.x() - margin) * scale;
1638 int y1 = (trackingBox.y() - margin) * scale;
1639 int w = (trackingBox.width() + margin * 2) * scale;
1640 int h = (trackingBox.height() + margin * 2) * scale;
1642 trackingBoxPixmap = m_ImageFrame->grab(
QRect(x1, y1, w, h));
1643 return trackingBoxPixmap;
1646 void FITSView::setTrackingBox(
const QRect &rect)
1648 if (rect != trackingBox)
1657 void FITSView::resizeTrackingBox(
int newSize)
1659 int x = trackingBox.x() + trackingBox.width() / 2;
1660 int y = trackingBox.y() + trackingBox.height() / 2;
1661 int delta = newSize / 2;
1662 setTrackingBox(
QRect( x - delta, y - delta, newSize, newSize));
1665 void FITSView::processRectangleFixed(
int s)
1667 int w = m_ImageData->width();
1668 int h = m_ImageData->height();
1670 QPoint c = selectionRectangleRaw.center();
1671 c.
setX(qMax((
int)round(s / 2.0), c.
x()));
1672 c.
setX(qMin(w - (
int)round(s / 2.0), c.
x()));
1673 c.
setY(qMax((
int)round(s / 2.0), c.
y()));
1674 c.
setY(qMin(h - (
int)round(s / 2.0), c.
y()));
1676 QPoint topLeft, botRight;
1677 topLeft =
QPoint(c.
x() - round(s / 2.0), c.
y() - round(s / 2.0));
1678 botRight =
QPoint(c.
x() + round(s / 2.0), c.
y() + round(s / 2.0));
1680 emit setRubberBand(
QRect(topLeft, botRight));
1681 processRectangle(topLeft, botRight,
true);
1684 void FITSView::processRectangle(
QPoint p1,
QPoint p2,
bool calculate)
1686 if(!isSelectionRectShown())
1697 QPoint topLeft = selectionRectangleRaw.topLeft();
1698 QPoint botRight = selectionRectangleRaw.bottomRight();
1700 topLeft.
setX(qMax(1, topLeft.
x()));
1701 topLeft.
setY(qMax(1, topLeft.
y()));
1702 botRight.
setX(qMin((
int)m_ImageData->width(), botRight.
x()));
1703 botRight.
setY(qMin((
int)m_ImageData->height(), botRight.
y()));
1705 selectionRectangleRaw.setTopLeft(topLeft);
1706 selectionRectangleRaw.setBottomRight(botRight);
1710 emit rectangleUpdated(selectionRectangleRaw);
1718 bool FITSView::isImageStretched()
1720 return stretchImage;
1723 bool FITSView::isClippingShown()
1725 return showClipping;
1728 bool FITSView::isCrosshairShown()
1730 return showCrosshair;
1733 bool FITSView::isEQGridShown()
1738 bool FITSView::isSelectionRectShown()
1740 return showSelectionRect;
1742 bool FITSView::areObjectsShown()
1747 bool FITSView::isPixelGridShown()
1749 return showPixelGrid;
1752 void FITSView::toggleCrosshair()
1754 showCrosshair = !showCrosshair;
1758 void FITSView::toggleClipping()
1760 showClipping = !showClipping;
1764 void FITSView::toggleEQGrid()
1766 showEQGrid = !showEQGrid;
1768 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.isRunning())
1771 wcsWatcher.setFuture(future);
1779 void FITSView::toggleSelectionMode()
1781 showSelectionRect = !showSelectionRect;
1782 emit showRubberBand(showSelectionRect);
1787 void FITSView::toggleObjects()
1789 showObjects = !showObjects;
1791 if (m_ImageData->getWCSState() == FITSData::Idle && !wcsWatcher.isRunning())
1794 wcsWatcher.setFuture(future);
1800 #if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
1801 m_ImageData->searchObjects();
1807 void FITSView::toggleStars()
1809 toggleStars(!markStars);
1814 void FITSView::toggleStretch()
1816 stretchImage = !stretchImage;
1817 if (m_ImageFrame && rescale(ZOOM_KEEP_LEVEL))
1821 void FITSView::toggleStarProfile()
1823 #ifdef HAVE_DATAVISUALIZATION
1824 showStarProfile = !showStarProfile;
1825 if(showStarProfile && trackingBoxEnabled)
1827 if(toggleProfileAction)
1828 toggleProfileAction->setChecked(showStarProfile);
1834 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
1836 setCursorMode(selectCursor);
1837 connect(
this, SIGNAL(trackingStarSelected(
int,
int)),
this, SLOT(move3DTrackingBox(
int,
int)));
1838 trackingBox =
QRect(0, 0, 128, 128);
1839 setTrackingBoxEnabled(
true);
1840 if(starProfileWidget)
1841 connect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
1843 if(starProfileWidget)
1844 connect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
1850 if(mode == FITS_NORMAL || mode == FITS_ALIGN)
1852 if(getCursorMode() == selectCursor)
1853 setCursorMode(dragCursor);
1854 disconnect(
this, SIGNAL(trackingStarSelected(
int,
int)),
this, SLOT(move3DTrackingBox(
int,
int)));
1855 setTrackingBoxEnabled(
false);
1856 if(starProfileWidget)
1857 disconnect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
1859 if(starProfileWidget)
1861 disconnect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
1862 starProfileWidget->close();
1863 starProfileWidget =
nullptr;
1865 emit starProfileWindowClosed();
1871 void FITSView::move3DTrackingBox(
int x,
int y)
1873 int boxSize = trackingBox.width();
1874 QRect starRect =
QRect(x - boxSize / 2, y - boxSize / 2, boxSize, boxSize);
1875 setTrackingBox(starRect);
1878 void FITSView::viewStarProfile()
1880 #ifdef HAVE_DATAVISUALIZATION
1881 if(!trackingBoxEnabled)
1883 setTrackingBoxEnabled(
true);
1884 setTrackingBox(
QRect(0, 0, 128, 128));
1886 if(!starProfileWidget)
1888 starProfileWidget =
new StarProfileViewer(
this);
1893 QWidget * superParent = this->parentWidget();
1899 connect(starProfileWidget, SIGNAL(rejected()),
this, SLOT(toggleStarProfile()));
1900 if(mode == FITS_ALIGN || mode == FITS_NORMAL)
1902 starProfileWidget->enableTrackingBox(
true);
1903 m_ImageData->setStarAlgorithm(ALGORITHM_CENTROID);
1904 connect(starProfileWidget, SIGNAL(sampleSizeUpdated(
int)),
this, SLOT(resizeTrackingBox(
int)));
1907 QList<Edge *> starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
1908 if(starCenters.
size() == 0)
1913 m_ImageData->findStars(ALGORITHM_CENTROID, trackingBox).waitForFinished();
1914 starCenters = m_ImageData->getStarCentersInSubFrame(trackingBox);
1917 starProfileWidget->loadData(m_ImageData, trackingBox, starCenters);
1918 starProfileWidget->show();
1919 starProfileWidget->raise();
1926 void FITSView::togglePixelGrid()
1928 showPixelGrid = !showPixelGrid;
1934 if(trackingBoxEnabled)
1935 return m_ImageData->findStars(algorithm, trackingBox);
1937 return m_ImageData->findStars(algorithm, searchBox);
1940 void FITSView::toggleStars(
bool enable)
1948 void FITSView::searchStars()
1951 if (m_ImageData->areStarsSearched() || !m_ImageData || (m_ImageData->getRecordValue(
"FRAME", frameType)
1952 && frameType.
toString() !=
"Light"))
1956 emit newStatus(
i18n(
"Finding stars..."), FITS_MESSAGE);
1957 qApp->processEvents();
1959 #ifdef HAVE_STELLARSOLVER
1960 QVariantMap extractionSettings;
1961 extractionSettings[
"optionsProfileIndex"] = Options::hFROptionsProfile();
1962 extractionSettings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::HFRProfiles);
1963 imageData()->setSourceExtractorSettings(extractionSettings);
1968 if (result.
result() && isVisible())
1970 emit newStatus(
"", FITS_MESSAGE);
1975 void FITSView::processPointSelection(
int x,
int y)
1977 emit trackingStarSelected(x, y);
1980 void FITSView::processMarkerSelection(
int x,
int y)
1982 markerCrosshair.setX(x);
1983 markerCrosshair.setY(y);
1988 void FITSView::setTrackingBoxEnabled(
bool enable)
1990 if (enable != trackingBoxEnabled)
1992 trackingBoxEnabled = enable;
2007 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2010 QPoint mouseCenter = getImagePoint(
event->position().toPoint());
2012 if (
event->angleDelta().y() > 0)
2017 cleanUpZoom(mouseCenter);
2019 emit zoomRubberBand(getCurrentZoom() / ZOOM_DEFAULT);
2028 void FITSView::cleanUpZoom(
QPoint viewCenter)
2032 double scale = (currentZoom / ZOOM_DEFAULT);
2033 if (!markerCrosshair.isNull())
2035 x0 = markerCrosshair.x() * scale;
2036 y0 = markerCrosshair.y() * scale;
2038 else if (trackingBoxEnabled)
2040 x0 = trackingBox.center().x() * scale;
2041 y0 = trackingBox.center().y() * scale;
2043 else if (!viewCenter.
isNull())
2045 x0 = viewCenter.
x() * scale;
2046 y0 = viewCenter.
y() * scale;
2048 if ((x0 != 0) || (y0 != 0))
2049 ensureVisible(x0, y0, width() / 2, height() / 2);
2050 updateMouseCursor();
2065 double scale = (currentZoom / ZOOM_DEFAULT);
2067 QPoint imagePoint =
QPoint(widgetPoint.
x() / scale, widgetPoint.
y() / scale);
2071 void FITSView::initDisplayImage()
2075 int w = (m_ImageData->width() + m_PreviewSampling - 1) / m_PreviewSampling;
2076 int h = (m_ImageData->height() + m_PreviewSampling - 1) / m_PreviewSampling;
2078 if (m_ImageData->channels() == 1)
2082 rawImage.setColorCount(256);
2083 for (
int i = 0; i < 256; i++)
2084 rawImage.setColor(i, qRgb(i, i, i));
2099 bool FITSView::event(
QEvent * event)
2122 zoomLocation = getImagePoint(mapFromGlobal(
QCursor::pos()));
2130 if (zoomTime > 10000)
2132 if (zooming && (zoomTime % 10 == 0))
2139 cleanUpZoom(zoomLocation);
2150 void FITSView::syncWCSState()
2152 bool hasWCS = m_ImageData->hasWCS();
2153 bool wcsLoaded = m_ImageData->getWCSState() == FITSData::Success;
2155 #if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
2157 m_ImageData->searchObjects();
2160 if (hasWCS && wcsLoaded)
2161 this->updateFrame();
2163 emit wcsToggled(hasWCS);
2165 if (toggleEQGridAction !=
nullptr)
2166 toggleEQGridAction->setEnabled(hasWCS);
2167 if (toggleObjectsAction !=
nullptr)
2168 toggleObjectsAction->setEnabled(hasWCS);
2169 if (centerTelescopeAction !=
nullptr)
2170 centerTelescopeAction->setEnabled(hasWCS);
2173 void FITSView::createFloatingToolBar()
2175 if (floatingToolBar !=
nullptr)
2178 floatingToolBar =
new QToolBar(
this);
2180 floatingToolBar->setGraphicsEffect(eff);
2181 eff->setOpacity(0.2);
2182 floatingToolBar->setVisible(
false);
2183 floatingToolBar->setStyleSheet(
2184 "QToolBar{background: rgba(150, 150, 150, 210); border:none; color: yellow}"
2185 "QToolButton{background: transparent; border:none; color: yellow}"
2186 "QToolButton:hover{background: rgba(200, 200, 200, 255);border:solid; color: yellow}"
2187 "QToolButton:checked{background: rgba(110, 110, 110, 255);border:solid; color: yellow}");
2188 floatingToolBar->setFloatable(
true);
2189 floatingToolBar->setIconSize(
QSize(25, 25));
2201 i18n(
"Default Zoom"),
this, SLOT(ZoomDefault()));
2204 i18n(
"Zoom to Fit"),
this, SLOT(ZoomToFit()));
2206 toggleStretchAction = floatingToolBar->addAction(
QIcon::fromTheme(
"transform-move"),
2207 i18n(
"Toggle Stretch"),
2208 this, SLOT(toggleStretch()));
2212 floatingToolBar->addSeparator();
2215 i18n(
"Show Cross Hairs"),
this, SLOT(toggleCrosshair()));
2219 i18n(
"Show Pixel Gridlines"),
this, SLOT(togglePixelGrid()));
2224 i18n(
"Detect Stars in Image"),
this, SLOT(toggleStars()));
2225 toggleStarsAction->setCheckable(
true);
2227 #ifdef HAVE_DATAVISUALIZATION
2228 toggleProfileAction =
2230 i18n(
"View Star Profile"),
this, SLOT(toggleStarProfile()));
2231 toggleProfileAction->setCheckable(
true);
2234 if (mode == FITS_NORMAL || mode == FITS_ALIGN)
2236 floatingToolBar->addSeparator();
2238 toggleEQGridAction =
2240 i18n(
"Show Equatorial Gridlines"),
this, SLOT(toggleEQGrid()));
2241 toggleEQGridAction->setCheckable(
true);
2242 toggleEQGridAction->setEnabled(
false);
2244 toggleObjectsAction =
2246 i18n(
"Show Objects in Image"),
this, SLOT(toggleObjects()));
2247 toggleObjectsAction->setCheckable(
true);
2248 toggleEQGridAction->setEnabled(
false);
2250 centerTelescopeAction =
2251 floatingToolBar->addAction(
QIcon::fromTheme(
"center_telescope",
QIcon(
":/icons/center_telescope.svg")),
2252 i18n(
"Center Telescope"),
this, SLOT(centerTelescope()));
2253 centerTelescopeAction->setCheckable(
true);
2254 centerTelescopeAction->setEnabled(
false);
2263 void FITSView::centerTelescope()
2267 if (getCursorMode() == FITSView::scopeCursor)
2269 setCursorMode(lastMouseMode);
2273 lastMouseMode = getCursorMode();
2274 setCursorMode(FITSView::scopeCursor);
2278 updateScopeButton();
2281 void FITSView::updateScopeButton()
2283 if (centerTelescopeAction !=
nullptr)
2285 if (getCursorMode() == FITSView::scopeCursor)
2287 centerTelescopeAction->setChecked(
true);
2291 centerTelescopeAction->setChecked(
false);
2300 bool FITSView::isTelescopeActive()
2303 if (INDIListener::Instance()->size() == 0)
2308 for (
auto &oneDevice : INDIListener::Instance()->getDevices())
2310 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE))
2312 return oneDevice->isConnected();
2320 void FITSView::setStarsEnabled(
bool enable)
2323 if (floatingToolBar !=
nullptr)
2325 foreach (
QAction * action, floatingToolBar->actions())
2327 if (action->
text() ==
i18n(
"Detect Stars in Image"))
2336 void FITSView::setStarsHFREnabled(
bool enable)
2338 showStarsHFR = enable;