Compare commits

..

10 Commits

Author SHA1 Message Date
nou 0ff2001797 Handle MAX_PATH every where 2025-01-26 16:00:00 +01:00
nou fc36024eee Remove deprecated QSqlQuery usage 2025-01-19 15:49:31 +01:00
nou 3cda53f26c Do not attempt open not existing file 2025-01-19 15:11:32 +01:00
nou 58d18cc28a Remove unused function 2025-01-19 15:11:14 +01:00
nou 2b96da60de Do not use global thread pool 2025-01-12 10:59:12 +01:00
nou 236f66ed2f Add solver profile to script engine 2024-12-27 23:20:51 +01:00
nou a86c100e69 Fix issue with Qt 6.8 2024-12-22 12:19:34 +01:00
nou 45ee9b7258 Fix half pixel offset and add filtering in sw rendering
Signed-off-by: Dušan Poizl <nou.spiro@gmail.com>
2024-12-05 16:02:46 +01:00
nou be1e65251d Support really big images 50000px 2024-11-30 22:03:58 +01:00
nou 9b7837e9fb SW rendering when image is too big for texture 2024-11-27 20:21:57 +01:00
18 changed files with 419 additions and 156 deletions
+30 -29
View File
@@ -15,32 +15,33 @@ bool Database::init(const QLatin1String &connectionName)
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir dir(path); QDir dir(path);
QSqlDatabase m_database = QSqlDatabase::addDatabase("QSQLITE", connectionName); QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE", connectionName);
if(!dir.mkpath(".")) if(!dir.mkpath("."))
return false; return false;
if(m_database.isValid()) if(database.isValid())
{ {
m_database.setDatabaseName(dir.absoluteFilePath("database2.db")); database.setDatabaseName(dir.absoluteFilePath("database2.db"));
if(m_database.open()) if(database.open())
{ {
m_database.exec("PRAGMA foreign_keys = ON"); QSqlQuery query(database);
query.exec("PRAGMA foreign_keys = ON");
int version = checkVersion(); int version = checkVersion();
if(version == 0) if(version == 0)
{ {
m_database.exec("PRAGMA user_version = 1"); query.exec("PRAGMA user_version = 1");
m_database.exec("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE)"); query.exec("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE)");
m_database.exec("CREATE TABLE IF NOT EXISTS fits_files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE, mtime DATETIME," query.exec("CREATE TABLE IF NOT EXISTS fits_files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE, mtime DATETIME,"
" minRa REAL, maxRa REAL, minDec REAL, maxDec REAL, crVal1 REAL, crVal2 REAL)"); " minRa REAL, maxRa REAL, minDec REAL, maxDec REAL, crVal1 REAL, crVal2 REAL)");
m_database.exec("CREATE TABLE IF NOT EXISTS fits_headers (id INTEGER PRIMARY KEY AUTOINCREMENT, id_file INTEGER," query.exec("CREATE TABLE IF NOT EXISTS fits_headers (id INTEGER PRIMARY KEY AUTOINCREMENT, id_file INTEGER,"
"key VARCHAR(81), value VARCHAR(81), comment VARCHAR(81), FOREIGN KEY(id_file) REFERENCES fits_files(id) ON DELETE CASCADE)"); "key VARCHAR(81), value VARCHAR(81), comment VARCHAR(81), FOREIGN KEY(id_file) REFERENCES fits_files(id) ON DELETE CASCADE)");
m_database.exec("CREATE INDEX IF NOT EXISTS key_value ON fits_headers(key, value)"); query.exec("CREATE INDEX IF NOT EXISTS key_value ON fits_headers(key, value)");
m_database.exec("CREATE INDEX IF NOT EXISTS id_file ON fits_headers(id_file)"); query.exec("CREATE INDEX IF NOT EXISTS id_file ON fits_headers(id_file)");
m_database.exec("CREATE INDEX IF NOT EXISTS minRa_idx ON fits_files(minRa)"); query.exec("CREATE INDEX IF NOT EXISTS minRa_idx ON fits_files(minRa)");
m_database.exec("CREATE INDEX IF NOT EXISTS maxRa_idx ON fits_files(maxRa)"); query.exec("CREATE INDEX IF NOT EXISTS maxRa_idx ON fits_files(maxRa)");
m_database.exec("CREATE INDEX IF NOT EXISTS minDec_idx ON fits_files(minDec)"); query.exec("CREATE INDEX IF NOT EXISTS minDec_idx ON fits_files(minDec)");
m_database.exec("CREATE INDEX IF NOT EXISTS maxDec_idx ON fits_files(maxDec)"); query.exec("CREATE INDEX IF NOT EXISTS maxDec_idx ON fits_files(maxDec)");
} }
else if(version > 1) else if(version > 1)
{ {
@@ -48,28 +49,28 @@ bool Database::init(const QLatin1String &connectionName)
return false; return false;
} }
QSqlError error = m_database.lastError(); QSqlError error = database.lastError();
if(error.type() == QSqlError::NoError) if(error.type() == QSqlError::NoError)
{ {
m_markQuery = QSqlQuery(m_database); m_markQuery = QSqlQuery(database);
m_markQuery.prepare("INSERT INTO files (file) VALUES (?)"); m_markQuery.prepare("INSERT INTO files (file) VALUES (?)");
m_unmarkQuery = QSqlQuery(m_database); m_unmarkQuery = QSqlQuery(database);
m_unmarkQuery.prepare("DELETE FROM files WHERE file = (?)"); m_unmarkQuery.prepare("DELETE FROM files WHERE file = (?)");
m_isMarkedQuery = QSqlQuery(m_database); m_isMarkedQuery = QSqlQuery(database);
m_isMarkedQuery.prepare("SELECT * FROM files WHERE file = (:name)"); m_isMarkedQuery.prepare("SELECT * FROM files WHERE file = (:name)");
m_insertFile = QSqlQuery(m_database); m_insertFile = QSqlQuery(database);
m_insertFile.prepare("INSERT INTO fits_files (file, mtime) VALUES (?, ?)"); m_insertFile.prepare("INSERT INTO fits_files (file, mtime) VALUES (?, ?)");
m_insertFileWcs = QSqlQuery(m_database); m_insertFileWcs = QSqlQuery(database);
m_insertFileWcs.prepare("INSERT INTO fits_files (file, mtime, minRa, maxRa, minDec, maxDec, crVal1, crVal2) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); m_insertFileWcs.prepare("INSERT INTO fits_files (file, mtime, minRa, maxRa, minDec, maxDec, crVal1, crVal2) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
m_insertFitsHeader = QSqlQuery(m_database); m_insertFitsHeader = QSqlQuery(database);
m_insertFitsHeader.prepare("INSERT INTO fits_headers (id_file, key, value, comment) VALUES (?, ?, ?, ?)"); m_insertFitsHeader.prepare("INSERT INTO fits_headers (id_file, key, value, comment) VALUES (?, ?, ?, ?)");
m_checkFile = QSqlQuery(m_database); m_checkFile = QSqlQuery(database);
m_checkFile.prepare("SELECT id,mtime FROM fits_files WHERE file=?"); m_checkFile.prepare("SELECT id,mtime FROM fits_files WHERE file=?");
m_headerKeywords = QSqlQuery(m_database); m_headerKeywords = QSqlQuery(database);
m_headerKeywords.prepare("SELECT DISTINCT key FROM fits_headers ORDER BY key"); m_headerKeywords.prepare("SELECT DISTINCT key FROM fits_headers ORDER BY key");
m_deleteFile = QSqlQuery(m_database); m_deleteFile = QSqlQuery(database);
m_deleteFile.prepare("DELETE FROM fits_files WHERE id=?"); m_deleteFile.prepare("DELETE FROM fits_files WHERE id=?");
return true; return true;
} }
@@ -130,7 +131,7 @@ QStringList Database::getMarkedFiles()
void Database::clearMarkedFiles() void Database::clearMarkedFiles()
{ {
QSqlDatabase::database().exec("DELETE FROM files"); QSqlQuery query("DELETE FROM files");
} }
bool Database::checkError(QSqlQuery &query) bool Database::checkError(QSqlQuery &query)
@@ -148,7 +149,7 @@ bool Database::checkError(QSqlQuery &query)
int Database::checkVersion() int Database::checkVersion()
{ {
QSqlDatabase db = QSqlDatabase::database(); QSqlDatabase db = QSqlDatabase::database();
QSqlQuery query = db.exec("PRAGMA user_version"); QSqlQuery query("PRAGMA user_version");
if(query.next()) if(query.next())
return query.value(0).toInt(); return query.value(0).toInt();
return -1; return -1;
@@ -194,10 +195,10 @@ void Database::reindex(QProgressDialog *progress)
QVariantList deleteids; QVariantList deleteids;
QSqlDatabase database = QSqlDatabase::database(); QSqlDatabase database = QSqlDatabase::database();
database.transaction(); database.transaction();
QSqlQuery size = database.exec("SELECT COUNT(*) FROM fits_files"); QSqlQuery size("SELECT COUNT(*) FROM fits_files", database);
size.next(); size.next();
progress->setMaximum(size.value(0).toInt()); progress->setMaximum(size.value(0).toInt());
QSqlQuery files = database.exec("SELECT id,file,mtime FROM fits_files"); QSqlQuery files("SELECT id,file,mtime FROM fits_files", database);
int i = 0; int i = 0;
while(files.next()) while(files.next())
{ {
+1 -1
View File
@@ -375,7 +375,7 @@ bool DataBaseView::exportCSV(const QString &path)
if(!csv.open(QIODevice::WriteOnly | QIODevice::Text)) if(!csv.open(QIODevice::WriteOnly | QIODevice::Text))
return false; return false;
QSqlQuery sql = m_model->query(); QSqlQuery sql(m_model->query().lastQuery());
int colCount = m_model->columnCount(); int colCount = m_model->columnCount();
QStringList header; QStringList header;
for(int i=0; i<colCount; i++) for(int i=0; i<colCount; i++)
-8
View File
@@ -51,14 +51,6 @@ FITSRecord::FITSRecord(const LibXISF::Property &property)
xisf = true; xisf = true;
} }
QByteArray FITSRecord::valueToByteArray() const
{
if(value.type() == QVariant::Bool)
return value.toBool() ? "T" : "F";
else
return value.toString().toLatin1();
}
ImageInfo::ImageInfo(QWidget *parent) : QTreeWidget(parent) ImageInfo::ImageInfo(QWidget *parent) : QTreeWidget(parent)
{ {
setColumnCount(3); setColumnCount(3);
-1
View File
@@ -19,7 +19,6 @@ struct FITSRecord
FITSRecord(const QByteArray &key, const QVariant &value, const QByteArray &comment); FITSRecord(const QByteArray &key, const QVariant &value, const QByteArray &comment);
FITSRecord(const LibXISF::FITSKeyword &record); FITSRecord(const LibXISF::FITSKeyword &record);
FITSRecord(const LibXISF::Property &property); FITSRecord(const LibXISF::Property &property);
QByteArray valueToByteArray() const;
}; };
class SkyPoint class SkyPoint
+26 -20
View File
@@ -22,13 +22,13 @@ Image::Image(const QString name, int number, ImageRingList *ringList) :
{ {
} }
void Image::load() void Image::load(QThreadPool *pool)
{ {
if(!m_rawImage && !m_loading) if(!m_rawImage && !m_loading)
{ {
m_loading = true; m_loading = true;
m_released = false; m_released = false;
QThreadPool::globalInstance()->start(new LoadRunable(m_name, this, m_ringList->analyzeLevel())); pool->start(new LoadRunable(m_name, this, m_ringList->analyzeLevel()));
} }
if(!m_loading && m_rawImage) if(!m_loading && m_rawImage)
emit pixmapLoaded(this); emit pixmapLoaded(this);
@@ -110,7 +110,10 @@ ImageRingList::ImageRingList(Database *database, const QStringList &nameFilter,
{ {
connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString))); connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
m_nameFilter.replaceInStrings(QRegularExpression("^"), "*."); m_nameFilter.replaceInStrings(QRegularExpression("^"), "*.");
m_loadPool = new QThreadPool(this);
m_loadPool->setThreadPriority(QThread::LowPriority);
m_thumbPool = new QThreadPool(this); m_thumbPool = new QThreadPool(this);
m_thumbPool->setThreadPriority(QThread::LowPriority);
m_slideShowTimer = new QTimer(this); m_slideShowTimer = new QTimer(this);
connect(m_slideShowTimer, &QTimer::timeout, this, static_cast<void (ImageRingList::*)()>(&ImageRingList::increment)); connect(m_slideShowTimer, &QTimer::timeout, this, static_cast<void (ImageRingList::*)()>(&ImageRingList::increment));
@@ -123,10 +126,10 @@ ImageRingList::ImageRingList(Database *database, const QStringList &nameFilter,
ImageRingList::~ImageRingList() ImageRingList::~ImageRingList()
{ {
QThreadPool::globalInstance()->clear(); m_loadPool->clear();
m_thumbPool->clear(); m_thumbPool->clear();
QThreadPool::globalInstance()->waitForDone(); m_loadPool->waitForDone();
m_thumbPool->waitForDone(); m_thumbPool->waitForDone();
} }
@@ -173,11 +176,14 @@ bool ImageRingList::setDir(const QString path, const QString &currentFile, bool
void ImageRingList::setFile(const QString &file) void ImageRingList::setFile(const QString &file)
{ {
QFileInfo info(file); if(!file.isEmpty())
if(info.isDir()) {
setDir(file, QString(), true); QFileInfo info(file);
else if(info.isDir())
setDir(info.absolutePath(), file); setDir(file, QString(), true);
else
setDir(info.absolutePath(), file);
}
} }
ImagePtr ImageRingList::currentImage() ImagePtr ImageRingList::currentImage()
@@ -199,9 +205,9 @@ void ImageRingList::increment()
(*m_firstImage)->release(); (*m_firstImage)->release();
m_firstImage = increment(m_firstImage); m_firstImage = increment(m_firstImage);
m_currImage = increment(m_currImage); m_currImage = increment(m_currImage);
(*m_currImage)->load(); (*m_currImage)->load(m_loadPool);
m_lastImage = increment(m_lastImage); m_lastImage = increment(m_lastImage);
(*m_lastImage)->load(); (*m_lastImage)->load(m_loadPool);
} }
} }
@@ -212,9 +218,9 @@ void ImageRingList::decrement()
(*m_lastImage)->release(); (*m_lastImage)->release();
m_firstImage = decrement(m_firstImage); m_firstImage = decrement(m_firstImage);
m_currImage = decrement(m_currImage); m_currImage = decrement(m_currImage);
(*m_currImage)->load(); (*m_currImage)->load(m_loadPool);
m_lastImage = decrement(m_lastImage); m_lastImage = decrement(m_lastImage);
(*m_firstImage)->load(); (*m_firstImage)->load(m_loadPool);
} }
} }
@@ -268,7 +274,7 @@ void ImageRingList::loadFile(int row)
if(m_images.empty()) if(m_images.empty())
return; return;
(*m_currImage)->load(); (*m_currImage)->load(m_loadPool);
m_width = DEFAULT_WIDTH<m_images.size()/2 ? DEFAULT_WIDTH : m_images.size()/2; m_width = DEFAULT_WIDTH<m_images.size()/2 ? DEFAULT_WIDTH : m_images.size()/2;
if(m_liveMode) if(m_liveMode)
@@ -277,9 +283,9 @@ void ImageRingList::loadFile(int row)
for(int i=0; i<m_width; i++) for(int i=0; i<m_width; i++)
{ {
m_firstImage = decrement(m_firstImage); m_firstImage = decrement(m_firstImage);
(*m_firstImage)->load(); (*m_firstImage)->load(m_loadPool);
m_lastImage = increment(m_lastImage); m_lastImage = increment(m_lastImage);
(*m_lastImage)->load(); (*m_lastImage)->load(m_loadPool);
} }
if(m_lastImage != m_firstImage) if(m_lastImage != m_firstImage)
{ {
@@ -403,9 +409,9 @@ void ImageRingList::setPreload(int width)
for(int i = newWidth - m_width; i>0; i--) for(int i = newWidth - m_width; i>0; i--)
{ {
m_firstImage = decrement(m_firstImage); m_firstImage = decrement(m_firstImage);
(*m_firstImage)->load(); (*m_firstImage)->load(m_loadPool);
m_lastImage = increment(m_lastImage); m_lastImage = increment(m_lastImage);
(*m_lastImage)->load(); (*m_lastImage)->load(m_loadPool);
} }
} }
if(newWidth < m_width) if(newWidth < m_width)
@@ -460,9 +466,9 @@ void ImageRingList::toggleSlideshow(bool start)
void ImageRingList::setFiles(const QStringList files, const QString &currentFile) void ImageRingList::setFiles(const QStringList files, const QString &currentFile)
{ {
QThreadPool::globalInstance()->clear(); m_loadPool->clear();
m_thumbPool->clear(); m_thumbPool->clear();
QThreadPool::globalInstance()->waitForDone(); m_loadPool->waitForDone();
m_thumbPool->waitForDone(); m_thumbPool->waitForDone();
beginResetModel(); beginResetModel();
m_images.clear(); m_images.clear();
+2 -1
View File
@@ -27,7 +27,7 @@ class Image : public QObject
ImageRingList *m_ringList; ImageRingList *m_ringList;
public: public:
explicit Image(const QString name, int number, ImageRingList *ringList); explicit Image(const QString name, int number, ImageRingList *ringList);
void load(); void load(QThreadPool *pool);
void loadThumbnail(QThreadPool *pool); void loadThumbnail(QThreadPool *pool);
void release(); void release();
QString name() const; QString name() const;
@@ -62,6 +62,7 @@ class ImageRingList : public QAbstractItemModel
QDir::SortFlag m_sort = QDir::Name; QDir::SortFlag m_sort = QDir::Name;
bool m_reversed = false; bool m_reversed = false;
AnalyzeLevel m_analyzeLevel; AnalyzeLevel m_analyzeLevel;
QThreadPool *m_loadPool;
QThreadPool *m_thumbPool; QThreadPool *m_thumbPool;
Database *m_database; Database *m_database;
QStringList m_nameFilter; QStringList m_nameFilter;
+208 -55
View File
@@ -10,6 +10,7 @@
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QPainter> #include <QPainter>
#include "imageringlist.h" #include "imageringlist.h"
#include <QFloat16>
int FILTERING = 1; int FILTERING = 1;
bool OpenGLES = false; bool OpenGLES = false;
@@ -110,16 +111,15 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
m_error.clear(); m_error.clear();
makeCurrent(); makeCurrent();
m_rawImage = image; m_rawImage = image;
if((int)image->width() > m_maxTextureSize || (int)image->height() > m_maxTextureSize)
{
uint32_t newW = std::min(image->width() * m_maxTextureSize / image->width(), image->width() * m_maxTextureSize / image->height());
uint32_t newH = std::min(image->height() * m_maxTextureSize / image->width(), image->height() * m_maxTextureSize / image->height());
m_rawImage->resize(newW, newH);
}
m_imgWidth = image->width(); m_imgWidth = image->width();
m_imgHeight = image->height(); m_imgHeight = image->height();
bool tooBig = false;
if((int)image->width() > m_maxTextureSize || (int)image->height() > m_maxTextureSize)
{
tooBig = true;
m_swPaint = true;
}
if(!m_image)return; if(!m_image)return;
@@ -133,21 +133,26 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
m_lut->setData(0, 0, 0, LUT_SIZE, LUT_SIZE, LUT_SIZE, 0, QOpenGLTexture::RGBA, QOpenGLTexture::RGBA, QOpenGLTexture::Float16, image->getLUT().data()); m_lut->setData(0, 0, 0, LUT_SIZE, LUT_SIZE, LUT_SIZE, 0, QOpenGLTexture::RGBA, QOpenGLTexture::RGBA, QOpenGLTexture::Float16, image->getLUT().data());
} }
QElapsedTimer timer; if(!tooBig)
timer.start(); {
m_image->destroy(); while(f->glGetError() != GL_NO_ERROR);
m_image->setAutoMipMapGenerationEnabled(false); QElapsedTimer timer;
m_image->setFormat(rawImageType.textureFormat); timer.start();
m_image->setSize(image->width(), image->height()); m_image->destroy();
m_image->setMipLevels([&](){ int c = 0; int s = std::min(m_imgWidth, m_imgHeight); while(s>>=1)c++; return c; }()); m_image->setAutoMipMapGenerationEnabled(false);
m_image->allocateStorage(); m_image->setFormat(rawImageType.textureFormat);
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); m_image->setSize(image->width(), image->height());
m_image->setWrapMode(QOpenGLTexture::ClampToEdge); m_image->setMipLevels([&](){ int c = 0; int s = std::min(m_imgWidth, m_imgHeight); while(s>>=1)c++; return c; }());
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data()); m_image->allocateStorage();
m_image->bind(); m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
f->glGenerateMipmap(GL_TEXTURE_2D); m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data());
qDebug() << "setImage" << timer.elapsed(); m_image->bind();
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
f->glGenerateMipmap(GL_TEXTURE_2D);
qDebug() << "setImage" << timer.elapsed();
m_swPaint = f->glGetError() != GL_NO_ERROR;
}
m_unit_scale[0] = 1.0f; m_unit_scale[0] = 1.0f;
m_unit_scale[1] = 0.0f; m_unit_scale[1] = 0.0f;
@@ -185,10 +190,10 @@ void ImageWidgetGL::zoom(int zoom, const QPointF &mousePos)
if(!mousePos.isNull()) if(!mousePos.isNull())
focus = mousePos; focus = mousePos;
if(width() > m_image->width() * m_scale) if(width() > m_imgWidth * m_scale)
m_dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f; m_dx = -width() * 0.5f + m_imgWidth * m_scale * 0.5f;
if(height() > m_image->height() * m_scale) if(height() > m_imgHeight * m_scale)
m_dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f; m_dy = -height() * 0.5f + m_imgHeight * m_scale * 0.5f;
float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop)); float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop));
float r = newScale / m_scale; float r = newScale / m_scale;
@@ -232,10 +237,10 @@ QVector2D ImageWidgetGL::getImagePixelCoord(const QVector2D &pos)
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
if(m_width > m_image->width()*m_scale) if(m_width > m_imgWidth * m_scale)
dx = -width()*0.5f + m_image->width()*m_scale*0.5f; dx = -width()*0.5f + m_imgWidth*m_scale * 0.5f;
if(m_height > m_image->height()*m_scale) if(m_height > m_imgHeight * m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f; dy = -height()*0.5f + m_imgHeight*m_scale * 0.5f;
QVector2D offset(dx, dy); QVector2D offset(dx, dy);
return (pos + offset) / m_scale; return (pos + offset) / m_scale;
@@ -341,17 +346,158 @@ void ImageWidgetGL::showThumbnail(bool enable)
setOffset(m_dx, m_dy); setOffset(m_dx, m_dy);
} }
void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scale, const MTFParam &mtfParams, QWidget *widget)
{
QPainter painter(widget);
int width = widget->width();
int height = widget->height();
QImage img(width, height, QImage::Format_RGB32);
img.fill(Qt::darkGray);
int64_t ox = dx;
int64_t oy = dy;
auto mtf = [&mtfParams](int i, float x)
{
x = (x - mtfParams.blackPoint[i]) / (mtfParams.whitePoint[i] - mtfParams.blackPoint[i]);
x = std::min(std::max(x, 0.0f), 1.0f);
return ((mtfParams.midPoint[i] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[i] - 1.0f) * x - mtfParams.midPoint[i]);
};
int imgWidth = rawImage->width();
int imgHeight = rawImage->height();
auto convert = [&](auto *src)
{
float s = 1.0f;
if constexpr(std::numeric_limits<std::remove_reference_t<decltype(*src)>>::is_integer)
s = (float)std::numeric_limits<std::remove_reference_t<decltype(*src)>>::max();
float iscale = 1.0f / scale;
float r[4];
float g[4];
float b[4];
for(int64_t y = std::max((int64_t)0, -oy); y < height; y++)
{
uint32_t *pixels = (uint32_t*)(img.scanLine(y));
float iptr;
float fy = std::modf((y + oy) * iscale, &iptr);
int64_t py = iptr;
int64_t w = py * rawImage->widthBytes();
int64_t w2 = w;
if(py+1 < imgHeight)w2 += rawImage->widthBytes();
if(py >= imgHeight)break;
for(int64_t x = std::max((int64_t)0, -ox); x < width; x++)
{
float fx = std::modf((x + ox) * iscale, &iptr);
int px = iptr;
int px2 = px + 1 < imgWidth ? px + 1 : px;
if(px >= imgWidth)break;
if(rawImage->channels() > 1)
{
r[0] = src[w + px * 4 + 0];
g[0] = src[w + px * 4 + 1];
b[0] = src[w + px * 4 + 2];
if(FILTERING)
{
r[1] = src[w + px2 * 4 + 0];
g[1] = src[w + px2 * 4 + 1];
b[1] = src[w + px2 * 4 + 2];
r[2] = src[w2 + px * 4 + 0];
g[2] = src[w2 + px * 4 + 1];
b[2] = src[w2 + px * 4 + 2];
r[3] = src[w2 + px2 * 4 + 0];
g[3] = src[w2 + px2 * 4 + 1];
b[3] = src[w2 + px2 * 4 + 2];
}
}
else
{
r[0] = src[w + px];
if(FILTERING)
{
r[2] = src[w2 + px];
r[1] = src[w + px2];
r[3] = src[w2 + px2];
}
}
uint32_t rgb = 0xff000000;
if(FILTERING)
{
if(rawImage->channels() > 1)
{
rgb |= (uint8_t)(mtf(0, ((r[3] * fx + r[2] * (1.0f - fx)) * fy + (r[1] * fx + r[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f) << 16;
rgb |= (uint8_t)(mtf(1, ((g[3] * fx + g[2] * (1.0f - fx)) * fy + (g[1] * fx + g[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f) << 8;
rgb |= (uint8_t)(mtf(1, ((b[3] * fx + b[2] * (1.0f - fx)) * fy + (b[1] * fx + b[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f);
}
else
{
uint32_t v = (uint8_t)(mtf(0, ((r[3] * fx + r[2] * (1.0f - fx)) * fy + (r[1] * fx + r[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f);
rgb = 0xff000000 | (v << 16) | (v << 8) | v;
}
}
else
{
if(rawImage->channels() > 1)
{
rgb |= (uint8_t)(mtf(0, r[0] / s) * 255.0f) << 16;
rgb |= (uint8_t)(mtf(1, g[0] / s) * 255.0f) << 8;
rgb |= (uint8_t)(mtf(1, b[0] / s) * 255.0f);
}
else
{
uint32_t v = (uint8_t)(mtf(0, r[0] / s) * 255.0f);
rgb = 0xff000000 | (v << 16) | (v << 8) | v;
}
}
pixels[x] = rgb;
}
}
};
if(rawImage)
{
switch(rawImage->type())
{
case RawImage::UINT8:
convert(static_cast<uint8_t*>(rawImage->data()));
break;
case RawImage::UINT16:
convert(static_cast<uint16_t*>(rawImage->data()));
break;
case RawImage::UINT32:
convert(static_cast<uint32_t*>(rawImage->data()));
break;
case RawImage::FLOAT16:
convert(static_cast<qfloat16*>(rawImage->data()));
break;
case RawImage::FLOAT32:
convert(static_cast<float*>(rawImage->data()));
break;
case RawImage::FLOAT64:
convert(static_cast<double*>(rawImage->data()));
break;
}
}
painter.drawImage(0, 0, img);
}
void ImageWidgetGL::paintGL() void ImageWidgetGL::paintGL()
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
if(m_width > m_image->width() * m_scale) if(m_width > m_imgWidth * m_scale)
dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f; dx = -width() * 0.5f + m_imgWidth * m_scale * 0.5f;
if(m_height > m_image->height() * m_scale) if(m_height > m_imgHeight * m_scale)
dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f; dy = -height() * 0.5f + m_imgHeight * m_scale * 0.5f;
QBrush highlight = style()->standardPalette().highlight(); QBrush highlight = style()->standardPalette().highlight();
f->glClear(GL_COLOR_BUFFER_BIT); f->glClear(GL_COLOR_BUFFER_BIT);
f->glBlendFunc(GL_ONE, GL_ZERO);
if(m_showThumbnails) if(m_showThumbnails)
{ {
m_vaoThumb->bind(); m_vaoThumb->bind();
@@ -425,31 +571,38 @@ void ImageWidgetGL::paintGL()
} }
else else
{ {
m_vao->bind(); if(m_swPaint)
debayer();
if(m_superpixel && m_debayerTex)
{ {
f->glActiveTexture(GL_TEXTURE0); swPaint(m_rawImage, dx, dy, m_scale, m_mtfParams, this);
f->glBindTexture(GL_TEXTURE_2D, m_debayerTex);
} }
else else
m_image->bind(0); {
m_vao->bind();
debayer();
m_program->bind(); if(m_superpixel && m_debayerTex)
m_program->setUniformValue("viewport", (float)width(), (float)height()); {
m_program->setUniformValue("offset", std::floor(dx), std::floor(dy)); f->glActiveTexture(GL_TEXTURE0);
m_program->setUniformValueArray("mtf_param", m_mtfParams.blackPoint, 3, 3); f->glBindTexture(GL_TEXTURE_2D, m_debayerTex);
m_program->setUniformValue("unit_scale", m_unit_scale[0], m_unit_scale[1]); }
m_program->setUniformValue("zoom", 1.0f/m_scale); else
m_program->setUniformValue("bw", m_bwImg && !m_superpixel); m_image->bind(0);
m_program->setUniformValue("false_color", m_falseColor && m_bwImg);
m_program->setUniformValue("invert", m_invert); m_program->bind();
m_program->setUniformValue("filtering", m_scale > 1.0f ? FILTERING : 1); m_program->setUniformValue("viewport", (float)width(), (float)height());
m_program->setUniformValue("lut_table", 2); m_program->setUniformValue("offset", std::floor(dx), std::floor(dy));
m_program->setUniformValue("srgb", m_srgb); m_program->setUniformValueArray("mtf_param", m_mtfParams.blackPoint, 3, 3);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); m_program->setUniformValue("unit_scale", m_unit_scale[0], m_unit_scale[1]);
m_vao->release(); m_program->setUniformValue("zoom", 1.0f/m_scale);
m_program->setUniformValue("bw", m_bwImg && !m_superpixel);
m_program->setUniformValue("false_color", m_falseColor && m_bwImg);
m_program->setUniformValue("invert", m_invert);
m_program->setUniformValue("filtering", m_scale > 1.0f ? FILTERING : 1);
m_program->setUniformValue("lut_table", 2);
m_program->setUniformValue("srgb", m_srgb);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_vao->release();
}
} }
} }
+1
View File
@@ -91,6 +91,7 @@ class ImageWidgetGL : public QOpenGLWidget, public ImageWidget
Database *m_database = nullptr; Database *m_database = nullptr;
QPointF m_lastPos; QPointF m_lastPos;
QString m_error; QString m_error;
bool m_swPaint = false;
public: public:
explicit ImageWidgetGL(Database *database, QWidget *parent = nullptr); explicit ImageWidgetGL(Database *database, QWidget *parent = nullptr);
~ImageWidgetGL() override; ~ImageWidgetGL() override;
+22 -5
View File
@@ -15,8 +15,23 @@
#include "starfit.h" #include "starfit.h"
#include <lcms2.h> #include <lcms2.h>
QString makeMaxPath(QString path)
{
#ifdef Q_OS_WIN64
if(!path.startsWith("\\\\?\\"))
{
QFileInfo info(path);
path = info.absoluteFilePath();
path = QDir::toNativeSeparators(path);
path.prepend("\\\\?\\");
qDebug() << path;
}
#endif
return path;
}
LoadRunable::LoadRunable(const QString &file, Image *receiver, AnalyzeLevel level, bool thumbnail) : LoadRunable::LoadRunable(const QString &file, Image *receiver, AnalyzeLevel level, bool thumbnail) :
m_file(file), m_file(makeMaxPath(file)),
m_receiver(receiver), m_receiver(receiver),
m_analyzeLevel(level), m_analyzeLevel(level),
m_thumbnail(thumbnail) m_thumbnail(thumbnail)
@@ -451,7 +466,8 @@ bool readFITSHeader(const QString &path, ImageInfoData &info)
{ {
fitsfile *fr; fitsfile *fr;
int status = 0; int status = 0;
fits_open_diskfile(&fr, path.toLocal8Bit().data(), READONLY, &status); QString path2 = makeMaxPath(path);
fits_open_diskfile(&fr, path2.toLocal8Bit().data(), READONLY, &status);
if(fr && status == 0) if(fr && status == 0)
{ {
@@ -463,10 +479,11 @@ bool readFITSHeader(const QString &path, ImageInfoData &info)
bool readXISFHeader(const QString &path, ImageInfoData &info) bool readXISFHeader(const QString &path, ImageInfoData &info)
{ {
QString path2 = makeMaxPath(path);
try try
{ {
LibXISF::XISFReader xisf; LibXISF::XISFReader xisf;
xisf.open(path.toLocal8Bit().data()); xisf.open(path2.toLocal8Bit().data());
const LibXISF::Image &image = xisf.getImage(0, false); const LibXISF::Image &image = xisf.getImage(0, false);
auto fitskeywords = image.fitsKeywords(); auto fitskeywords = image.fitsKeywords();
@@ -532,8 +549,8 @@ bool loadImage(const QString &path, ImageInfoData &info, std::shared_ptr<RawImag
} }
ConvertRunable::ConvertRunable(const QString &in, const QString &out, const QString &format, const ConvertParams &params, QSemaphore *semaphore) : ConvertRunable::ConvertRunable(const QString &in, const QString &out, const QString &format, const ConvertParams &params, QSemaphore *semaphore) :
m_infile(in), m_infile(makeMaxPath(in)),
m_outfile(out), m_outfile(makeMaxPath(out)),
m_format(format), m_format(format),
m_params(params), m_params(params),
m_semaphore(semaphore) m_semaphore(semaphore)
+1
View File
@@ -8,6 +8,7 @@
class RawImage; class RawImage;
QString makeMaxPath(QString path);
bool readFITSHeader(const QString &path, ImageInfoData &info); bool readFITSHeader(const QString &path, ImageInfoData &info);
bool readXISFHeader(const QString &path, ImageInfoData &info); bool readXISFHeader(const QString &path, ImageInfoData &info);
bool loadImage(const QString &path, ImageInfoData &info, std::shared_ptr<RawImage> &rawImage, bool planar = false); bool loadImage(const QString &path, ImageInfoData &info, std::shared_ptr<RawImage> &rawImage, bool planar = false);
+1 -1
View File
@@ -60,6 +60,6 @@ void MarkedFiles::clearSelected()
void MarkedFiles::clearAll() void MarkedFiles::clearAll()
{ {
QSqlDatabase db = QSqlDatabase::database(); QSqlDatabase db = QSqlDatabase::database();
db.exec("DELETE FROM files"); QSqlQuery("DELETE FROM files", db);
m_model->select(); m_model->select();
} }
+46 -28
View File
@@ -45,7 +45,7 @@ void RawImage::allocate(uint32_t w, uint32_t h, uint32_t ch, DataType type)
m_channels = ch; m_channels = ch;
m_ch = ch == 3 ? 4 : ch; m_ch = ch == 3 ? 4 : ch;
m_origType = m_type = type; m_origType = m_type = type;
m_pixels = std::make_unique<PixelType[]>(m_width * m_height * m_ch * typeSize(type)); m_pixels = std::make_unique<PixelType[]>((size_t)m_width * m_height * m_ch * typeSize(type));
} }
RawImage::RawImage() RawImage::RawImage()
@@ -60,7 +60,7 @@ RawImage::RawImage(uint32_t w, uint32_t h, uint32_t ch, DataType type)
RawImage::RawImage(const RawImage &d) RawImage::RawImage(const RawImage &d)
{ {
allocate(d.m_width, d.m_height, d.m_channels, d.m_type); allocate(d.m_width, d.m_height, d.m_channels, d.m_type);
std::memcpy(m_pixels.get(), d.m_pixels.get(), m_width * m_height * m_ch * typeSize(m_type)); std::memcpy(m_pixels.get(), d.m_pixels.get(), (size_t)m_width * m_height * m_ch * typeSize(m_type));
m_stats = d.m_stats; m_stats = d.m_stats;
} }
@@ -118,6 +118,24 @@ RawImage::RawImage(const QImage &img)
for(int i=0; i<img.height(); i++) for(int i=0; i<img.height(); i++)
std::memcpy(data(i), img.scanLine(i), img.width()*2); std::memcpy(data(i), img.scanLine(i), img.width()*2);
} }
else if(img.format() == QImage::Format_RGB32 || img.format() == QImage::Format_ARGB32)
{
allocate(img.width(), img.height(), 4, UINT8);
for(int i=0; i<img.height(); i++)
{
uint32_t *src = (uint32_t*)img.scanLine(i);
uint32_t *dst = (uint32_t*)data(i);
for(int o=0; o<img.width(); o++)
{
uint32_t p = src[o];
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
dst[o] = (p & 0xff000000) | (p >> 16 & 0xff) | (p & 0xff00) | (p << 16 & 0xff0000);
#else
dst[o] = (p >> 24) | (p << 8 & 0xffffff00);
#endif
}
}
}
else else
{ {
QImage tmp = img.convertToFormat(QImage::Format_RGBA8888); QImage tmp = img.convertToFormat(QImage::Format_RGBA8888);
@@ -294,9 +312,9 @@ uint32_t RawImage::channels() const
return m_channels; return m_channels;
} }
uint32_t RawImage::size() const uint64_t RawImage::size() const
{ {
return width()*height(); return (uint64_t)width()*height();
} }
RawImage::DataType RawImage::type() const RawImage::DataType RawImage::type() const
@@ -336,12 +354,12 @@ const void *RawImage::data() const
void *RawImage::data(uint32_t row, uint32_t col) void *RawImage::data(uint32_t row, uint32_t col)
{ {
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
const void *RawImage::data(uint32_t row, uint32_t col) const const void *RawImage::data(uint32_t row, uint32_t col) const
{ {
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
const void *RawImage::origData() const const void *RawImage::origData() const
@@ -356,12 +374,12 @@ const void *RawImage::origData(uint32_t row, uint32_t col) const
{ {
if(m_original) if(m_original)
{ {
col = col * m_origWidth / m_width; col = (uint64_t)col * m_origWidth / m_width;
row = row * m_origHeight / m_height; row = (uint64_t)row * m_origHeight / m_height;
return m_original.get() + (m_origWidth * row * m_ch + col * m_ch) * typeSize(m_origType); return m_original.get() + ((size_t)m_origWidth * row * m_ch + (size_t)col * m_ch) * typeSize(m_origType);
} }
else else
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
bool RawImage::planar() const bool RawImage::planar() const
@@ -381,12 +399,12 @@ void RawImage::convertToThumbnail()
auto loop = [&](F16 *out, auto *in, float scale) auto loop = [&](F16 *out, auto *in, float scale)
{ {
for(int i=0; i<THUMB_SIZE; i++) for(int64_t i=0; i<THUMB_SIZE; i++)
{ {
for(int o=0; o<THUMB_SIZE; o++) for(int64_t o=0; o<THUMB_SIZE; o++)
{ {
int idx = (i*THUMB_SIZE + o)*4; int64_t idx = (i*THUMB_SIZE + o)*4;
int idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch; int64_t idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch;
if(m_channels == 1) if(m_channels == 1)
{ {
@@ -442,21 +460,21 @@ void RawImage::convertToGLFormat()
} }
template<typename T, typename U> template<typename T, typename U>
void convertType2(uint32_t size, const T *src, U *dst) void convertType2(size_t size, const T *src, U *dst)
{ {
if constexpr((std::is_floating_point_v<T> || std::is_same_v<T, F16>) && (std::is_floating_point_v<U> || std::is_same_v<T, F16>)) if constexpr((std::is_floating_point_v<T> || std::is_same_v<T, F16>) && (std::is_floating_point_v<U> || std::is_same_v<T, F16>))
{ {
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i]; dst[i] = src[i];
} }
if constexpr(std::is_integral_v<T> && std::is_integral_v<U>) if constexpr(std::is_integral_v<T> && std::is_integral_v<U>)
{ {
if constexpr(sizeof(T) > sizeof(U)) if constexpr(sizeof(T) > sizeof(U))
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8); dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8);
else else
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = static_cast<U>(src[i]) << ((sizeof(U) - sizeof(T)) * 8); dst[i] = static_cast<U>(src[i]) << ((sizeof(U) - sizeof(T)) * 8);
} }
@@ -464,20 +482,20 @@ void convertType2(uint32_t size, const T *src, U *dst)
{ {
U max = std::numeric_limits<U>::max(); U max = std::numeric_limits<U>::max();
T scale = (T)(max); T scale = (T)(max);
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i] * scale; dst[i] = src[i] * scale;
} }
if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>)) if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>))
{ {
U scale = (U)(1.0 / (double)std::numeric_limits<T>::max()); U scale = (U)(1.0 / (double)std::numeric_limits<T>::max());
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = (U)src[i] * scale; dst[i] = (U)src[i] * scale;
} }
} }
template<typename T> template<typename T>
void convertType(uint32_t size, RawImage::DataType dstType, const T *src, void *dst) void convertType(size_t size, RawImage::DataType dstType, const T *src, void *dst)
{ {
switch(dstType) switch(dstType)
{ {
@@ -514,7 +532,7 @@ void RawImage::convertToType(DataType type)
allocate(m_width, m_height, m_channels, type); allocate(m_width, m_height, m_channels, type);
m_origType = origType; m_origType = origType;
uint32_t s = size() * m_ch; size_t s = size() * m_ch;
switch(m_origType) switch(m_origType)
{ {
case UINT8: case UINT8:
@@ -656,15 +674,15 @@ void boxResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t ol
float sx = (float)w / oldw; float sx = (float)w / oldw;
float sy = (float)h / oldh; float sy = (float)h / oldh;
for(uint32_t y = 0; y < h; y++)//iterate over destination Y for(uint64_t y = 0; y < h; y++)//iterate over destination Y
{ {
for(uint32_t x = 0; x < w; x++)//iterate over destination X for(uint64_t x = 0; x < w; x++)//iterate over destination X
{ {
U p[4] = {0.0f}; U p[4] = {0.0f};
uint32_t xx = x * oldw / w;//calculate source rect uint64_t xx = x * oldw / w;//calculate source rect
uint32_t yy = y * oldh / h; uint64_t yy = y * oldh / h;
uint32_t xe = std::min((x + 1) * oldw / w, oldw - 1); uint64_t xe = std::min((x + 1) * oldw / w, (uint64_t)oldw - 1);
uint32_t ye = std::min((y + 1) * oldh / h, oldh - 1); uint64_t ye = std::min((y + 1) * oldh / h, (uint64_t)oldh - 1);
for(uint32_t o = yy; o <= ye; o++)//iterate over source Y for(uint32_t o = yy; o <= ye; o++)//iterate over source Y
{ {
float cy = o * sy - y; float cy = o * sy - y;
+1 -1
View File
@@ -89,7 +89,7 @@ public:
uint32_t width() const; uint32_t width() const;
uint32_t height() const; uint32_t height() const;
uint32_t channels() const; uint32_t channels() const;
uint32_t size() const; uint64_t size() const;
DataType type() const; DataType type() const;
uint32_t norm() const; uint32_t norm() const;
uint32_t widthBytes() const; uint32_t widthBytes() const;
+62 -6
View File
@@ -3,6 +3,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDebug> #include <QDebug>
#include <QInputDialog> #include <QInputDialog>
#include <QJsonValue>
#include "loadrunable.h" #include "loadrunable.h"
#include "rawimage.h" #include "rawimage.h"
#include "loadrunable.h" #include "loadrunable.h"
@@ -28,6 +29,7 @@ ScriptEngine::ScriptEngine(BatchProcessing *parent)
_jsEngine->globalObject().setProperty("FITSRecordModify", fitsRecordObject); _jsEngine->globalObject().setProperty("FITSRecordModify", fitsRecordObject);
_database->init(QLatin1String("scriptengine")); _database->init(QLatin1String("scriptengine"));
_semaphore.release(_pool->maxThreadCount()); _semaphore.release(_pool->maxThreadCount());
_pool->setThreadPriority(QThread::LowPriority);
#ifdef PLATESOLVER #ifdef PLATESOLVER
_solver = new Solver(this); _solver = new Solver(this);
@@ -162,6 +164,58 @@ bool ScriptEngine::convert(File *file, QString &outpath, const QString &format,
} }
#ifdef PLATESOLVER #ifdef PLATESOLVER
void ScriptEngine::setSolverProfile(int index)
{
if(_solver && index >= SSolver::Parameters::DEFAULT && index < SSolver::Parameters::BIG_STARS)
{
_solver->setParameters((SSolver::Parameters::ParametersProfile)index);
}
}
void ScriptEngine::setSolverProfile(const QVariantMap &profile)
{
if(_solver)
{
SSolver::Parameters params = SSolver::Parameters::convertFromMap(profile);
_solver->setParameters(params);
}
}
QJSValue ScriptEngine::getSolverProfile() const
{
if(_solver)
{
QMap<QString, QVariant> params = SSolver::Parameters::convertToMap(_solver->getProfile());
QJSValue ret = _jsEngine->newObject();
for(auto i = params.begin(); i != params.end(); i++)
{
switch(i.value().metaType().id())
{
case QMetaType::Int:
ret.setProperty(i.key(), i.value().toInt());
break;
case QMetaType::Double:
ret.setProperty(i.key(), i.value().toDouble());
break;
case QMetaType::Bool:
ret.setProperty(i.key(), i.value().toBool());
break;
case QMetaType::QString:
ret.setProperty(i.key(), i.value().toString());
break;
default:
qWarning() << "unhandled metatype" << i.key() << i.value();
break;
}
}
return ret;
}
else
{
return QJSValue();
}
}
void ScriptEngine::setStartingSolution(const QJSValue &solution) void ScriptEngine::setStartingSolution(const QJSValue &solution)
{ {
if(solution.isObject()) if(solution.isObject())
@@ -465,7 +519,8 @@ bool File::modifyFITSRecords(const FITSRecordModify *modify)
{ {
fitsfile *file; fitsfile *file;
int status = 0; int status = 0;
fits_open_diskfile(&file, _path.toLocal8Bit().data(), READWRITE, &status); QString path = makeMaxPath(_path);
fits_open_diskfile(&file, path.toLocal8Bit().data(), READWRITE, &status);
int num = 0; int num = 0;
fits_get_num_hdus(file, &num, &status); fits_get_num_hdus(file, &num, &status);
if(status) if(status)
@@ -588,9 +643,10 @@ bool File::modifyFITSRecords(const FITSRecordModify *modify)
try try
{ {
LibXISF::XISFModify modifyXISF; LibXISF::XISFModify modifyXISF;
modifyXISF.open(_path.toLocal8Bit().data()); QString in = makeMaxPath(absoluteFilePath());
QFileInfo in(_path); QString out = in + "~";
QFileInfo out(_path + "~"); modifyXISF.open(in.toLocal8Bit().data());
qDebug() << "modify" << in << out;
for(auto &remove : modify->_remove) for(auto &remove : modify->_remove)
modifyXISF.removeFITSKeyword(0, remove.toStdString()); modifyXISF.removeFITSKeyword(0, remove.toStdString());
@@ -601,9 +657,9 @@ bool File::modifyFITSRecords(const FITSRecordModify *modify)
for(auto &record : modify->_add) for(auto &record : modify->_add)
modifyXISF.addFITSKeyword(0, {record.key.toStdString(), record.value.toString().toStdString(), record.comment.toStdString()}); modifyXISF.addFITSKeyword(0, {record.key.toStdString(), record.value.toString().toStdString(), record.comment.toStdString()});
modifyXISF.save(out.absoluteFilePath().toLocal8Bit().toStdString()); modifyXISF.save(out.toLocal8Bit().toStdString());
modifyXISF.close(); modifyXISF.close();
std::filesystem::rename(out.filesystemAbsoluteFilePath(), in.filesystemAbsoluteFilePath()); std::filesystem::rename(out.toLocal8Bit().toStdString(), in.toLocal8Bit().toStdString());
return true; return true;
} }
catch(std::filesystem::filesystem_error &err) catch(std::filesystem::filesystem_error &err)
+3
View File
@@ -49,6 +49,9 @@ public:
Q_INVOKABLE QJSValue getItem(const QStringList &items, const QString &label = "", int current = 0) const; Q_INVOKABLE QJSValue getItem(const QStringList &items, const QString &label = "", int current = 0) const;
bool convert(File *file, QString &outpath, const QString &format, const QVariantMap &params, bool async); bool convert(File *file, QString &outpath, const QString &format, const QVariantMap &params, bool async);
#ifdef PLATESOLVER #ifdef PLATESOLVER
Q_INVOKABLE void setSolverProfile(int index);
Q_INVOKABLE void setSolverProfile(const QVariantMap &profile);
Q_INVOKABLE QJSValue getSolverProfile() const;
Q_INVOKABLE void setStartingSolution(const QJSValue &solution = QJSValue()); Q_INVOKABLE void setStartingSolution(const QJSValue &solution = QJSValue());
QJSValue solveImage(File *file, bool updateHeader); QJSValue solveImage(File *file, bool updateHeader);
QJSValue extractStars(File *file, bool hfr); QJSValue extractStars(File *file, bool hfr);
+5
View File
@@ -205,6 +205,11 @@ void Solver::setParameters(const Parameters &parameters)
_solver->setParameters(profile); _solver->setParameters(profile);
} }
Parameters Solver::getProfile() const
{
return _solver->getCurrentParameters();
}
void Solver::setSearchScale(double fovLow, double fowHigh, SSolver::ScaleUnits units) void Solver::setSearchScale(double fovLow, double fowHigh, SSolver::ScaleUnits units)
{ {
_solver->setSearchScale(fovLow, fowHigh, units); _solver->setSearchScale(fovLow, fowHigh, units);
+1
View File
@@ -34,6 +34,7 @@ public:
bool updateHeader(QString &error); bool updateHeader(QString &error);
void setParameters(SSolver::Parameters::ParametersProfile profile); void setParameters(SSolver::Parameters::ParametersProfile profile);
void setParameters(const SSolver::Parameters &parameters); void setParameters(const SSolver::Parameters &parameters);
SSolver::Parameters getProfile() const;
void setSearchScale(double fovLow, double fowHigh, ScaleUnits units); void setSearchScale(double fovLow, double fowHigh, ScaleUnits units);
void setSearchPosition(double ra, double dec); void setSearchPosition(double ra, double dec);
void clearStartingPositionAndScale(); void clearStartingPositionAndScale();
+9
View File
@@ -57,6 +57,15 @@
</screenshots> </screenshots>
<content_rating type="oars-1.1"/> <content_rating type="oars-1.1"/>
<releases> <releases>
<release version="20250126" date="2025-01-26">
<description>
<ul>
<li>Support for really big images +50000px</li>
<li>Fix handling of MAX_PATH on Windows</li>
<li>Add setting solver profile in scripts</li>
</ul>
</description>
</release>
<release version="20241116" date="2024-11-16"> <release version="20241116" date="2024-11-16">
<description> <description>
<ul> <ul>