From e08107aa13d0d2cd18b9cccb5c1a4f59528295ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Sat, 1 Nov 2025 12:05:19 +0100 Subject: [PATCH] Improve Save as --- space.nouspiro.tenmon.metainfo.xml | 9 +++++++++ src/loadrunable.cpp | 6 +++++- src/loadrunable.h | 3 +++ src/mainwindow.cpp | 27 ++++++++++++++------------- src/mainwindow.h | 2 +- src/mtfparam.h | 30 ++++++++++++++++++++++++++++++ src/rawimage.cpp | 28 ++++++++++++++++++++++------ src/stretchtoolbar.cpp | 5 +++++ src/stretchtoolbar.h | 1 + 9 files changed, 90 insertions(+), 21 deletions(-) diff --git a/space.nouspiro.tenmon.metainfo.xml b/space.nouspiro.tenmon.metainfo.xml index 4b14d6c..aaee8bd 100644 --- a/space.nouspiro.tenmon.metainfo.xml +++ b/space.nouspiro.tenmon.metainfo.xml @@ -59,6 +59,15 @@ + + +
    +
  • Better image Save as
  • +
  • Fix xisf file corruption when platesolving
  • +
  • Add selecting language
  • +
+
+
    diff --git a/src/loadrunable.cpp b/src/loadrunable.cpp index bead155..05b9e39 100644 --- a/src/loadrunable.cpp +++ b/src/loadrunable.cpp @@ -193,7 +193,11 @@ void ConvertRunable::run() QFileInfo info(m_outfile); info.dir().mkpath("."); - if(m_params.autostretch) + if(m_params.stretch) + { + rawimage->applySTF(m_params.mtf); + } + else if(m_params.autostretch) { rawimage->calcStats(); MTFParam mtfParam = rawimage->calcMTFParams(); diff --git a/src/loadrunable.h b/src/loadrunable.h index ab96439..4bcd9a3 100644 --- a/src/loadrunable.h +++ b/src/loadrunable.h @@ -6,6 +6,7 @@ #include #include #include "imageinfodata.h" +#include "mtfparam.h" class Image; @@ -33,6 +34,8 @@ public: QSize resize; Qt::AspectRatioMode aspect = Qt::KeepAspectRatio; bool autostretch = false; + bool stretch = false; + MTFParam mtf; ConvertParams(){} ConvertParams(const QVariantMap &map); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9506a26..b917c2b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -620,9 +620,13 @@ void MainWindow::reindex() void MainWindow::saveAs() { QString selectedFilter; + ImagePtr ptr = m_ringList->currentImage(); + if(!ptr)return; + + QFileInfo srcFile(ptr->name()); QString file = QFileDialog::getSaveFileName(this, tr("Save as"), - _lastDir, + _lastDir + "/" + srcFile.baseName(), _saveFilter, &selectedFilter); auto filterToFormat = [](const QString &file, const QString &filter) -> const QString @@ -644,25 +648,22 @@ void MainWindow::saveAs() if(!file.isEmpty()) { + auto button = QMessageBox::question(this, tr("Apply stretch?"), tr("Apply current stretch function to image?")); + QString format = filterToFormat(file, selectedFilter); - if(format == "fits" || format == "xisf") - { - convert(file, format); - } - else - { - QImage img = m_image->renderToImage(); - if(!img.isNull()) - img.save(file, filterToFormat(file, selectedFilter).toLatin1().data()); - } + convert(file, format, button == QMessageBox::Yes); } } -void MainWindow::convert(const QString &outfile, const QString &format) +void MainWindow::convert(const QString &outfile, const QString &format, bool stretch) { QString file = m_ringList->currentImage()->name(); - QThreadPool::globalInstance()->start(new ConvertRunable(file, outfile, format)); + ConvertRunable::ConvertParams param; + param.stretch = stretch; + param.mtf = m_stretchPanel->params(); + + QThreadPool::globalInstance()->start(new ConvertRunable(file, outfile, format, param)); } void MainWindow::markImage() diff --git a/src/mainwindow.h b/src/mainwindow.h index 16efbf6..ad9124a 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -52,7 +52,7 @@ public slots: void indexDir(const QString &dir); void reindex(); void saveAs(); - void convert(const QString &outfile, const QString &format); + void convert(const QString &outfile, const QString &format, bool stretch); void markImage(); void unmarkImage(); void markAndNext(); diff --git a/src/mtfparam.h b/src/mtfparam.h index 64c31e7..6736381 100644 --- a/src/mtfparam.h +++ b/src/mtfparam.h @@ -1,11 +1,41 @@ #ifndef MTFPARAM_H #define MTFPARAM_H +#include + struct MTFParam { float blackPoint[3] = {0.0f, 0.0f, 0.0f}; float midPoint[3] = {0.5f, 0.5f, 0.5f}; float whitePoint[3] = {1.0f, 1.0f, 1.0f}; + QVariantMap toVariantMap() const + { + QVariantMap ret; + ret["black"] = QList({blackPoint[0], blackPoint[1], blackPoint[2]}); + ret["mid"] = QList({midPoint[0], midPoint[1], midPoint[2]}); + ret["white"] = QList({whitePoint[0], whitePoint[1], whitePoint[2]}); + return ret; + } + static bool fromVariantMap(const QVariantMap &map, MTFParam &mtf) + { + if(!map.contains("black") || !map.contains("mid") || !map.contains("white")) + return false; + + QVariantList black = map["black"].toList(); + QVariantList mid = map["mid"].toList(); + QVariantList white = map["white"].toList(); + if(black.size() < 3 || mid.size() < 3 || white.size() < 3) + return false; + + for(int i = 0; i < 3; i++) + { + mtf.blackPoint[i] = black[i].toFloat(); + mtf.midPoint[i] = mid[i].toFloat(); + mtf.whitePoint[i] = white[i].toFloat(); + } + + return true; + } }; #endif // MTFPARAM_H diff --git a/src/rawimage.cpp b/src/rawimage.cpp index c8cf346..6533b64 100644 --- a/src/rawimage.cpp +++ b/src/rawimage.cpp @@ -1195,12 +1195,28 @@ void RawImage::applySTF(const MTFParam &mtfParams) for(size_t i = 0; i < len; i++) { float x; - if constexpr(std::numeric_limits>::is_integer)x = src[i] * iscale; - else x = src[i] * unit.first + unit.second; - x = (x - mtfParams.blackPoint[0]) / (mtfParams.whitePoint[0] - mtfParams.blackPoint[0]); - x = std::clamp(x, 0.0f, 1.0f); - x = ((mtfParams.midPoint[0] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[0] - 1.0f) * x - mtfParams.midPoint[0]); - src[i] = x * s; + if(m_ch == 4) + { + size_t c = i & 0x3; + if(c < 3) + { + if constexpr(std::numeric_limits>::is_integer)x = src[i] * iscale; + else x = src[i] * unit.first + unit.second; + x = (x - mtfParams.blackPoint[c]) / (mtfParams.whitePoint[c] - mtfParams.blackPoint[c]); + x = std::clamp(x, 0.0f, 1.0f); + x = ((mtfParams.midPoint[c] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[c] - 1.0f) * x - mtfParams.midPoint[c]); + src[i] = x * s; + } + } + else + { + if constexpr(std::numeric_limits>::is_integer)x = src[i] * iscale; + else x = src[i] * unit.first + unit.second; + x = (x - mtfParams.blackPoint[0]) / (mtfParams.whitePoint[0] - mtfParams.blackPoint[0]); + x = std::clamp(x, 0.0f, 1.0f); + x = ((mtfParams.midPoint[0] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[0] - 1.0f) * x - mtfParams.midPoint[0]); + src[i] = x * s; + } } }; diff --git a/src/stretchtoolbar.cpp b/src/stretchtoolbar.cpp index 017e282..b6573bc 100644 --- a/src/stretchtoolbar.cpp +++ b/src/stretchtoolbar.cpp @@ -104,6 +104,11 @@ StretchToolbar::~StretchToolbar() settings.setValue("stretchtoolbar/autostretch", m_autoStretchOnLoad->isChecked()); } +const MTFParam &StretchToolbar::params() const +{ + return m_mtfParam; +} + void StretchToolbar::stretchImage(Image *img) { if(img && img->rawImage()) diff --git a/src/stretchtoolbar.h b/src/stretchtoolbar.h index 3f5cd0d..cb3690e 100644 --- a/src/stretchtoolbar.h +++ b/src/stretchtoolbar.h @@ -22,6 +22,7 @@ class StretchToolbar : public QToolBar public: explicit StretchToolbar(QWidget *parent = nullptr); ~StretchToolbar(); + const MTFParam& params() const; public slots: void stretchImage(Image *img); void resetMTF();