Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ff2001797 | |||
| fc36024eee | |||
| 3cda53f26c | |||
| 58d18cc28a | |||
| 2b96da60de | |||
| 236f66ed2f | |||
| a86c100e69 | |||
| 45ee9b7258 | |||
| be1e65251d | |||
| 9b7837e9fb | |||
| 4afa940886 | |||
| d1344d2dc8 | |||
| 24eea573e6 | |||
| 8f7f527732 | |||
| 3635ac00cb | |||
| eba9110933 | |||
| 464207beb1 | |||
| 4aeff61c44 | |||
| 790c836bbd | |||
| 62616898ed | |||
| e216af6a6d | |||
| e0d6f417a0 | |||
| 3c5fef988e |
+17
-12
@@ -81,6 +81,23 @@ if(COLOR_MANAGMENT)
|
|||||||
target_compile_definitions(tenmon PRIVATE "COLOR_MANAGMENT")
|
target_compile_definitions(tenmon PRIVATE "COLOR_MANAGMENT")
|
||||||
endif(COLOR_MANAGMENT)
|
endif(COLOR_MANAGMENT)
|
||||||
|
|
||||||
|
find_path(STELLARSOLVER_INCLUDE stellarsolver.h PATH_SUFFIXES libstellarsolver)
|
||||||
|
if(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
|
||||||
|
target_include_directories(tenmon PRIVATE ${STELLARSOLVER_INCLUDE})
|
||||||
|
if(MXE)
|
||||||
|
target_link_libraries(tenmon PRIVATE ${STELLARSOLVER_LIB} ${GSL_LIB} ${GSLCBLAS_LIB} boost_regex-mt-x64)
|
||||||
|
else(MXE)
|
||||||
|
target_link_libraries(tenmon PRIVATE ${STELLARSOLVER_LIB})
|
||||||
|
endif(MXE)
|
||||||
|
target_compile_definitions(tenmon PRIVATE "PLATESOLVER")
|
||||||
|
target_sources(tenmon PRIVATE
|
||||||
|
solver.cpp solver.h
|
||||||
|
platesolving.cpp platesolving.h platesolving.ui
|
||||||
|
platesolvingsettings.cpp platesolvingsettings.h platesolvingsettings.ui
|
||||||
|
)
|
||||||
|
message(STATUS "Found stellarsolver ${STELLARSOLVER_INCLUDE} ${STELLARSOLVER_LIB}")
|
||||||
|
endif(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
|
||||||
|
|
||||||
target_link_libraries(tenmon PRIVATE Qt6::Widgets Qt6::Sql Qt6::OpenGLWidgets Qt6::Qml ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB} ${WCS_LIB} ${LCMS2_LIB} XISF)
|
target_link_libraries(tenmon PRIVATE Qt6::Widgets Qt6::Sql Qt6::OpenGLWidgets Qt6::Qml ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB} ${WCS_LIB} ${LCMS2_LIB} XISF)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(tenmon PRIVATE Qt6::DBus "-framework CoreFoundation")
|
target_link_libraries(tenmon PRIVATE Qt6::DBus "-framework CoreFoundation")
|
||||||
@@ -93,18 +110,6 @@ if(LIBRAW_STATIC)
|
|||||||
target_link_libraries(tenmon PRIVATE jasper)
|
target_link_libraries(tenmon PRIVATE jasper)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_path(STELLARSOLVER_INCLUDE stellarsolver.h PATH_SUFFIXES libstellarsolver)
|
|
||||||
if(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
|
|
||||||
target_include_directories(tenmon PRIVATE ${STELLARSOLVER_INCLUDE})
|
|
||||||
target_link_libraries(tenmon PRIVATE ${STELLARSOLVER_LIB})
|
|
||||||
target_compile_definitions(tenmon PRIVATE "PLATESOLVER")
|
|
||||||
target_sources(tenmon PRIVATE
|
|
||||||
solver.cpp solver.h
|
|
||||||
platesolving.cpp platesolving.h platesolving.ui
|
|
||||||
platesolvingsettings.cpp platesolvingsettings.h platesolvingsettings.ui
|
|
||||||
)
|
|
||||||
endif(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
|
|
||||||
|
|
||||||
option(FLATPAK "Flatpak build" OFF)
|
option(FLATPAK "Flatpak build" OFF)
|
||||||
if(FLATPAK)
|
if(FLATPAK)
|
||||||
target_compile_definitions(tenmon PRIVATE FLATPAK)
|
target_compile_definitions(tenmon PRIVATE FLATPAK)
|
||||||
|
|||||||
+1
-1
@@ -202,7 +202,7 @@ In <b>files</b> array there are instances of type <b>File</b> objects that have
|
|||||||
This path can be relative or absolute. In case that <i>newpath</i> parameter is relative path then it "Output directory" from GUI windows is used as base directory. Parameter <i>newpath</i> can be absolute path.
|
This path can be relative or absolute. In case that <i>newpath</i> parameter is relative path then it "Output directory" from GUI windows is used as base directory. Parameter <i>newpath</i> can be absolute path.
|
||||||
File is then moved to this path.</li>
|
File is then moved to this path.</li>
|
||||||
<li><b>convert(outpath, format, params)</b> convert image file from any format that program is able to open into FITS, XISF, JPEG, PNG, BMP.
|
<li><b>convert(outpath, format, params)</b> convert image file from any format that program is able to open into FITS, XISF, JPEG, PNG, BMP.
|
||||||
Parameters are: <i>outputpath</i> path where converted image will be saved. It automatically replace suffix according to format. <i>format</i> one of "FITS" "XISF", "JPG", "PNG" or "BMP". <i>params</i> object with attributes "compressionType" and "compressionLevel".
|
Parameters are: <i>outputpath</i> path where converted image will be saved. It automatically replace suffix according to format. <i>format</i> one of "FITS" "XISF", "JPG", "PNG", "TIFF" or "BMP". <i>params</i> object with attributes "compressionType" and "compressionLevel".
|
||||||
Valid values for compressionType are be "gzip" or "rice" when converting to FITS. When converting to XISF compressionType can be "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
Valid values for compressionType are be "gzip" or "rice" when converting to FITS. When converting to XISF compressionType can be "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
||||||
It is recommended to use "+sh" variants of compression.
|
It is recommended to use "+sh" variants of compression.
|
||||||
XISF format also accept "compressionLevel" in range 0-100 where zero is fastest compression and 100 slowest. If you omit this attribute or set it to -1 then default compression level will be used.
|
XISF format also accept "compressionLevel" in range 0-100 where zero is fastest compression and 100 slowest. If you omit this attribute or set it to -1 then default compression level will be used.
|
||||||
|
|||||||
+1
-1
@@ -161,7 +161,7 @@ le fichier <i>C:/images/lights/red/M42_001.fits</i>, alors cette méthode renver
|
|||||||
Ce chemin peut être relatif ou absolu. Dans le cas où le paramètre <i>newpath</i> est un chemin relatif, le "répertoire de sortie" des fenêtres de l'interface graphique est utilisé comme répertoire de base. Le paramètre <i>newpath</i> peut être un chemin absolu.
|
Ce chemin peut être relatif ou absolu. Dans le cas où le paramètre <i>newpath</i> est un chemin relatif, le "répertoire de sortie" des fenêtres de l'interface graphique est utilisé comme répertoire de base. Le paramètre <i>newpath</i> peut être un chemin absolu.
|
||||||
Le fichier est ensuite déplacé vers ce chemin.</li>
|
Le fichier est ensuite déplacé vers ce chemin.</li>
|
||||||
<li><b>convert(outpath, format, params)</b> Convertir un fichier image à partir de n'importe quel format que le programme peut ouvrir en FITS, XISF, JPEG, PNG, BMP.
|
<li><b>convert(outpath, format, params)</b> Convertir un fichier image à partir de n'importe quel format que le programme peut ouvrir en FITS, XISF, JPEG, PNG, BMP.
|
||||||
Les paramètres sont : <i>outputpath</i> chemin où l'image convertie sera enregistrée. Il remplace automatiquement le suffixe en fonction du format. <i>format</i> l'un des éléments suivants : "FITS", "XISF", "JPG", "PNG" ou "BMP". <i>params</i> objet avec les attributs "compressionType" et "compressionLevel".
|
Les paramètres sont : <i>outputpath</i> chemin où l'image convertie sera enregistrée. Il remplace automatiquement le suffixe en fonction du format. <i>format</i> l'un des éléments suivants : "FITS", "XISF", "JPG", "PNG", "TIFF" ou "BMP". <i>params</i> objet avec les attributs "compressionType" et "compressionLevel".
|
||||||
Les valeurs valides pour compressionType sont "gzip" ou "rice" lors de la conversion en FITS. Lors de la conversion en XISF, compressionType peut être "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
Les valeurs valides pour compressionType sont "gzip" ou "rice" lors de la conversion en FITS. Lors de la conversion en XISF, compressionType peut être "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
||||||
Il est recommandé d'utiliser les variantes de compression "+sh".
|
Il est recommandé d'utiliser les variantes de compression "+sh".
|
||||||
Le format XISF accepte également les "compressionLevel" dans la plage 0-100, où zéro est la compression la plus rapide et 100 la plus lente. Si vous omettez cet attribut ou le définissez sur -1, le niveau de compression par défaut sera utilisé.
|
Le format XISF accepte également les "compressionLevel" dans la plage 0-100, où zéro est la compression la plus rapide et 100 la plus lente. Si vous omettez cet attribut ou le définissez sur -1, le niveau de compression par défaut sera utilisé.
|
||||||
|
|||||||
+1
-1
@@ -151,7 +151,7 @@ V poli <b>files</b> sú inštancie objektu typu <b>File</b> ktorý ma nasledovn
|
|||||||
This path can be relative or absolute. In case that <i>newpath</i> parameter is relative path then it "Output directory" from GUI windows is used as base directory. Parameter <i>newpath</i> can be absolute path.
|
This path can be relative or absolute. In case that <i>newpath</i> parameter is relative path then it "Output directory" from GUI windows is used as base directory. Parameter <i>newpath</i> can be absolute path.
|
||||||
File is then moved to this path.</li>
|
File is then moved to this path.</li>
|
||||||
<li><b>convert(outpath, format, params)</b> convert image file from any format that program is able to open into FITS, XISF, JPEG, PNG, BMP.
|
<li><b>convert(outpath, format, params)</b> convert image file from any format that program is able to open into FITS, XISF, JPEG, PNG, BMP.
|
||||||
Parameters are: <i>outputpath</i> path where converted image will be saved. It automatically replace suffix according to format. <i>format</i> one of "FITS" "XISF", "JPG", "PNG" or "BMP". <i>params</i> object with attributes "compressionType" and "compressionLevel".
|
Parameters are: <i>outputpath</i> path where converted image will be saved. It automatically replace suffix according to format. <i>format</i> one of "FITS" "XISF", "JPG", "PNG", "TIFF" or "BMP". <i>params</i> object with attributes "compressionType" and "compressionLevel".
|
||||||
Valid values for compressionType are be "gzip" or "rice" when converting to FITS. When converting to XISF compressionType can be "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
Valid values for compressionType are be "gzip" or "rice" when converting to FITS. When converting to XISF compressionType can be "zlib", "lz4", "lz4hc", "zstd", "zlib+sh", "lz4+sh", "lz4hc+sh", "zstd+sh".
|
||||||
It is recommended to use "+sh" variants of compression.
|
It is recommended to use "+sh" variants of compression.
|
||||||
XISF format also accept "compressionLevel" in range 0-100 where zero is fastest compression and 100 slowest. If you omit this attribute or set it to -1 then default compression level will be used.
|
XISF format also accept "compressionLevel" in range 0-100 where zero is fastest compression and 100 slowest. If you omit this attribute or set it to -1 then default compression level will be used.
|
||||||
|
|||||||
+30
-29
@@ -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
@@ -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++)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+21
-15
@@ -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 ¤tFile, bool
|
|||||||
|
|
||||||
void ImageRingList::setFile(const QString &file)
|
void ImageRingList::setFile(const QString &file)
|
||||||
{
|
{
|
||||||
|
if(!file.isEmpty())
|
||||||
|
{
|
||||||
QFileInfo info(file);
|
QFileInfo info(file);
|
||||||
if(info.isDir())
|
if(info.isDir())
|
||||||
setDir(file, QString(), true);
|
setDir(file, QString(), true);
|
||||||
else
|
else
|
||||||
setDir(info.absolutePath(), file);
|
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 ¤tFile)
|
void ImageRingList::setFiles(const QStringList files, const QString ¤tFile)
|
||||||
{
|
{
|
||||||
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
@@ -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;
|
||||||
|
|||||||
+172
-19
@@ -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,6 +133,9 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!tooBig)
|
||||||
|
{
|
||||||
|
while(f->glGetError() != GL_NO_ERROR);
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
m_image->destroy();
|
m_image->destroy();
|
||||||
@@ -148,6 +151,8 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
|
|||||||
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
f->glGenerateMipmap(GL_TEXTURE_2D);
|
f->glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
qDebug() << "setImage" << timer.elapsed();
|
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();
|
||||||
@@ -424,6 +570,12 @@ void ImageWidgetGL::paintGL()
|
|||||||
painter.drawText(0, 0, width(), height(), Qt::AlignCenter | Qt::AlignHCenter, m_error);
|
painter.drawText(0, 0, width(), height(), Qt::AlignCenter | Qt::AlignHCenter, m_error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if(m_swPaint)
|
||||||
|
{
|
||||||
|
swPaint(m_rawImage, dx, dy, m_scale, m_mtfParams, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
m_vao->bind();
|
m_vao->bind();
|
||||||
debayer();
|
debayer();
|
||||||
@@ -451,6 +603,7 @@ void ImageWidgetGL::paintGL()
|
|||||||
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
m_vao->release();
|
m_vao->release();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+34
-7
@@ -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 ¶ms, QSemaphore *semaphore) :
|
ConvertRunable::ConvertRunable(const QString &in, const QString &out, const QString &format, const ConvertParams ¶ms, 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)
|
||||||
@@ -709,6 +726,7 @@ void ConvertRunable::run()
|
|||||||
{
|
{
|
||||||
QImage::Format format = QImage::Format_Invalid;
|
QImage::Format format = QImage::Format_Invalid;
|
||||||
int width = rawimage->widthBytes();
|
int width = rawimage->widthBytes();
|
||||||
|
|
||||||
switch(rawimage->type())
|
switch(rawimage->type())
|
||||||
{
|
{
|
||||||
case RawImage::UINT8:
|
case RawImage::UINT8:
|
||||||
@@ -722,9 +740,18 @@ void ConvertRunable::run()
|
|||||||
else if(rawimage->channels() == 4)format = QImage::Format_RGBA64;
|
else if(rawimage->channels() == 4)format = QImage::Format_RGBA64;
|
||||||
width *= 2;
|
width *= 2;
|
||||||
break;
|
break;
|
||||||
default:
|
case RawImage::FLOAT16:
|
||||||
return;
|
case RawImage::FLOAT32:
|
||||||
|
case RawImage::FLOAT64:
|
||||||
|
case RawImage::UINT32:
|
||||||
|
rawimage->convertToType(RawImage::UINT16);
|
||||||
|
if(rawimage->channels() == 1)format = QImage::Format_Grayscale16;
|
||||||
|
else if(rawimage->channels() == 3)format = QImage::Format_RGBX64;
|
||||||
|
else if(rawimage->channels() == 4)format = QImage::Format_RGBA64;
|
||||||
|
width *= 2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(format == QImage::Format_Invalid)return;
|
if(format == QImage::Format_Invalid)return;
|
||||||
|
|
||||||
QImage qimage(rawimage->width(), rawimage->height(), format);
|
QImage qimage(rawimage->width(), rawimage->height(), format);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
+41
-2
@@ -64,7 +64,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
|||||||
}
|
}
|
||||||
_openFilter.append("*.fit *.fits *.fts *.fz *.xisf *.cr2 *.cr3 *.nef *.dng)");
|
_openFilter.append("*.fit *.fits *.fts *.fz *.xisf *.cr2 *.cr3 *.nef *.dng)");
|
||||||
_openFilter.append(tr(";;All files (*)"));
|
_openFilter.append(tr(";;All files (*)"));
|
||||||
nameFilter.append({"fit", "fits", "xisf", "cr2", "cr3", "nef", "dng"});
|
nameFilter.append({"fit", "fits", "fts", "fz", "xisf", "cr2", "cr3", "nef", "dng"});
|
||||||
QImageReader::setAllocationLimit(0);
|
QImageReader::setAllocationLimit(0);
|
||||||
|
|
||||||
m_info = new ImageInfo(this);
|
m_info = new ImageInfo(this);
|
||||||
@@ -407,6 +407,9 @@ void MainWindow::copyOrMove(bool copy, const QString &dest)
|
|||||||
if(!dest.isEmpty() && dir.exists())
|
if(!dest.isEmpty() && dir.exists())
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int missing = 0;
|
||||||
|
bool overwriteAll = false;
|
||||||
|
bool skipAll = false;
|
||||||
QStringList files = m_database->getMarkedFiles();
|
QStringList files = m_database->getMarkedFiles();
|
||||||
QProgressDialog progress(copy ? tr("Copying") : tr("Moving"), tr("Cancel"), 0, files.size(), this);
|
QProgressDialog progress(copy ? tr("Copying") : tr("Moving"), tr("Cancel"), 0, files.size(), this);
|
||||||
progress.setWindowModality(Qt::WindowModal);
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
@@ -418,8 +421,42 @@ void MainWindow::copyOrMove(bool copy, const QString &dest)
|
|||||||
QFile srcFile(file);
|
QFile srcFile(file);
|
||||||
QFile dstFile(dir.absoluteFilePath(info.fileName()));
|
QFile dstFile(dir.absoluteFilePath(info.fileName()));
|
||||||
|
|
||||||
if(dstFile.exists())
|
if(!srcFile.exists())
|
||||||
|
{
|
||||||
|
missing++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dstFile.exists())
|
||||||
|
{
|
||||||
|
if(skipAll)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(overwriteAll)
|
||||||
|
{
|
||||||
|
dstFile.remove();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton button = QMessageBox::question(this, tr("Overwrite file?"), tr("Destination file %1 already exists. Overwrite?").arg(dstFile.fileName()),
|
||||||
|
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll);
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case QMessageBox::YesToAll:
|
||||||
|
overwriteAll = true;
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
dstFile.remove();
|
||||||
|
break;
|
||||||
|
case QMessageBox::NoToAll:
|
||||||
|
skipAll = true;
|
||||||
|
case QMessageBox::No:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(progress.wasCanceled())
|
if(progress.wasCanceled())
|
||||||
return;
|
return;
|
||||||
@@ -458,6 +495,8 @@ void MainWindow::copyOrMove(bool copy, const QString &dest)
|
|||||||
progress.setValue(i++);
|
progress.setValue(i++);
|
||||||
}
|
}
|
||||||
m_database->clearMarkedFiles();
|
m_database->clearMarkedFiles();
|
||||||
|
if(missing)
|
||||||
|
QMessageBox::information(this, tr("Missing marked files"), tr("%1 marked files were missing. They were skipped.").arg(missing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,4 +198,5 @@ void PlateSolving::settings()
|
|||||||
{
|
{
|
||||||
PlateSolvingSettings settings(this);
|
PlateSolvingSettings settings(this);
|
||||||
settings.exec();
|
settings.exec();
|
||||||
|
_solver->setIndexFolder(settings.indexDirectory());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ void PlateSolvingSettings::checkIndexFiles()
|
|||||||
checkScale(_ui->scale19, 19);
|
checkScale(_ui->scale19, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PlateSolvingSettings::indexDirectory() const
|
||||||
|
{
|
||||||
|
return _ui->indexPaths->currentText();
|
||||||
|
}
|
||||||
|
|
||||||
void PlateSolvingSettings::progress(int percent, int files)
|
void PlateSolvingSettings::progress(int percent, int files)
|
||||||
{
|
{
|
||||||
_ui->filesRemaining->setText(tr("%1 files").arg(files));
|
_ui->filesRemaining->setText(tr("%1 files").arg(files));
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
explicit PlateSolvingSettings(QWidget *parent = nullptr);
|
explicit PlateSolvingSettings(QWidget *parent = nullptr);
|
||||||
~PlateSolvingSettings();
|
~PlateSolvingSettings();
|
||||||
void checkIndexFiles();
|
void checkIndexFiles();
|
||||||
|
QString indexDirectory() const;
|
||||||
protected slots:
|
protected slots:
|
||||||
void progress(int percent, int files);
|
void progress(int percent, int files);
|
||||||
private:
|
private:
|
||||||
|
|||||||
+141
-99
@@ -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);
|
||||||
@@ -279,46 +297,6 @@ void RawImage::calcStats()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawImage::rect(int &x, int &y, int w, int h, std::vector<double> &r) const
|
|
||||||
{
|
|
||||||
/*r.resize(w*h);
|
|
||||||
x -= w/2;
|
|
||||||
y -= h/2;
|
|
||||||
if(x<0)x = 0;
|
|
||||||
if(y<0)y = 0;
|
|
||||||
if(x+w >= m_img.cols)x = m_img.cols-w;
|
|
||||||
if(y+h >= m_img.rows)y = m_img.rows-h;
|
|
||||||
cv::Mat roiImg(m_img, cv::Rect(x, y, w, h));
|
|
||||||
cv::Mat doubleMat;
|
|
||||||
roiImg.convertTo(doubleMat, CV_64F);
|
|
||||||
r = std::vector<double>(doubleMat.begin<double>(), doubleMat.end<double>());*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int RawImage::findPeaks(double background, double distance, std::vector<Peak> &peaks) const
|
|
||||||
{
|
|
||||||
/*std::vector<std::vector<cv::Point>> contours;
|
|
||||||
|
|
||||||
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(distance, distance));
|
|
||||||
|
|
||||||
cv::Mat img, mask, dilate, locMax, result;
|
|
||||||
if(m_img.channels() == 1)img = m_img;
|
|
||||||
else cv::cvtColor(m_img, img, cv::COLOR_RGB2GRAY);
|
|
||||||
|
|
||||||
cv::dilate(img, dilate, kernel);
|
|
||||||
cv::compare(img, dilate, locMax, cv::CMP_GE);
|
|
||||||
cv::compare(img, cv::Scalar(background), mask, cv::CMP_GT);
|
|
||||||
cv::bitwise_and(locMax, mask, result);
|
|
||||||
|
|
||||||
cv::findContours(result, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
|
|
||||||
peaks.reserve(contours.size());
|
|
||||||
for(auto contour : contours)
|
|
||||||
{
|
|
||||||
peaks.push_back(Peak(1, contour[0].x, contour[0].y));
|
|
||||||
}
|
|
||||||
|
|
||||||
return peaks.size();*/
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t RawImage::width() const
|
uint32_t RawImage::width() const
|
||||||
{
|
{
|
||||||
return m_width;
|
return m_width;
|
||||||
@@ -334,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
|
||||||
@@ -376,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
|
||||||
@@ -396,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
|
||||||
@@ -421,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)
|
||||||
{
|
{
|
||||||
@@ -475,45 +453,106 @@ void RawImage::convertToThumbnail()
|
|||||||
|
|
||||||
void RawImage::convertToGLFormat()
|
void RawImage::convertToGLFormat()
|
||||||
{
|
{
|
||||||
size_t s = size() * m_ch;
|
if(m_type == UINT32 || m_type == FLOAT64)
|
||||||
if(m_type == UINT32)
|
convertToType(FLOAT32);
|
||||||
{
|
else if(OpenGLES && m_type == UINT16)
|
||||||
m_origWidth = m_width;
|
convertToType(FLOAT16);
|
||||||
m_origHeight = m_height;
|
}
|
||||||
m_original = std::move(m_pixels);
|
|
||||||
allocate(m_width, m_height, m_channels, FLOAT32);
|
|
||||||
m_origType = UINT32;
|
|
||||||
float *dst = reinterpret_cast<float*>(m_pixels.get());
|
|
||||||
uint32_t *src = reinterpret_cast<uint32_t*>(m_original.get());
|
|
||||||
|
|
||||||
for(size_t i = 0; i < s; i++)
|
template<typename T, typename U>
|
||||||
dst[i] = src[i] / (float)UINT32_MAX;
|
void convertType2(size_t size, const T *src, U *dst)
|
||||||
}
|
{
|
||||||
else if(m_type == FLOAT64)
|
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>))
|
||||||
{
|
{
|
||||||
m_origWidth = m_width;
|
for(size_t i = 0; i < size; i++)
|
||||||
m_origHeight = m_height;
|
|
||||||
m_original = std::move(m_pixels);
|
|
||||||
allocate(m_width, m_height, m_channels, FLOAT32);
|
|
||||||
m_origType = FLOAT64;
|
|
||||||
float *dst = reinterpret_cast<float*>(m_pixels.get());
|
|
||||||
double *src = reinterpret_cast<double*>(m_original.get());
|
|
||||||
|
|
||||||
for(size_t i = 0; i < s; i++)
|
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
}
|
}
|
||||||
else if(OpenGLES && m_type == UINT16)
|
|
||||||
|
if constexpr(std::is_integral_v<T> && std::is_integral_v<U>)
|
||||||
{
|
{
|
||||||
|
if constexpr(sizeof(T) > sizeof(U))
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8);
|
||||||
|
else
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
dst[i] = static_cast<U>(src[i]) << ((sizeof(U) - sizeof(T)) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr((std::is_floating_point_v<T> || std::is_same_v<T, F16>) && std::is_integral_v<U>)
|
||||||
|
{
|
||||||
|
U max = std::numeric_limits<U>::max();
|
||||||
|
T scale = (T)(max);
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
dst[i] = src[i] * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
dst[i] = (U)src[i] * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void convertType(size_t size, RawImage::DataType dstType, const T *src, void *dst)
|
||||||
|
{
|
||||||
|
switch(dstType)
|
||||||
|
{
|
||||||
|
case RawImage::UINT8:
|
||||||
|
convertType2(size, src, static_cast<uint8_t*>(dst));
|
||||||
|
break;
|
||||||
|
case RawImage::UINT16:
|
||||||
|
convertType2(size, src, static_cast<uint16_t*>(dst));
|
||||||
|
break;
|
||||||
|
case RawImage::UINT32:
|
||||||
|
convertType2(size, src, static_cast<uint32_t*>(dst));
|
||||||
|
break;
|
||||||
|
case RawImage::FLOAT16:
|
||||||
|
convertType2(size, src, static_cast<F16*>(dst));
|
||||||
|
break;
|
||||||
|
case RawImage::FLOAT32:
|
||||||
|
convertType2(size, src, static_cast<float*>(dst));
|
||||||
|
break;
|
||||||
|
case RawImage::FLOAT64:
|
||||||
|
convertType2(size, src, static_cast<double*>(dst));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RawImage::convertToType(DataType type)
|
||||||
|
{
|
||||||
|
if(type == m_type)
|
||||||
|
return;
|
||||||
|
|
||||||
m_origWidth = m_width;
|
m_origWidth = m_width;
|
||||||
m_origHeight = m_height;
|
m_origHeight = m_height;
|
||||||
m_original = std::move(m_pixels);
|
m_original = std::move(m_pixels);
|
||||||
allocate(m_width, m_height, m_channels, FLOAT16);
|
DataType origType = m_type;
|
||||||
m_origType = UINT16;
|
allocate(m_width, m_height, m_channels, type);
|
||||||
F16 *dst = reinterpret_cast<F16*>(m_pixels.get());
|
m_origType = origType;
|
||||||
uint16_t *src = reinterpret_cast<uint16_t*>(m_original.get());
|
|
||||||
|
|
||||||
for(size_t i = 0; i < s; i++)
|
size_t s = size() * m_ch;
|
||||||
dst[i] = (F16)(src[i] / (float)UINT16_MAX);
|
switch(m_origType)
|
||||||
|
{
|
||||||
|
case UINT8:
|
||||||
|
convertType(s, type, reinterpret_cast<uint8_t*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case UINT16:
|
||||||
|
convertType(s, type, reinterpret_cast<uint16_t*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case UINT32:
|
||||||
|
convertType(s, type, reinterpret_cast<uint32_t*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case FLOAT16:
|
||||||
|
convertType(s, type, reinterpret_cast<F16*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case FLOAT32:
|
||||||
|
convertType(s, type, reinterpret_cast<float*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case FLOAT64:
|
||||||
|
convertType(s, type, reinterpret_cast<double*>(m_original.get()), m_pixels.get());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,28 +661,28 @@ bool RawImage::pixel(int x, int y, double &r, double &g, double &b) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename U = float>
|
||||||
void boxResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t oldh, const uint8_t *in_, uint8_t *out_)
|
void boxResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t oldh, const uint8_t *in_, uint8_t *out_)
|
||||||
{
|
{
|
||||||
if(oldw == 0 || oldh == 0)return;
|
if(oldw == 0 || oldh == 0)return;
|
||||||
|
|
||||||
const T *in = reinterpret_cast<const T*>(in_);
|
const T *in = reinterpret_cast<const T*>(in_);
|
||||||
T *out = reinterpret_cast<T*>(out_);
|
T *out = reinterpret_cast<T*>(out_);
|
||||||
float max = 255.0f;
|
U max = 255.0f;
|
||||||
if constexpr(std::is_same_v<T, uint16_t>)
|
if constexpr(std::is_integral_v<T>)
|
||||||
max = UINT16_MAX;
|
max = (U)std::numeric_limits<T>::max();
|
||||||
|
|
||||||
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
|
||||||
{
|
{
|
||||||
float 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;
|
||||||
@@ -692,14 +731,17 @@ void RawImage::resize(uint32_t w, uint32_t h)
|
|||||||
case RawImage::UINT16:
|
case RawImage::UINT16:
|
||||||
boxResample<uint16_t>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
boxResample<uint16_t>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
||||||
break;
|
break;
|
||||||
case RawImage::FLOAT32:
|
case RawImage::UINT32:
|
||||||
boxResample<float>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
boxResample<uint32_t>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
||||||
break;
|
break;
|
||||||
case RawImage::FLOAT16:
|
case RawImage::FLOAT16:
|
||||||
boxResample<F16>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
boxResample<F16>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
||||||
break;
|
break;
|
||||||
default:
|
case RawImage::FLOAT32:
|
||||||
qWarning() << "Resizing format not supported";
|
boxResample<float>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
||||||
|
break;
|
||||||
|
case RawImage::FLOAT64:
|
||||||
|
boxResample<double, double>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -86,12 +86,10 @@ public:
|
|||||||
RawImage(const QImage &img);
|
RawImage(const QImage &img);
|
||||||
const RawImage::Stats& imageStats() const;
|
const RawImage::Stats& imageStats() const;
|
||||||
void calcStats();
|
void calcStats();
|
||||||
void rect(int &x, int &y, int w, int h, std::vector<double> &r) const;
|
|
||||||
int findPeaks(double background, double distance, std::vector<Peak> &peaks) const;
|
|
||||||
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;
|
||||||
@@ -105,6 +103,7 @@ public:
|
|||||||
void setPlanar();
|
void setPlanar();
|
||||||
void convertToThumbnail();
|
void convertToThumbnail();
|
||||||
void convertToGLFormat();
|
void convertToGLFormat();
|
||||||
|
void convertToType(RawImage::DataType type);
|
||||||
float thumbAspect() const;
|
float thumbAspect() const;
|
||||||
bool pixel(int x, int y, double &r, double &g, double &b) const;
|
bool pixel(int x, int y, double &r, double &g, double &b) const;
|
||||||
void resize(uint32_t w, uint32_t h);
|
void resize(uint32_t w, uint32_t h);
|
||||||
|
|||||||
+3
-3
@@ -21,7 +21,7 @@ void fromPlanarSSE(const void *in, void *out, size_t count)
|
|||||||
__m128i r = _mm_loadu_si128(_in[0] + i);
|
__m128i r = _mm_loadu_si128(_in[0] + i);
|
||||||
__m128i g = _mm_loadu_si128(_in[1] + i);
|
__m128i g = _mm_loadu_si128(_in[1] + i);
|
||||||
__m128i b = _mm_loadu_si128(_in[2] + i);
|
__m128i b = _mm_loadu_si128(_in[2] + i);
|
||||||
if constexpr(ch==4)a = _mm_loadu_si128(_in[3]);
|
if constexpr(ch==4)a = _mm_loadu_si128(_in[3] + i);
|
||||||
|
|
||||||
__m128i d1 = _mm_unpacklo_epi8(r, b);
|
__m128i d1 = _mm_unpacklo_epi8(r, b);
|
||||||
__m128i d2 = _mm_unpacklo_epi8(g, a);
|
__m128i d2 = _mm_unpacklo_epi8(g, a);
|
||||||
@@ -43,7 +43,7 @@ void fromPlanarSSE(const void *in, void *out, size_t count)
|
|||||||
__m128i r = _mm_loadu_si128(_in[0] + i);
|
__m128i r = _mm_loadu_si128(_in[0] + i);
|
||||||
__m128i g = _mm_loadu_si128(_in[1] + i);
|
__m128i g = _mm_loadu_si128(_in[1] + i);
|
||||||
__m128i b = _mm_loadu_si128(_in[2] + i);
|
__m128i b = _mm_loadu_si128(_in[2] + i);
|
||||||
if constexpr(ch==4)a = _mm_loadu_si128(_in[3]);
|
if constexpr(ch==4)a = _mm_loadu_si128(_in[3] + i);
|
||||||
|
|
||||||
__m128i d1 = _mm_unpacklo_epi16(r, b);
|
__m128i d1 = _mm_unpacklo_epi16(r, b);
|
||||||
__m128i d2 = _mm_unpacklo_epi16(g, a);
|
__m128i d2 = _mm_unpacklo_epi16(g, a);
|
||||||
@@ -66,7 +66,7 @@ void fromPlanarSSE(const void *in, void *out, size_t count)
|
|||||||
__m128i r = _mm_loadu_si128(_in[0] + i);
|
__m128i r = _mm_loadu_si128(_in[0] + i);
|
||||||
__m128i g = _mm_loadu_si128(_in[1] + i);
|
__m128i g = _mm_loadu_si128(_in[1] + i);
|
||||||
__m128i b = _mm_loadu_si128(_in[2] + i);
|
__m128i b = _mm_loadu_si128(_in[2] + i);
|
||||||
if constexpr(ch==4)a = _mm_loadu_si128(_in[3]);
|
if constexpr(ch==4)a = _mm_loadu_si128(_in[3] + i);
|
||||||
|
|
||||||
__m128i d1 = _mm_unpacklo_epi32(r, b);
|
__m128i d1 = _mm_unpacklo_epi32(r, b);
|
||||||
__m128i d2 = _mm_unpacklo_epi32(g, a);
|
__m128i d2 = _mm_unpacklo_epi32(g, a);
|
||||||
|
|||||||
+94
-28
@@ -3,13 +3,16 @@
|
|||||||
#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"
|
||||||
#include "batchprocessing.h"
|
#include "batchprocessing.h"
|
||||||
#include <fitsio2.h>
|
#include <fitsio2.h>
|
||||||
#include "libXISF/libxisf.h"
|
#include "libXISF/libxisf.h"
|
||||||
|
#ifdef PLATESOLVER
|
||||||
#include "solver.h"
|
#include "solver.h"
|
||||||
|
#endif // PLATESOLVER
|
||||||
|
|
||||||
namespace Script
|
namespace Script
|
||||||
{
|
{
|
||||||
@@ -26,8 +29,11 @@ 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
|
||||||
_solver = new Solver(this);
|
_solver = new Solver(this);
|
||||||
|
#endif // PLATESOLVER
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir)
|
void ScriptEngine::setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir)
|
||||||
@@ -49,7 +55,9 @@ const QString &ScriptEngine::outputDir() const
|
|||||||
|
|
||||||
void ScriptEngine::interrupt()
|
void ScriptEngine::interrupt()
|
||||||
{
|
{
|
||||||
_solver->abort();
|
#ifdef PLATESOLVER
|
||||||
|
if(_solver)_solver->abort();
|
||||||
|
#endif
|
||||||
_jsEngine->setInterrupted(true);
|
_jsEngine->setInterrupted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,25 +130,6 @@ QJSValue ScriptEngine::getItem(const QStringList &items, const QString &label, i
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::setStartingSolution(const QJSValue &solution)
|
|
||||||
{
|
|
||||||
if(solution.isObject())
|
|
||||||
{
|
|
||||||
if(solution.hasProperty("ra") && solution.hasProperty("dec") && solution.property("ra").isNumber() && solution.property("dec").isNumber())
|
|
||||||
_solver->setSearchPosition(solution.property("ra").toNumber(), solution.property("dec").toNumber());
|
|
||||||
if(solution.hasProperty("pixscale") && solution.property("pixscale").isNumber())
|
|
||||||
{
|
|
||||||
double scale = solution.property("pixscale").toNumber();
|
|
||||||
_solver->setSearchScale(scale * 0.8, scale * 1.2, SSolver::ScaleUnits::ARCSEC_PER_PIX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_solver->clearStartingPositionAndScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScriptEngine::convert(File *file, QString &outpath, const QString &format, const QVariantMap ¶ms, bool async)
|
bool ScriptEngine::convert(File *file, QString &outpath, const QString &format, const QVariantMap ¶ms, bool async)
|
||||||
{
|
{
|
||||||
QString path;
|
QString path;
|
||||||
@@ -153,9 +142,9 @@ bool ScriptEngine::convert(File *file, QString &outpath, const QString &format,
|
|||||||
path = dir.absoluteFilePath(outpath);
|
path = dir.absoluteFilePath(outpath);
|
||||||
|
|
||||||
QString f = format.toLower();
|
QString f = format.toLower();
|
||||||
if(f != "xisf" && f != "fits" && f != "png" && f != "bmp" && f != "jpg")
|
if(f != "xisf" && f != "fits" && f != "png" && f != "bmp" && f != "jpg" && f != "tiff")
|
||||||
{
|
{
|
||||||
logError("Output format must be one of xisf fits jpg png bmp");
|
logError("Output format must be one of xisf fits jpg png bmp tiff");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +163,78 @@ bool ScriptEngine::convert(File *file, QString &outpath, const QString &format,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
if(solution.isObject())
|
||||||
|
{
|
||||||
|
if(solution.hasProperty("ra") && solution.hasProperty("dec") && solution.property("ra").isNumber() && solution.property("dec").isNumber())
|
||||||
|
_solver->setSearchPosition(solution.property("ra").toNumber(), solution.property("dec").toNumber());
|
||||||
|
|
||||||
|
if(solution.hasProperty("pixscale") && solution.property("pixscale").isNumber())
|
||||||
|
{
|
||||||
|
double scale = solution.property("pixscale").toNumber();
|
||||||
|
_solver->setSearchScale(scale * 0.8, scale * 1.2, SSolver::ScaleUnits::ARCSEC_PER_PIX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_solver->clearStartingPositionAndScale();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QJSValue ScriptEngine::solveImage(File *file, bool updateHeader)
|
QJSValue ScriptEngine::solveImage(File *file, bool updateHeader)
|
||||||
{
|
{
|
||||||
QString path = file->absoluteFilePath();
|
QString path = file->absoluteFilePath();
|
||||||
@@ -253,6 +314,7 @@ QJSValue ScriptEngine::extractStars(File *file, bool hfr)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif // PLATESOLVER
|
||||||
|
|
||||||
QJSValue ScriptEngine::newObject()
|
QJSValue ScriptEngine::newObject()
|
||||||
{
|
{
|
||||||
@@ -457,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)
|
||||||
@@ -580,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());
|
||||||
@@ -593,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)
|
||||||
@@ -682,6 +746,7 @@ QJSValue File::stats()
|
|||||||
return _stats;
|
return _stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLATESOLVER
|
||||||
QJSValue File::solve(bool updateHeader)
|
QJSValue File::solve(bool updateHeader)
|
||||||
{
|
{
|
||||||
if(_solution.isUndefined() || updateHeader)
|
if(_solution.isUndefined() || updateHeader)
|
||||||
@@ -697,6 +762,7 @@ QJSValue File::extractStars(bool hfr)
|
|||||||
|
|
||||||
return _stars;
|
return _stars;
|
||||||
}
|
}
|
||||||
|
#endif // PLATESOLVER
|
||||||
|
|
||||||
ScriptEngineThread::ScriptEngineThread(BatchProcessing *parent) : QObject(parent)
|
ScriptEngineThread::ScriptEngineThread(BatchProcessing *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
|||||||
+9
-2
@@ -29,7 +29,7 @@ class ScriptEngine : public QObject
|
|||||||
QString _scriptPath;
|
QString _scriptPath;
|
||||||
QString _outputDir;
|
QString _outputDir;
|
||||||
QList<QPair<QString, QString>> _paths;
|
QList<QPair<QString, QString>> _paths;
|
||||||
Solver *_solver;
|
Solver *_solver = nullptr;
|
||||||
public:
|
public:
|
||||||
explicit ScriptEngine(BatchProcessing *parent = nullptr);
|
explicit ScriptEngine(BatchProcessing *parent = nullptr);
|
||||||
void setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir);
|
void setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir);
|
||||||
@@ -47,10 +47,15 @@ public:
|
|||||||
Q_INVOKABLE QJSValue getInt(const QString &label = QString(), int value = 0);
|
Q_INVOKABLE QJSValue getInt(const QString &label = QString(), int value = 0);
|
||||||
Q_INVOKABLE QJSValue getFloat(const QString &label = QString(), double value = 0, int decimals = 3) const;
|
Q_INVOKABLE QJSValue getFloat(const QString &label = QString(), double value = 0, int decimals = 3) const;
|
||||||
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;
|
||||||
Q_INVOKABLE void setStartingSolution(const QJSValue &solution = QJSValue());
|
|
||||||
bool convert(File *file, QString &outpath, const QString &format, const QVariantMap ¶ms, bool async);
|
bool convert(File *file, QString &outpath, const QString &format, const QVariantMap ¶ms, bool async);
|
||||||
|
#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());
|
||||||
QJSValue solveImage(File *file, bool updateHeader);
|
QJSValue solveImage(File *file, bool updateHeader);
|
||||||
QJSValue extractStars(File *file, bool hfr);
|
QJSValue extractStars(File *file, bool hfr);
|
||||||
|
#endif // PLATESOLVER
|
||||||
QJSValue newObject();
|
QJSValue newObject();
|
||||||
QJSValue newArray(uint size);
|
QJSValue newArray(uint size);
|
||||||
public slots:
|
public slots:
|
||||||
@@ -116,8 +121,10 @@ public:
|
|||||||
Q_INVOKABLE File* convert(const QString &outpath, const QString &format, const QVariantMap ¶ms = QVariantMap());
|
Q_INVOKABLE File* convert(const QString &outpath, const QString &format, const QVariantMap ¶ms = QVariantMap());
|
||||||
Q_INVOKABLE File* convertAsync(const QString &outpath, const QString &format, const QVariantMap ¶ms = QVariantMap());
|
Q_INVOKABLE File* convertAsync(const QString &outpath, const QString &format, const QVariantMap ¶ms = QVariantMap());
|
||||||
Q_INVOKABLE QJSValue stats();
|
Q_INVOKABLE QJSValue stats();
|
||||||
|
#ifdef PLATESOLVER
|
||||||
Q_INVOKABLE QJSValue solve(bool updateHeader = false);
|
Q_INVOKABLE QJSValue solve(bool updateHeader = false);
|
||||||
Q_INVOKABLE QJSValue extractStars(bool hfr);
|
Q_INVOKABLE QJSValue extractStars(bool hfr);
|
||||||
|
#endif // PLATESOLVER
|
||||||
};
|
};
|
||||||
|
|
||||||
class FITSRecordModify : public QObject
|
class FITSRecordModify : public QObject
|
||||||
|
|||||||
@@ -205,6 +205,11 @@ void Solver::setParameters(const Parameters ¶meters)
|
|||||||
_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);
|
||||||
|
|||||||
@@ -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 ¶meters);
|
void setParameters(const SSolver::Parameters ¶meters);
|
||||||
|
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();
|
||||||
|
|||||||
@@ -57,6 +57,22 @@
|
|||||||
</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">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Extending support of data formats</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="20241002" date="2024-10-02">
|
<release version="20241002" date="2024-10-02">
|
||||||
<description>
|
<description>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user