Compare commits

..

17 Commits

Author SHA1 Message Date
nou 1a220bc3ed Update metainfo 2022-12-28 14:59:17 +01:00
nou f67539a3a1 Update translations 2022-12-28 14:51:45 +01:00
nou 468bcb5abb Add saturation statistic 2022-12-28 14:43:47 +01:00
nou fd49ba9a44 CSV export 2022-12-28 13:24:05 +01:00
nou 22e3b06fdd Fix potentional race conditions 2022-12-28 11:33:26 +01:00
nou 01febbf421 Fix invalid query when no column is selected 2022-12-28 11:17:36 +01:00
nou 7690496cf5 Load XISF::ReadImageProperties 2022-12-26 18:07:16 +01:00
nou 743a5f50c4 Disable manual mipmap generation on ATI cards 2022-12-26 10:19:45 +01:00
nou eac534352f Tidy up some debug outputs 2022-12-26 10:19:20 +01:00
nou 57bdc74ef6 Get rid of QRegExp 2022-12-26 10:13:24 +01:00
nou fd1fd7ff08 Get rid of fullscreen mode 2022-12-25 19:34:09 +01:00
nou c1aca3ca65 Add fine tune for STF slider 2022-12-22 12:45:47 +01:00
nou 5cc8fdd83d Simple grey world white balance 2022-12-20 22:27:15 +01:00
nou 66e13529be Allow change of preload without restart 2022-12-18 10:18:01 +01:00
nou e1bed8e1cb Allow change of thumbnail size without restart 2022-12-18 00:17:28 +01:00
nou 151f521688 Set image width and height for XISF 2022-12-17 09:48:35 +01:00
nou 926647e1a7 Don't do unecessary color profile conversion 2022-12-17 09:47:38 +01:00
27 changed files with 370 additions and 55 deletions
+4 -6
View File
@@ -125,7 +125,6 @@ QStringList Database::getMarkedFiles()
files << markedFiles.value("file").toString(); files << markedFiles.value("file").toString();
} }
qDebug() << files.size();
return files; return files;
} }
@@ -226,7 +225,6 @@ QStringList Database::getFitsKeywords()
return keywords; return keywords;
} }
bool Database::indexDir2(const QDir &dir, QProgressDialog *progress) bool Database::indexDir2(const QDir &dir, QProgressDialog *progress)
{ {
QFileInfoList files = dir.entryInfoList(nameFilters, QDir::Files); QFileInfoList files = dir.entryInfoList(nameFilters, QDir::Files);
@@ -288,7 +286,7 @@ bool Database::indexFile(const QFileInfo &file)
m_insertFileWcs.bindValue(7, crVal2); m_insertFileWcs.bindValue(7, crVal2);
if(!m_insertFileWcs.exec()) if(!m_insertFileWcs.exec())
{ {
qDebug() << m_insertFileWcs.lastError(); qDebug() << "Database error" << m_insertFileWcs.lastError();
return false; return false;
} }
last_id = m_insertFileWcs.lastInsertId().toLongLong(); last_id = m_insertFileWcs.lastInsertId().toLongLong();
@@ -299,7 +297,7 @@ bool Database::indexFile(const QFileInfo &file)
m_insertFile.bindValue(1, mtime); m_insertFile.bindValue(1, mtime);
if(!m_insertFile.exec()) if(!m_insertFile.exec())
{ {
qDebug() << m_insertFile.lastError(); qDebug() << "Database error" << m_insertFile.lastError();
return false; return false;
} }
last_id = m_insertFile.lastInsertId().toLongLong(); last_id = m_insertFile.lastInsertId().toLongLong();
@@ -319,10 +317,10 @@ bool Database::indexFile(const QFileInfo &file)
m_insertFitsHeader.bindValue(3, comments); m_insertFitsHeader.bindValue(3, comments);
if(!m_insertFitsHeader.execBatch()) if(!m_insertFitsHeader.execBatch())
{ {
qDebug() << m_insertFitsHeader.lastError(); qDebug() << "Database error" << m_insertFitsHeader.lastError();
return false; return false;
} }
} }
qDebug() << filePath << last_id; qDebug() << "Indexed" << filePath << last_id;
return true; return true;
} }
+40 -5
View File
@@ -8,7 +8,7 @@
#include <QDebug> #include <QDebug>
#include <QMenu> #include <QMenu>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QRegExp> #include <QRegularExpression>
#include <iostream> #include <iostream>
const QStringList DEFAULT_COLUMNS = {"EXPTIME", "OBJECT", "RA", "DEC"}; const QStringList DEFAULT_COLUMNS = {"EXPTIME", "OBJECT", "RA", "DEC"};
@@ -20,7 +20,7 @@ double RA(const QString &ra)
double h = match.captured(1).toDouble(); double h = match.captured(1).toDouble();
double m = match.captured(2).toDouble(); double m = match.captured(2).toDouble();
double s = match.captured(3).toDouble(); double s = match.captured(3).toDouble();
qDebug() << match.capturedTexts() << h << m << s; qDebug() << "RA" << match.capturedTexts() << h << m << s;
return h*15 + m*0.25 + s*15/3600; return h*15 + m*0.25 + s*15/3600;
} }
@@ -32,7 +32,7 @@ double DEC(const QString &dec)
double d = match.captured(2).toDouble(); double d = match.captured(2).toDouble();
double m = match.captured(3).toDouble(); double m = match.captured(3).toDouble();
double s = match.captured(4).toDouble(); double s = match.captured(4).toDouble();
qDebug() << match.capturedTexts() << sign << d << m << s; qDebug() << "DEC" << match.capturedTexts() << sign << d << m << s;
return sign * (d + m/60 + s/3600); return sign * (d + m/60 + s/3600);
} }
@@ -157,7 +157,7 @@ void FITSFileModel::prepareQuery()
QString cols; QString cols;
QString join; QString join;
QStringList where; QStringList where;
QString sql = "SELECT f.file,"; QString sql = m_columns.size() ? "SELECT f.file," : "SELECT f.file";
for(int i=0; i<m_value.size(); i++) for(int i=0; i<m_value.size(); i++)
{ {
if(m_key[i] == "file") if(m_key[i] == "file")
@@ -195,7 +195,7 @@ void FITSFileModel::prepareQuery()
} }
std::cout << sql.toStdString() << std::endl; std::cout << sql.toStdString() << std::endl;
if(lastError().type() != QSqlError::NoError) if(lastError().type() != QSqlError::NoError)
qDebug() << lastError(); qDebug() << "Database error" << lastError();
m_markedFiles = m_database->getMarkedFiles().toSet(); m_markedFiles = m_database->getMarkedFiles().toSet();
} }
@@ -362,3 +362,38 @@ void DataBaseView::applyFilter()
} }
m_model->setFilter(keys, values, limits); m_model->setFilter(keys, values, limits);
} }
bool DataBaseView::exportCSV(const QString &path)
{
QFile csv(path);
if(!csv.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QSqlQuery sql = m_model->query();
int colCount = m_model->columnCount();
QStringList header;
for(int i=0; i<colCount; i++)
header.append(m_model->headerData(i, Qt::Horizontal).toString());
csv.write(header.join(",").toUtf8());
csv.write("\n");
while(sql.next())
{
QStringList columns;
for(int i=0; i<colCount; i++)
{
QString val = sql.value(i).toString();
val.replace("\"", "\"\"");
if(val.contains('"') || val.contains(','))
{
val.prepend('"');
val.append('"');
}
columns.append(val);
}
csv.write(columns.join(",").toUtf8());
csv.write("\n");
}
return true;
}
+1
View File
@@ -71,6 +71,7 @@ public slots:
void loadDatabase(); void loadDatabase();
void itemActivated(const QModelIndex &index); void itemActivated(const QModelIndex &index);
void applyFilter(); void applyFilter();
bool exportCSV(const QString &path);
signals: signals:
void loadFile(QString file); void loadFile(QString file);
}; };
+33
View File
@@ -5,6 +5,7 @@
#include <wcslib/wcshdr.h> #include <wcslib/wcshdr.h>
#include <wcslib/wcsfix.h> #include <wcslib/wcsfix.h>
#include "pcl/FITSHeaderKeyword.h" #include "pcl/FITSHeaderKeyword.h"
#include "pcl/Property.h"
static const QVector<QByteArray> noEditableKey = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "EXTEND", "BZERO", "BSCALE"}; static const QVector<QByteArray> noEditableKey = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "EXTEND", "BZERO", "BSCALE"};
@@ -43,6 +44,38 @@ FITSRecord::FITSRecord(const pcl::FITSHeaderKeyword &record)
value = string; value = string;
} }
FITSRecord::FITSRecord(const pcl::Property &property)
{
key = property.Identifier().c_str();
const pcl::Variant &pclval = property.Value();
switch(pclval.Type())
{
case pcl::VariantType::Bool:
value = pclval.ToBool();
break;
case pcl::VariantType::Int8:
case pcl::VariantType::Int16:
case pcl::VariantType::Int32:
case pcl::VariantType::Int64:
value = pclval.ToInt64();
break;
case pcl::VariantType::UInt8:
case pcl::VariantType::UInt16:
case pcl::VariantType::UInt32:
case pcl::VariantType::UInt64:
value = pclval.ToUInt64();
break;
case pcl::VariantType::Float:
case pcl::VariantType::Double:
value = pclval.ToDouble();
break;
default:
value = pclval.ToIsoString().c_str();
break;
}
}
QByteArray FITSRecord::valueToByteArray() const QByteArray FITSRecord::valueToByteArray() const
{ {
if(value.type() == QVariant::Bool) if(value.type() == QVariant::Bool)
+2 -1
View File
@@ -6,7 +6,7 @@
#include <cmath> #include <cmath>
#include <memory> #include <memory>
namespace pcl { class FITSHeaderKeyword; } namespace pcl { class FITSHeaderKeyword; class Property; }
struct FITSRecord struct FITSRecord
{ {
@@ -17,6 +17,7 @@ struct FITSRecord
FITSRecord(){} FITSRecord(){}
FITSRecord(const QByteArray &key, const QVariant &value, const QByteArray &comment); FITSRecord(const QByteArray &key, const QVariant &value, const QByteArray &comment);
FITSRecord(const pcl::FITSHeaderKeyword &record); FITSRecord(const pcl::FITSHeaderKeyword &record);
FITSRecord(const pcl::Property &property);
QByteArray valueToByteArray() const; QByteArray valueToByteArray() const;
}; };
+41 -1
View File
@@ -76,6 +76,11 @@ int Image::number() const
return m_number; return m_number;
} }
void Image::clearThumbnail()
{
m_thumbnail.reset();
}
void Image::imageLoaded(void *rawImage, ImageInfoData info) void Image::imageLoaded(void *rawImage, ImageInfoData info)
{ {
m_loading = false; m_loading = false;
@@ -105,7 +110,7 @@ ImageRingList::ImageRingList(Database *database, const QStringList &nameFilter,
, m_nameFilter(nameFilter) , m_nameFilter(nameFilter)
{ {
connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString))); connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
m_nameFilter.replaceInStrings(QRegExp("^"), "*."); m_nameFilter.replaceInStrings(QRegularExpression("^"), "*.");
m_thumbPool = new QThreadPool(this); m_thumbPool = new QThreadPool(this);
} }
@@ -284,6 +289,12 @@ void ImageRingList::updateMark()
} }
} }
void ImageRingList::clearThumbnails()
{
for(auto &img : m_images)
img->clearThumbnail();
}
QModelIndex ImageRingList::index(int row, int column, const QModelIndex &parent) const QModelIndex ImageRingList::index(int row, int column, const QModelIndex &parent) const
{ {
return createIndex(row, column, m_images.at(row).get()); return createIndex(row, column, m_images.at(row).get());
@@ -337,6 +348,35 @@ QVariant ImageRingList::headerData(int section, Qt::Orientation orientation, int
return QVariant(); return QVariant();
} }
void ImageRingList::setPreload(int width)
{
DEFAULT_WIDTH = width;
if(m_images.size() == 0)return;
int newWidth = DEFAULT_WIDTH<m_images.size()/2 ? DEFAULT_WIDTH : m_images.size()/2;
if(newWidth > m_width)
{
for(int i = newWidth - m_width; i>0; i--)
{
m_firstImage = decrement(m_firstImage);
(*m_firstImage)->load();
m_lastImage = increment(m_lastImage);
(*m_lastImage)->load();
}
}
if(newWidth < m_width)
{
for(int i = m_width - newWidth; i>0; i--)
{
(*m_firstImage)->release();
m_firstImage = increment(m_firstImage);
(*m_lastImage)->release();
m_lastImage = decrement(m_lastImage);
}
}
m_width = newWidth;
}
void ImageRingList::setFiles(const QStringList files, const QString &currentFile) void ImageRingList::setFiles(const QStringList files, const QString &currentFile)
{ {
QThreadPool::globalInstance()->clear(); QThreadPool::globalInstance()->clear();
+4
View File
@@ -35,6 +35,7 @@ public:
ImageInfoData info() const; ImageInfoData info() const;
bool isCurrent() const; bool isCurrent() const;
int number() const; int number() const;
void clearThumbnail();
signals: signals:
void pixmapLoaded(Image *ptr); void pixmapLoaded(Image *ptr);
void thumbnailLoaded(Image *ptr); void thumbnailLoaded(Image *ptr);
@@ -80,6 +81,7 @@ public:
int imageCount() const; int imageCount() const;
QStringList imageNames() const; QStringList imageNames() const;
void updateMark(); void updateMark();
void clearThumbnails();
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override; QModelIndex parent(const QModelIndex &child) const override;
@@ -87,6 +89,8 @@ public:
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
public slots:
void setPreload(int width);
protected: protected:
void setFiles(const QStringList files, const QString &currentFile = QString()); void setFiles(const QStringList files, const QString &currentFile = QString());
QList<ImagePtr>::iterator increment(QList<ImagePtr>::iterator iter); QList<ImagePtr>::iterator increment(QList<ImagePtr>::iterator iter);
+22 -2
View File
@@ -97,13 +97,15 @@ ImageWidget::~ImageWidget()
void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index) void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
{ {
if(image == nullptr)return; if(image == nullptr)return;
makeCurrent();
m_rawImage = image; m_rawImage = image;
m_imgWidth = image->width(); m_imgWidth = image->width();
m_imgHeight = image->height(); m_imgHeight = image->height();
m_currentImg = index; m_currentImg = index;
if(!m_image)return;
const RawImageType &rawImageType = rawImageTypes[image->type()]; const RawImageType &rawImageType = rawImageTypes[image->type()];
m_srgb = rawImageType.textureFormat == QOpenGLTexture::SRGB8 || rawImageType.textureFormat == QOpenGLTexture::SRGB8_Alpha8; m_srgb = rawImageType.textureFormat == QOpenGLTexture::SRGB8 || rawImageType.textureFormat == QOpenGLTexture::SRGB8_Alpha8;
m_bwImg = rawImageType.bw; m_bwImg = rawImageType.bw;
@@ -353,6 +355,8 @@ void ImageWidget::paintGL()
m_program->setUniformValue("zoom", 1.0f/m_scale); m_program->setUniformValue("zoom", 1.0f/m_scale);
m_program->setUniformValue("bw", m_bwImg && !m_superpixel); m_program->setUniformValue("bw", m_bwImg && !m_superpixel);
m_program->setUniformValue("invert", m_invert); m_program->setUniformValue("invert", m_invert);
if(m_superpixel)m_program->setUniformValue("whiteBalance", m_whiteBalance[0], m_whiteBalance[1], m_whiteBalance[2]);
else m_program->setUniformValue("whiteBalance", 1.0f, 1.0f, 1.0f);
#ifdef COLOR_MANAGMENT #ifdef COLOR_MANAGMENT
m_program->setUniformValue("srgb", m_srgb); m_program->setUniformValue("srgb", m_srgb);
#endif #endif
@@ -395,7 +399,7 @@ void ImageWidget::initializeGL()
qDebug() << (char*)f->glGetString(GL_RENDERER); qDebug() << (char*)f->glGetString(GL_RENDERER);
qDebug() << (char*)f->glGetString(GL_VERSION); qDebug() << (char*)f->glGetString(GL_VERSION);
MANUAL_MIPMAP_GEN = QString((const char*)f->glGetString(GL_VENDOR)).startsWith("ATI Technologies Inc", Qt::CaseInsensitive); //MANUAL_MIPMAP_GEN = QString((const char*)f->glGetString(GL_VENDOR)).startsWith("ATI Technologies Inc", Qt::CaseInsensitive);
qDebug() << context()->format(); qDebug() << context()->format();
@@ -487,6 +491,9 @@ void ImageWidget::initializeGL()
m_transferOptions = std::unique_ptr<QOpenGLPixelTransferOptions>(new QOpenGLPixelTransferOptions); m_transferOptions = std::unique_ptr<QOpenGLPixelTransferOptions>(new QOpenGLPixelTransferOptions);
m_transferOptions->setAlignment(1); m_transferOptions->setAlignment(1);
if(m_rawImage)
setImage(m_rawImage, m_currentImg);
} }
void ImageWidget::dragEnterEvent(QDragEnterEvent *event) void ImageWidget::dragEnterEvent(QDragEnterEvent *event)
@@ -642,6 +649,19 @@ void ImageWidget::debayer()
f->glGenerateMipmap(GL_TEXTURE_2D); f->glGenerateMipmap(GL_TEXTURE_2D);
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
int size = std::max(m_imgWidth, m_imgHeight);
int level = 0;
while(size >>= 1)level++;
int w,h;
f3->glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &w);
f3->glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &h);
uint16_t pixel[w*h*4];
f3->glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_SHORT, pixel);
float maxRGB = std::max(std::max(pixel[0], pixel[1]), pixel[2]);
m_whiteBalance[0] = maxRGB / pixel[0];
m_whiteBalance[1] = maxRGB / pixel[1];
m_whiteBalance[2] = maxRGB / pixel[2];
} }
ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent) ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent)
+1
View File
@@ -52,6 +52,7 @@ class ImageWidget : public QOpenGLWidget
float m_range; float m_range;
float m_dx, m_dy; float m_dx, m_dy;
float m_scale; float m_scale;
float m_whiteBalance[3];
bool m_blockRepaint; bool m_blockRepaint;
bool m_bwImg; bool m_bwImg;
bool m_invert; bool m_invert;
+25 -7
View File
@@ -280,7 +280,7 @@ bool loadFITS(const QString path, ImageInfoData &info, RawImage **image)
char err[100]; char err[100];
fits_get_errstatus(status, err); fits_get_errstatus(status, err);
info.info.append({QObject::tr("Error"), QString(err)}); info.info.append({QObject::tr("Error"), QString(err)});
qDebug() << err; qDebug() << "Failed to load FITS file" << err;
} }
return true; return true;
@@ -297,7 +297,7 @@ bool loadPCLImage(pcl::XISFReader &xisf, RawImage **image)
#ifdef COLOR_MANAGMENT #ifdef COLOR_MANAGMENT
pcl::ICCProfile iccProfile = xisf.ReadICCProfile(); pcl::ICCProfile iccProfile = xisf.ReadICCProfile();
if(iccProfile.IsProfile()) if(iccProfile.IsProfile() && iccProfile != sRgbIccProfile)
{ {
pcl::ICCProfileTransformation iccTran; pcl::ICCProfileTransformation iccTran;
iccTran.DisableParallelProcessing(); iccTran.DisableParallelProcessing();
@@ -349,7 +349,15 @@ bool loadXISF(const QString &path, ImageInfoData &info, RawImage **image)
{ {
info.fitsHeader.append(fits); info.fitsHeader.append(fits);
} }
auto imageproperties = xisf.ReadImageProperties();
for(auto prop : imageproperties)
{
info.fitsHeader.append(prop);
}
info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader); info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader);
info.info.append({QObject::tr("Width"), QString::number(xisf.ImageInfo().width)});
info.info.append({QObject::tr("Height"), QString::number(xisf.ImageInfo().height)});
if(!info.wcs->valid())info.wcs.reset(); if(!info.wcs->valid())info.wcs.reset();
if(floatType && bps == 32) if(floatType && bps == 32)
@@ -368,7 +376,7 @@ bool loadXISF(const QString &path, ImageInfoData &info, RawImage **image)
catch (pcl::Error err) catch (pcl::Error err)
{ {
info.info.append(QPair<QString, QString>("Error", err.FormatInfo().ToUTF8().c_str())); info.info.append(QPair<QString, QString>("Error", err.FormatInfo().ToUTF8().c_str()));
qDebug() << err.FormatInfo().ToUTF8().c_str(); qDebug() << "Failed to load XISF" << err.FormatInfo().ToUTF8().c_str();
} }
info.info.append({QObject::tr("Error"), QObject::tr("Unsupported sample format")}); info.info.append({QObject::tr("Error"), QObject::tr("Unsupported sample format")});
return false; return false;
@@ -387,20 +395,22 @@ void LoadRunable::run()
RawImage *rawImage = nullptr; RawImage *rawImage = nullptr;
bool raw = false; bool raw = false;
timer.start();
if(m_file.endsWith(".CR2", Qt::CaseInsensitive) || m_file.endsWith(".NEF", Qt::CaseInsensitive) || m_file.endsWith(".DNG", Qt::CaseInsensitive)) if(m_file.endsWith(".CR2", Qt::CaseInsensitive) || m_file.endsWith(".NEF", Qt::CaseInsensitive) || m_file.endsWith(".DNG", Qt::CaseInsensitive))
{ {
timer.start();
loadRAW(m_file, info, &rawImage); loadRAW(m_file, info, &rawImage);
raw = true; raw = true;
qDebug() << "LoadRaw" << timer.elapsed(); qDebug() << "LoadRAW" << timer.elapsed();
} }
else if(m_file.endsWith(".FIT", Qt::CaseInsensitive) || m_file.endsWith(".FITS", Qt::CaseInsensitive)) else if(m_file.endsWith(".FIT", Qt::CaseInsensitive) || m_file.endsWith(".FITS", Qt::CaseInsensitive))
{ {
loadFITS(m_file, info, &rawImage); loadFITS(m_file, info, &rawImage);
qDebug() << "LoadFITS" << timer.elapsed();
} }
else if(m_file.endsWith(".XISF", Qt::CaseInsensitive)) else if(m_file.endsWith(".XISF", Qt::CaseInsensitive))
{ {
loadXISF(m_file, info, &rawImage); loadXISF(m_file, info, &rawImage);
qDebug() << "LoadXISF" << timer.elapsed();
} }
else else
{ {
@@ -426,8 +436,9 @@ void LoadRunable::run()
{ {
double mean, median, min, max, mad; double mean, median, min, max, mad;
double stdDev; double stdDev;
uint32_t saturated;
timer.start(); timer.start();
rawImage->imageStats(&mean, &stdDev, &median, &min, &max, &mad); rawImage->imageStats(&mean, &stdDev, &median, &min, &max, &mad, &saturated);
qDebug() << "image stats" << timer.restart(); qDebug() << "image stats" << timer.restart();
info.info.append({QObject::tr("Mean"), QString::number(mean)}); info.info.append({QObject::tr("Mean"), QString::number(mean)});
info.info.append({QObject::tr("Standart deviation"), QString::number(stdDev)}); info.info.append({QObject::tr("Standart deviation"), QString::number(stdDev)});
@@ -435,6 +446,7 @@ void LoadRunable::run()
info.info.append({QObject::tr("Minimum"), QString::number(min)}); info.info.append({QObject::tr("Minimum"), QString::number(min)});
info.info.append({QObject::tr("Maximum"), QString::number(max)}); info.info.append({QObject::tr("Maximum"), QString::number(max)});
info.info.append({QObject::tr("MAD"), QString::number(mad)}); info.info.append({QObject::tr("MAD"), QString::number(mad)});
info.info.append({QObject::tr("Saturated"), QString::number(100.0 * saturated / rawImage->size()) + "%"});
if(m_analyzeLevel >= Peaks) if(m_analyzeLevel >= Peaks)
{ {
@@ -452,7 +464,7 @@ void LoadRunable::run()
// drawPeaks(img, peaks); // drawPeaks(img, peaks);
qDebug() << "draw peaks" << timer.restart(); qDebug() << "draw peaks" << timer.restart();
info.info.append({QObject::tr("Peaks"), QString::number(numPeaks)}); info.info.append({QObject::tr("Peaks"), QString::number(numPeaks)});
info.info.append({QObject::tr("Peaks draw"), QString::number(peaks.size())}); //info.info.append({QObject::tr("Peaks draw"), QString::number(peaks.size())});
if(m_analyzeLevel>= Stars) if(m_analyzeLevel>= Stars)
{ {
@@ -530,6 +542,12 @@ bool readXISFHeader(const QString &path, ImageInfoData &info)
{ {
info.fitsHeader.append(fits); info.fitsHeader.append(fits);
} }
auto imageproperties = xisf.ReadImageProperties();
for(auto prop : imageproperties)
{
info.fitsHeader.append(prop);
}
info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader); info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader);
if(!info.wcs->valid())info.wcs.reset(); if(!info.wcs->valid())info.wcs.reset();
} }
+16 -16
View File
@@ -137,6 +137,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
fileMenu->addSeparator(); fileMenu->addSeparator();
fileMenu->addAction(tr("Index directory"), this, SLOT(indexDir())); fileMenu->addAction(tr("Index directory"), this, SLOT(indexDir()));
fileMenu->addAction(tr("Reindex files"), this, SLOT(reindex())); fileMenu->addAction(tr("Reindex files"), this, SLOT(reindex()));
fileMenu->addAction(tr("Export database to CSV"), this, &MainWindow::exportCSV);
fileMenu->addSeparator(); fileMenu->addSeparator();
QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, SLOT(liveMode(bool))); QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, SLOT(liveMode(bool)));
liveModeAction->setCheckable(true); liveModeAction->setCheckable(true);
@@ -153,8 +154,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
viewMenu->addAction(tr("Zoom Out"), m_imageGL, SLOT(zoomOut()), QKeySequence::ZoomOut); viewMenu->addAction(tr("Zoom Out"), m_imageGL, SLOT(zoomOut()), QKeySequence::ZoomOut);
viewMenu->addAction(tr("Best Fit"), m_imageGL, SLOT(bestFit()), QKeySequence("Ctrl+1")); viewMenu->addAction(tr("Best Fit"), m_imageGL, SLOT(bestFit()), QKeySequence("Ctrl+1"));
viewMenu->addAction(tr("100%"), m_imageGL, SLOT(oneToOne())); viewMenu->addAction(tr("100%"), m_imageGL, SLOT(oneToOne()));
viewMenu->addAction(tr("Fullscreen"), this, SLOT(toggleFullScreen()), Qt::CTRL + Qt::Key_F11);
QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), [this](bool checked){ QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), [this](bool checked){
if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails();
m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageNames()); m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageNames());
m_imageGL->imageWidget()->showThumbnail(checked); m_imageGL->imageWidget()->showThumbnail(checked);
m_imageGL->setThumbnails(checked ? m_ringList->imageCount() : 0); m_imageGL->setThumbnails(checked ? m_ringList->imageCount() : 0);
@@ -376,7 +377,6 @@ void MainWindow::copyOrMove(bool copy, const QString &dest)
QMessageBox::StandardButton button = QMessageBox::warning(this, t, QMessageBox::StandardButton button = QMessageBox::warning(this, t,
m.arg(srcFile.fileName()).arg(dir.absolutePath()), m.arg(srcFile.fileName()).arg(dir.absolutePath()),
QMessageBox::Ignore | QMessageBox::Abort); QMessageBox::Ignore | QMessageBox::Abort);
qDebug() << button;
if(button == QMessageBox::Abort)return; if(button == QMessageBox::Abort)return;
} }
progress.setValue(i++); progress.setValue(i++);
@@ -583,20 +583,6 @@ void MainWindow::deleteMarked()
m_database->clearMarkedFiles(); m_database->clearMarkedFiles();
} }
void MainWindow::toggleFullScreen()
{
if(isFullScreen())
{
showNormal();
if(_maximized)showMaximized();
}
else
{
_maximized = isMaximized();
showFullScreen();
}
}
void MainWindow::liveMode(bool active) void MainWindow::liveMode(bool active)
{ {
m_ringList->setLiveMode(active); m_ringList->setLiveMode(active);
@@ -626,9 +612,23 @@ void MainWindow::showMarkFilesDialog()
void MainWindow::showSettingsDialog() void MainWindow::showSettingsDialog()
{ {
SettingsDialog settingsDialog(this); SettingsDialog settingsDialog(this);
connect(&settingsDialog, &SettingsDialog::preloadChanged, m_ringList, &ImageRingList::setPreload);
settingsDialog.exec(); settingsDialog.exec();
} }
void MainWindow::exportCSV()
{
QStringList documentDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
if(documentDir.empty())documentDir.append("");
QString file = QFileDialog::getSaveFileName(this,
tr("Save as"),
documentDir.first(),
tr("CSV file (*.csv)"));
if(!file.isEmpty())
m_databaseView->exportCSV(file);
}
void MainWindow::updateWindowTitle() void MainWindow::updateWindowTitle()
{ {
ImagePtr ptr = m_ringList->currentImage(); ImagePtr ptr = m_ringList->currentImage();
+1 -1
View File
@@ -60,13 +60,13 @@ protected slots:
void copyMarked(); void copyMarked();
void moveMarked(); void moveMarked();
void deleteMarked(); void deleteMarked();
void toggleFullScreen();
void liveMode(bool active); void liveMode(bool active);
void imageStats(bool imageStats); void imageStats(bool imageStats);
void peakFinder(bool findPeaks); void peakFinder(bool findPeaks);
void starFinder(bool findStars); void starFinder(bool findStars);
void showMarkFilesDialog(); void showMarkFilesDialog();
void showSettingsDialog(); void showSettingsDialog();
void exportCSV();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H
+10 -1
View File
@@ -3,6 +3,7 @@
int THUMB_SIZE = 128; int THUMB_SIZE = 128;
int THUMB_SIZE_BORDER = 138; int THUMB_SIZE_BORDER = 138;
int THUMB_SIZE_BORDER_Y = 158; int THUMB_SIZE_BORDER_Y = 158;
double SATURATION = 0.95;
RawImage::ImgType CV2Type(int cvtype) RawImage::ImgType CV2Type(int cvtype)
{ {
@@ -84,6 +85,7 @@ RawImage::RawImage(const RawImage &d)
m_max = d.m_max; m_max = d.m_max;
m_mad = d.m_mad; m_mad = d.m_mad;
m_stats = d.m_stats; m_stats = d.m_stats;
m_saturated = d.m_saturated;
} }
RawImage::RawImage(const QImage &img) RawImage::RawImage(const QImage &img)
@@ -126,7 +128,7 @@ RawImage::RawImage(const QImage &img)
m_stats = false; m_stats = false;
} }
bool RawImage::imageStats(double *mean, double *stdDev, double *median, double *min, double *max, double *mad) bool RawImage::imageStats(double *mean, double *stdDev, double *median, double *min, double *max, double *mad, uint32_t *saturated)
{ {
if(!m_stats)calcStats(); if(!m_stats)calcStats();
if(mean)*mean = m_mean; if(mean)*mean = m_mean;
@@ -135,6 +137,7 @@ bool RawImage::imageStats(double *mean, double *stdDev, double *median, double *
if(min)*min = m_min; if(min)*min = m_min;
if(max)*max = m_max; if(max)*max = m_max;
if(mad)*mad = m_mad; if(mad)*mad = m_mad;
if(saturated)*saturated = m_saturated;
return true; return true;
} }
@@ -176,6 +179,12 @@ void RawImage::calcStats()
} }
} }
if(img.type() == CV_32F)m_median /= histSize; if(img.type() == CV_32F)m_median /= histSize;
int threshold = SATURATION * histSize;
m_saturated = 0;
for(int i = histSize-1; i >= threshold; i--)
m_saturated += hist.at<float>(0, i);
cv::Mat absDev; cv::Mat absDev;
img.convertTo(absDev, CV_32F, 1, -m_median); img.convertTo(absDev, CV_32F, 1, -m_median);
absDev = cv::abs(absDev); absDev = cv::abs(absDev);
+2 -1
View File
@@ -48,6 +48,7 @@ protected:
double m_max; double m_max;
double m_mad; double m_mad;
float m_thumbAspect; float m_thumbAspect;
uint32_t m_saturated;
public: public:
enum ImgType enum ImgType
{ {
@@ -66,7 +67,7 @@ public:
RawImage(cv::Mat &img); RawImage(cv::Mat &img);
RawImage(const RawImage &d); RawImage(const RawImage &d);
RawImage(const QImage &img); RawImage(const QImage &img);
bool imageStats(double *mean, double *stdDev, double *median, double *min, double *max, double *mad); bool imageStats(double *mean, double *stdDev, double *median, double *min, double *max, double *mad, uint32_t *saturated);
void calcStats(); void calcStats();
void rect(int &x, int &y, int w, int h, std::vector<double> &r) const; 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; int findPeaks(double background, double distance, std::vector<Peak> &peaks) const;
+25 -1
View File
@@ -7,6 +7,7 @@
#include "rawimage.h" #include "rawimage.h"
extern int DEFAULT_WIDTH; extern int DEFAULT_WIDTH;
extern double SATURATION;
class EvenNumber : public QSpinBox class EvenNumber : public QSpinBox
{ {
@@ -48,13 +49,21 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent)
m_thumSize->setValue(settings.value("settings/thumnailsize", THUMB_SIZE).toInt()); m_thumSize->setValue(settings.value("settings/thumnailsize", THUMB_SIZE).toInt());
m_thumSize->setToolTip(tr("Thumbnail size in pixels")); m_thumSize->setToolTip(tr("Thumbnail size in pixels"));
m_saturation = new QDoubleSpinBox(this);
m_saturation->setMinimum(0);
m_saturation->setMaximum(100);
m_saturation->setSuffix(" %");
m_saturation->setValue(settings.value("settings/saturation", SATURATION * 100.0).toDouble());
m_saturation->setToolTip(tr("Set threshold value that is considered saturated when showing statistics.\nFor RAW files you may set 22%"));
m_useNativeDialog = new QCheckBox(tr("Don't use native file dialog"), this); m_useNativeDialog = new QCheckBox(tr("Don't use native file dialog"), this);
m_useNativeDialog->setChecked(QApplication::testAttribute(Qt::AA_DontUseNativeDialogs)); m_useNativeDialog->setChecked(QApplication::testAttribute(Qt::AA_DontUseNativeDialogs));
layout->addRow(tr("Image preload count"), m_preloadImages); layout->addRow(tr("Image preload count"), m_preloadImages);
layout->addRow(tr("Thumbnails size"), m_thumSize); layout->addRow(tr("Thumbnails size"), m_thumSize);
layout->addRow(tr("Saturation"), m_saturation);
layout->addRow(m_useNativeDialog); layout->addRow(m_useNativeDialog);
layout->addRow(new QLabel(tr("Changes in settings will take effect after program restart."))); //layout->addRow(new QLabel(tr("Changes in settings will take effect after program restart.")));
QDialogButtonBox *buttonBox = new QDialogButtonBox(this); QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
@@ -75,11 +84,26 @@ void SettingsDialog::loadSettings()
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, settings.value("settings/dontusenativedialogs", false).toBool()); QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, settings.value("settings/dontusenativedialogs", false).toBool());
} }
bool SettingsDialog::loadThumbsizes()
{
QSettings settings;
int OLD_THUMB_SIZE = THUMB_SIZE;
THUMB_SIZE = settings.value("settings/thumbnailsize", THUMB_SIZE).toInt();
THUMB_SIZE_BORDER = THUMB_SIZE + 10;
THUMB_SIZE_BORDER_Y = THUMB_SIZE + 30;
SATURATION = settings.value("settings/saturation", 95.0).toDouble() / 100.0;
return OLD_THUMB_SIZE != THUMB_SIZE;
}
void SettingsDialog::saveSettings() void SettingsDialog::saveSettings()
{ {
QSettings settings; QSettings settings;
settings.setValue("settings/thumbnailsize", m_thumSize->value()); settings.setValue("settings/thumbnailsize", m_thumSize->value());
settings.setValue("settings/preloadimagecount", m_preloadImages->value()); settings.setValue("settings/preloadimagecount", m_preloadImages->value());
settings.setValue("settings/dontusenativedialogs", m_useNativeDialog->isChecked()); settings.setValue("settings/dontusenativedialogs", m_useNativeDialog->isChecked());
settings.setValue("settings/saturation", m_saturation->value());
SATURATION = m_saturation->value() / 100.0;
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, m_useNativeDialog->isChecked()); QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, m_useNativeDialog->isChecked());
if(DEFAULT_WIDTH != m_preloadImages->value())
emit preloadChanged(m_preloadImages->value());
} }
+4
View File
@@ -11,11 +11,15 @@ class SettingsDialog : public QDialog
public: public:
explicit SettingsDialog(QWidget *parent = nullptr); explicit SettingsDialog(QWidget *parent = nullptr);
static void loadSettings(); static void loadSettings();
static bool loadThumbsizes();
signals:
void preloadChanged(int witdth);
private: private:
void saveSettings(); void saveSettings();
QSpinBox *m_preloadImages; QSpinBox *m_preloadImages;
QSpinBox *m_thumSize; QSpinBox *m_thumSize;
QDoubleSpinBox *m_saturation;
QCheckBox *m_useNativeDialog; QCheckBox *m_useNativeDialog;
}; };
+3
View File
@@ -5,6 +5,7 @@ uniform vec3 mtf_param;
uniform bool bw; uniform bool bw;
uniform bool invert; uniform bool invert;
uniform bool srgb; uniform bool srgb;
uniform vec3 whiteBalance;
in vec2 qt_TexCoord0; in vec2 qt_TexCoord0;
out vec4 color; out vec4 color;
@@ -40,6 +41,8 @@ void main(void)
if(srgb)color.rgb = Linear2sRGB(color.rgb); if(srgb)color.rgb = Linear2sRGB(color.rgb);
color.rgb *= whiteBalance;
if(any(lessThan(qt_TexCoord0, vec2(0.0))) || any(greaterThan(qt_TexCoord0, vec2(1.0)))) if(any(lessThan(qt_TexCoord0, vec2(0.0))) || any(greaterThan(qt_TexCoord0, vec2(1.0))))
color = vec4(0.0, 0.0, 0.0, 1.0); color = vec4(0.0, 0.0, 0.0, 1.0);
+11
View File
@@ -48,6 +48,17 @@
</screenshots> </screenshots>
<content_rating type="oars-1.1"/> <content_rating type="oars-1.1"/>
<releases> <releases>
<release version="20221228" date="2022-12-28">
<description>
<ul>
<li>Add gray world white balance</li>
<li>Export database to CSV</li>
<li>Fine tune of STF when Shift key is pressed</li>
<li>Add saturation statistic</li>
<li>Various fixes</li>
</ul>
</description>
</release>
<release version="20221215" date="2022-12-15"> <release version="20221215" date="2022-12-15">
<description> <description>
<ul> <ul>
+26 -3
View File
@@ -21,6 +21,8 @@ STFSlider::STFSlider(QWidget *parent) : QWidget(parent)
m_midPoint = 0.5; m_midPoint = 0.5;
m_whitePoint = 1; m_whitePoint = 1;
m_grabbed = -1; m_grabbed = -1;
m_fineTune = false;
setToolTip(tr("Press Shift for fine tuning"));
} }
float STFSlider::blackPoint() const float STFSlider::blackPoint() const
@@ -94,20 +96,34 @@ void STFSlider::mouseMoveEvent(QMouseEvent *event)
else else
unsetCursor(); unsetCursor();
qreal x = (qreal)event->x()/width();
if(event->modifiers() & Qt::ShiftModifier && !m_fineTune)
{
m_fineTune = true;
m_fineTuneX = x;
}
if(!(event->modifiers() & Qt::ShiftModifier) && m_fineTune)
m_fineTune = false;
if(m_fineTune)
{
x = m_fineTuneX + (x - m_fineTuneX) * 0.2;
}
switch(m_grabbed) switch(m_grabbed)
{ {
case 0: case 0:
m_blackPoint = clamp((qreal)event->x()/width()); m_blackPoint = clamp(x);
m_whitePoint = std::max(m_whitePoint, m_blackPoint); m_whitePoint = std::max(m_whitePoint, m_blackPoint);
QToolTip::showText(event->globalPos(), QString::number(m_blackPoint), this); QToolTip::showText(event->globalPos(), QString::number(m_blackPoint), this);
break; break;
case 1: case 1:
m_midPoint = ((qreal)event->x()/width() - m_blackPoint) / (m_whitePoint - m_blackPoint); m_midPoint = (x - m_blackPoint) / (m_whitePoint - m_blackPoint);
m_midPoint = clamp(m_midPoint); m_midPoint = clamp(m_midPoint);
QToolTip::showText(event->globalPos(), QString::number(m_midPoint), this); QToolTip::showText(event->globalPos(), QString::number(m_midPoint), this);
break; break;
case 2: case 2:
m_whitePoint = clamp((qreal)event->x()/width()); m_whitePoint = clamp(x);
m_blackPoint = std::min(m_blackPoint, m_whitePoint); m_blackPoint = std::min(m_blackPoint, m_whitePoint);
QToolTip::showText(event->globalPos(), QString::number(m_whitePoint), this); QToolTip::showText(event->globalPos(), QString::number(m_whitePoint), this);
break; break;
@@ -121,6 +137,12 @@ void STFSlider::mouseMoveEvent(QMouseEvent *event)
void STFSlider::mousePressEvent(QMouseEvent *event) void STFSlider::mousePressEvent(QMouseEvent *event)
{ {
if(event->modifiers() & Qt::ShiftModifier)
{
m_fineTune = true;
m_fineTuneX = (qreal)event->x()/width();
}
if(std::abs((m_blackPoint + (m_whitePoint - m_blackPoint) * m_midPoint)*width() - event->x()) < 5) if(std::abs((m_blackPoint + (m_whitePoint - m_blackPoint) * m_midPoint)*width() - event->x()) < 5)
m_grabbed = 1; m_grabbed = 1;
else if(std::abs(m_blackPoint*width() - event->x()) < 5) else if(std::abs(m_blackPoint*width() - event->x()) < 5)
@@ -134,5 +156,6 @@ void STFSlider::mousePressEvent(QMouseEvent *event)
void STFSlider::mouseReleaseEvent(QMouseEvent *) void STFSlider::mouseReleaseEvent(QMouseEvent *)
{ {
m_grabbed = -1; m_grabbed = -1;
m_fineTune = false;
emit paramChanged(m_blackPoint, midPoint(), m_whitePoint); emit paramChanged(m_blackPoint, midPoint(), m_whitePoint);
} }
+2
View File
@@ -11,6 +11,8 @@ class STFSlider : public QWidget
float m_midPoint; float m_midPoint;
float m_whitePoint; float m_whitePoint;
int m_grabbed; int m_grabbed;
bool m_fineTune;
float m_fineTuneX;
public: public:
explicit STFSlider(QWidget *parent = nullptr); explicit STFSlider(QWidget *parent = nullptr);
float blackPoint() const; float blackPoint() const;
+1 -1
View File
@@ -49,7 +49,7 @@ void StretchToolbar::stretchImage(Image *img)
if(img->rawImage()) if(img->rawImage())
{ {
double median, mad, max; double median, mad, max;
img->rawImage()->imageStats(nullptr, nullptr, &median, nullptr, &max, &mad); img->rawImage()->imageStats(nullptr, nullptr, &median, nullptr, &max, &mad, nullptr);
median /= img->rawImage()->norm(); median /= img->rawImage()->norm();
mad /= img->rawImage()->norm(); mad /= img->rawImage()->norm();
max /= img->rawImage()->norm(); max /= img->rawImage()->norm();
Binary file not shown.
+32 -3
View File
@@ -204,7 +204,7 @@
</message> </message>
<message> <message>
<source>Fullscreen</source> <source>Fullscreen</source>
<translation>Fullscreen</translation> <translation type="vanished">Fullscreen</translation>
</message> </message>
<message> <message>
<source>Select</source> <source>Select</source>
@@ -316,7 +316,7 @@
</message> </message>
<message> <message>
<source>FITS header editor</source> <source>FITS header editor</source>
<translation>FITS header editor</translation> <translation type="vanished">FITS header editor</translation>
</message> </message>
<message> <message>
<source>Settings</source> <source>Settings</source>
@@ -374,6 +374,14 @@
<source>Moving marked files to trash</source> <source>Moving marked files to trash</source>
<translation>Moving marked files to trash</translation> <translation>Moving marked files to trash</translation>
</message> </message>
<message>
<source>Export database to CSV</source>
<translation>Export database to CSV file</translation>
</message>
<message>
<source>CSV file (*.csv)</source>
<translation>CSV files (*.csv)</translation>
</message>
</context> </context>
<context> <context>
<name>MarkedFiles</name> <name>MarkedFiles</name>
@@ -450,7 +458,7 @@
</message> </message>
<message> <message>
<source>Peaks draw</source> <source>Peaks draw</source>
<translation>Peaks draw</translation> <translation type="vanished">Peaks draw</translation>
</message> </message>
<message> <message>
<source>FWHM X</source> <source>FWHM X</source>
@@ -464,6 +472,17 @@
<source>Unsupported sample format</source> <source>Unsupported sample format</source>
<translation>Unsupported sample format</translation> <translation>Unsupported sample format</translation>
</message> </message>
<message>
<source>Saturated</source>
<translation>Saturated</translation>
</message>
</context>
<context>
<name>STFSlider</name>
<message>
<source>Press Shift for fine tuning</source>
<translation>Press Shift for fine tuning</translation>
</message>
</context> </context>
<context> <context>
<name>SelectColumnsDialog</name> <name>SelectColumnsDialog</name>
@@ -502,6 +521,16 @@
<source>Don&apos;t use native file dialog</source> <source>Don&apos;t use native file dialog</source>
<translation>Don&apos;t use native file dialog</translation> <translation>Don&apos;t use native file dialog</translation>
</message> </message>
<message>
<source>Set threshold value that is considered saturated when showing statistics.
For RAW files you may set 22%</source>
<translation>Set threshold value that is considered saturated when showing statistics.
For RAW files you may set 22%</translation>
</message>
<message>
<source>Saturation</source>
<translation>Saturated</translation>
</message>
</context> </context>
<context> <context>
<name>StretchToolbar</name> <name>StretchToolbar</name>
Binary file not shown.
+32 -3
View File
@@ -204,7 +204,7 @@
</message> </message>
<message> <message>
<source>Fullscreen</source> <source>Fullscreen</source>
<translation>Plein écran</translation> <translation type="vanished">Plein écran</translation>
</message> </message>
<message> <message>
<source>Select</source> <source>Select</source>
@@ -316,7 +316,7 @@
</message> </message>
<message> <message>
<source>FITS header editor</source> <source>FITS header editor</source>
<translation>Éditeur d&apos;en-tête FITS</translation> <translation type="vanished">Éditeur d&apos;en-tête FITS</translation>
</message> </message>
<message> <message>
<source>Settings</source> <source>Settings</source>
@@ -374,6 +374,14 @@
<source>Moving marked files to trash</source> <source>Moving marked files to trash</source>
<translation>Déplacement des fichiers marqués dans la corbeille</translation> <translation>Déplacement des fichiers marqués dans la corbeille</translation>
</message> </message>
<message>
<source>Export database to CSV</source>
<translation>Exporter la base de données vers un fichier CSV</translation>
</message>
<message>
<source>CSV file (*.csv)</source>
<translation>Fichiers CSV (*.csv)</translation>
</message>
</context> </context>
<context> <context>
<name>MarkedFiles</name> <name>MarkedFiles</name>
@@ -450,7 +458,7 @@
</message> </message>
<message> <message>
<source>Peaks draw</source> <source>Peaks draw</source>
<translation>Dessin des pic</translation> <translation type="vanished">Dessin des pic</translation>
</message> </message>
<message> <message>
<source>FWHM X</source> <source>FWHM X</source>
@@ -464,6 +472,17 @@
<source>Unsupported sample format</source> <source>Unsupported sample format</source>
<translation>Format non pris en charge</translation> <translation>Format non pris en charge</translation>
</message> </message>
<message>
<source>Saturated</source>
<translation>Saturé</translation>
</message>
</context>
<context>
<name>STFSlider</name>
<message>
<source>Press Shift for fine tuning</source>
<translation>Appuyez sur Shift pour un réglage fin</translation>
</message>
</context> </context>
<context> <context>
<name>SelectColumnsDialog</name> <name>SelectColumnsDialog</name>
@@ -502,6 +521,16 @@
<source>Don&apos;t use native file dialog</source> <source>Don&apos;t use native file dialog</source>
<translation>N&apos;utilisez pas la boîte de dialogue de fichier natif</translation> <translation>N&apos;utilisez pas la boîte de dialogue de fichier natif</translation>
</message> </message>
<message>
<source>Set threshold value that is considered saturated when showing statistics.
For RAW files you may set 22%</source>
<translation>Définissez la valeur seuil qui est considérée comme saturée lors de l&apos;affichage des statistiques.
Pour les fichiers RAW, vous pouvez définir 22&#xa0;%</translation>
</message>
<message>
<source>Saturation</source>
<translation>Saturé</translation>
</message>
</context> </context>
<context> <context>
<name>StretchToolbar</name> <name>StretchToolbar</name>
Binary file not shown.
+32 -3
View File
@@ -201,7 +201,7 @@
</message> </message>
<message> <message>
<source>Fullscreen</source> <source>Fullscreen</source>
<translation>Celá obrazovka</translation> <translation type="vanished">Celá obrazovka</translation>
</message> </message>
<message> <message>
<source>Select</source> <source>Select</source>
@@ -317,7 +317,7 @@
</message> </message>
<message> <message>
<source>FITS header editor</source> <source>FITS header editor</source>
<translation>Editor FITS hlavičky</translation> <translation type="vanished">Editor FITS hlavičky</translation>
</message> </message>
<message> <message>
<source>Settings</source> <source>Settings</source>
@@ -375,6 +375,14 @@
<source>Moving marked files to trash</source> <source>Moving marked files to trash</source>
<translation>Presúvanie do koša</translation> <translation>Presúvanie do koša</translation>
</message> </message>
<message>
<source>Export database to CSV</source>
<translation>Exportovať databázu do CSV súboru</translation>
</message>
<message>
<source>CSV file (*.csv)</source>
<translation>Súbory CSV (*.csv)</translation>
</message>
</context> </context>
<context> <context>
<name>MarkedFiles</name> <name>MarkedFiles</name>
@@ -455,7 +463,7 @@
</message> </message>
<message> <message>
<source>Peaks draw</source> <source>Peaks draw</source>
<translation>Vykreslené vrcholky</translation> <translation type="vanished">Vykreslené vrcholky</translation>
</message> </message>
<message> <message>
<source>FWHM X</source> <source>FWHM X</source>
@@ -465,6 +473,17 @@
<source>FWHM Y</source> <source>FWHM Y</source>
<translation>FWHM Y</translation> <translation>FWHM Y</translation>
</message> </message>
<message>
<source>Saturated</source>
<translation>Saturované</translation>
</message>
</context>
<context>
<name>STFSlider</name>
<message>
<source>Press Shift for fine tuning</source>
<translation>Stlačte Shift pre jemné ladenie</translation>
</message>
</context> </context>
<context> <context>
<name>SelectColumnsDialog</name> <name>SelectColumnsDialog</name>
@@ -503,6 +522,16 @@
<source>Don&apos;t use native file dialog</source> <source>Don&apos;t use native file dialog</source>
<translation>Nepoužívať natívny súborový dialóg</translation> <translation>Nepoužívať natívny súborový dialóg</translation>
</message> </message>
<message>
<source>Set threshold value that is considered saturated when showing statistics.
For RAW files you may set 22%</source>
<translation>Nastavuje prahovú hodnotu ktorá sa považuje za saturovanú.
Pre RAW súbory možno treba nastaviť 22%</translation>
</message>
<message>
<source>Saturation</source>
<translation>Saturované</translation>
</message>
</context> </context>
<context> <context>
<name>StretchToolbar</name> <name>StretchToolbar</name>