Refractor ImageScrollArea

This commit is contained in:
2024-09-17 12:30:49 +02:00
parent efd3ff35f3
commit 30960033c5
8 changed files with 273 additions and 340 deletions
+2 -2
View File
@@ -38,8 +38,8 @@ set(TENMON_SRC
histogram.cpp histogram.h histogram.cpp histogram.h
imageinfo.cpp imageinfo.h imageinfo.cpp imageinfo.h
imageringlist.cpp imageringlist.h imageringlist.cpp imageringlist.h
imagescrollarea.cpp imagescrollarea.cpp imagescrollarea.h
imagescrollareagl.cpp imagescrollareagl.h imagewidget.h imagewidget.cpp
loadrunable.cpp loadrunable.h loadrunable.cpp loadrunable.h
main.cpp main.cpp
mainwindow.cpp mainwindow.h mainwindow.cpp mainwindow.h
+2 -1
View File
@@ -14,8 +14,9 @@ class FilesystemWidget : public QWidget
public: public:
explicit FilesystemWidget(QAbstractItemModel *model, QWidget *parent = nullptr); explicit FilesystemWidget(QAbstractItemModel *model, QWidget *parent = nullptr);
void contextMenuEvent(QContextMenuEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override;
private slots: public slots:
void selectFile(int row); void selectFile(int row);
protected slots:
void fileClicked(const QModelIndex &index, const QModelIndex &); void fileClicked(const QModelIndex &index, const QModelIndex &);
signals: signals:
void fileSelected(int row); void fileSelected(int row);
+114 -87
View File
@@ -1,121 +1,148 @@
#include "imagescrollarea.h" #include "imagescrollarea.h"
#include <QMouseEvent> #include "imageringlist.h"
#include <QScrollBar>
#include <QKeyEvent>
#include <QPalette>
#include <QDebug> #include <QDebug>
#include <QKeyEvent>
#include <QGridLayout>
#include <QMimeData>
#include <QMessageBox>
#include <QCoreApplication>
#include <QPainter>
#include <QFileInfo>
#include <QScrollBar>
#include <cmath>
ImageScrollArea::ImageScrollArea(QWidget *parent) : QScrollArea(parent), ImageScrollArea::ImageScrollArea(Database *database, QWidget *parent) : QWidget(parent)
m_scale(-1)
{ {
m_label = new QLabel(this); QGridLayout *layout = new QGridLayout(this);
setWidget(m_label); setLayout(layout);
setAlignment(Qt::AlignCenter);
setBackgroundRole(QPalette::Dark); ImageWidgetGL *imageWidgetGL = new ImageWidgetGL(database, this);
m_imageWidget = imageWidgetGL;
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
layout->setSpacing(0);
layout->addWidget(dynamic_cast<ImageWidgetGL*>(m_imageWidget), 0, 0);
layout->addWidget(m_verticalScrollBar, 0, 1);
layout->addWidget(m_horizontalScrollBar, 1, 0);
connect(m_verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
connect(m_horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
if(imageWidgetGL)
{
connect(imageWidgetGL, &ImageWidgetGL::fileDropped, this, &ImageScrollArea::fileDropped);
connect(imageWidgetGL, &ImageWidgetGL::status, this, &ImageScrollArea::status);
connect(imageWidgetGL, &ImageWidgetGL::scrollBarsUpdate, this, &ImageScrollArea::updateScrollbars);
}
} }
void ImageScrollArea::setImage(const QPixmap &img) ImageScrollArea::~ImageScrollArea()
{ {
m_pixmap = img;
QPixmap pix; }
if(m_scale < 0)
pix = img.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); void ImageScrollArea::allocateThumbnails(const QStringList &paths)
{
m_imageWidget->allocateThumbnails(paths);
}
void ImageScrollArea::showThumbnail(bool enable)
{
m_imageWidget->showThumbnail(enable);
}
void ImageScrollArea::setBayerMask(int mask)
{
m_imageWidget->setBayerMask(mask);
}
void ImageScrollArea::updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV)
{
if(maxH > 0)
{
m_horizontalScrollBar->show();
m_horizontalScrollBar->setRange(0, maxH);
m_horizontalScrollBar->setPageStep(stepH);
m_horizontalScrollBar->setValue(valueH);
}
else else
pix = img.scaled(img.size() * m_scale, Qt::KeepAspectRatio, Qt::SmoothTransformation); m_horizontalScrollBar->hide();
m_label->setPixmap(pix); if(maxV > 0)
m_label->resize(pix.size()); {
m_verticalScrollBar->show();
horizontalScrollBar()->setValue(horizontalScrollBar()->maximum() / 2); m_verticalScrollBar->setRange(0, maxV);
verticalScrollBar()->setValue(verticalScrollBar()->maximum() / 2); m_verticalScrollBar->setPageStep(stepV);
} m_verticalScrollBar->setValue(valueV);
}
void ImageScrollArea::setScale(float scale) else
{ m_verticalScrollBar->hide();
if(scale > 4 || (scale < 0.2 && scale > 0) || m_pixmap.isNull())
return;
m_scale = scale;
QSize newSize = m_scale < 0 ? size() : m_pixmap.size()*scale;
m_label->setPixmap(m_pixmap.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_label->resize(newSize);
} }
void ImageScrollArea::zoomIn() void ImageScrollArea::zoomIn()
{ {
if(m_scale < 0) m_imageWidget->zoom(1);
m_scale = (float)size().width()/m_pixmap.size().width();
setScale(m_scale + 0.1);
} }
void ImageScrollArea::zoomOut() void ImageScrollArea::zoomOut()
{ {
if(m_scale < 0) m_imageWidget->zoom(-1);
m_scale = (float)size().width()/m_pixmap.size().width();
setScale(m_scale - 0.1);
} }
void ImageScrollArea::bestFit() void ImageScrollArea::bestFit()
{ {
setScale(-1); m_horizontalScrollBar->hide();
m_verticalScrollBar->hide();
m_imageWidget->bestFit();
} }
void ImageScrollArea::oneToOne() void ImageScrollArea::oneToOne()
{ {
setScale(1); m_imageWidget->zoom(0);
} }
void ImageScrollArea::keyPressEvent(QKeyEvent *event) void ImageScrollArea::imageLoaded(Image *image)
{ {
event->ignore(); if(image && image->rawImage())
}
void ImageScrollArea::keyReleaseEvent(QKeyEvent *event)
{
event->ignore();
}
void ImageScrollArea::mouseMoveEvent(QMouseEvent *event)
{
QPoint delta = m_lastPos - event->pos();
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + delta.x());
verticalScrollBar()->setValue(verticalScrollBar()->value() + delta.y());
m_lastPos = event->pos();
}
void ImageScrollArea::mousePressEvent(QMouseEvent *event)
{
m_lastPos = event->pos();
}
void ImageScrollArea::resizeEvent(QResizeEvent *event)
{
if(m_scale < 0 && !m_pixmap.isNull())
{ {
m_label->setPixmap(m_pixmap.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); m_imageWidget->setImage(image->rawImage(), image->number());
m_label->resize(event->size()); m_imageWidget->setWCS(image->info().wcs);
} }
QScrollArea::resizeEvent(event);
} }
void ImageScrollArea::wheelEvent(QWheelEvent *event) void ImageScrollArea::thumbnailLoaded(const Image *image)
{ {
if(m_scale < 0) m_imageWidget->thumbnailLoaded(image);
m_scale = (float)size().width()/m_pixmap.size().width(); }
QPointF top(horizontalScrollBar()->value(), verticalScrollBar()->value()); void ImageScrollArea::setMTFParams(const MTFParam &params)
QPointF mousePos = (top + event->position()) / m_scale; {
m_imageWidget->setMTFParams(params);
QPoint delta = event->angleDelta(); }
if(delta.y() > 0)
setScale(m_scale + 0.1); void ImageScrollArea::invert(bool enable)
else {
setScale(m_scale - 0.1); m_imageWidget->invert(enable);
}
mousePos *= m_scale;
top = mousePos - event->position(); void ImageScrollArea::superPixel(bool enable)
horizontalScrollBar()->setValue(top.x()); {
verticalScrollBar()->setValue(top.y()); m_imageWidget->superPixel(enable);
}
void ImageScrollArea::falseColor(bool enable)
{
m_imageWidget->falseColor(enable);
}
QImage ImageScrollArea::renderToImage()
{
return m_imageWidget->renderToImage();
}
void ImageScrollArea::scrollEvent()
{
m_imageWidget->setOffset(m_horizontalScrollBar->value(), m_verticalScrollBar->value());
} }
+26 -17
View File
@@ -1,32 +1,41 @@
#ifndef IMAGESCROLLAREA_H #ifndef IMAGESCROLLAREA_H
#define IMAGESCROLLAREA_H #define IMAGESCROLLAREA_H
#include <QScrollArea> #include "imagewidget.h"
#include <QLabel>
class ImageScrollArea : public QScrollArea class ImageScrollArea : public QWidget
{ {
Q_OBJECT Q_OBJECT
QPoint m_lastPos; QScrollBar *m_verticalScrollBar;
QLabel *m_label; QScrollBar *m_horizontalScrollBar;
QPixmap m_pixmap; ImageWidget *m_imageWidget;
float m_scale;
public: public:
explicit ImageScrollArea(QWidget *parent = 0); explicit ImageScrollArea(Database *database, QWidget *parent = nullptr);
void setImage(const QPixmap &img); ~ImageScrollArea();
void setScale(float scale);
void allocateThumbnails(const QStringList &paths);
void showThumbnail(bool enable);
void setBayerMask(int mask);
protected:
void updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
public slots: public slots:
void zoomIn(); void zoomIn();
void zoomOut(); void zoomOut();
void bestFit(); void bestFit();
void oneToOne(); void oneToOne();
protected: void imageLoaded(Image *image);
void keyPressEvent(QKeyEvent *event) override; void thumbnailLoaded(const Image *image);
void keyReleaseEvent(QKeyEvent *event) override; void setMTFParams(const MTFParam &params);
void mouseMoveEvent(QMouseEvent *event) override; void invert(bool enable);
void mousePressEvent(QMouseEvent *event) override; void superPixel(bool enable);
void resizeEvent(QResizeEvent *event) override; void falseColor(bool enable);
void wheelEvent(QWheelEvent *event) override; QImage renderToImage();
protected slots:
void scrollEvent();
signals:
void fileDropped(const QString &path);
void status(const QString &value, const QString &pixelCoords, const QString &celestialCoords);
void scrollBarsUpdate(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
}; };
#endif // IMAGESCROLLAREA_H #endif // IMAGESCROLLAREA_H
+57 -147
View File
@@ -1,21 +1,15 @@
#include "imagescrollareagl.h" #include "imagewidget.h"
#include <QOpenGLFunctions>
#include <QOpenGLVersionFunctionsFactory>
#include <QDebug>
#include <QKeyEvent>
#include <QOpenGLDebugLogger>
#include <QOpenGLPixelTransferOptions>
#include <QOpenGLFramebufferObject>
#include <QGridLayout>
#include <QMimeData>
#include <QMessageBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QPainter> #include <QMessageBox>
#include <QFileInfo> #include <QTimer>
#include <cmath>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QFloat16> #include <QOpenGLFramebufferObject>
#include <lcms2.h> #include <QOpenGLExtraFunctions>
#include <QOpenGLDebugLogger>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QPainter>
#include "imageringlist.h"
int FILTERING = 1; int FILTERING = 1;
bool OpenGLES = false; bool OpenGLES = false;
@@ -74,8 +68,8 @@ RawImageType getRawImageType(const RawImage *img)
return type; return type;
} }
ImageWidget::ImageWidget(Database *database, QWidget *parent) : QOpenGLWidget(parent) ImageWidgetGL::ImageWidgetGL(Database *database, QWidget *parent) : QOpenGLWidget(parent)
, m_database(database) , m_database(database)
{ {
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
m_updateTimer = new QTimer(this); m_updateTimer = new QTimer(this);
@@ -87,19 +81,19 @@ ImageWidget::ImageWidget(Database *database, QWidget *parent) : QOpenGLWidget(pa
if(!isValid()) if(!isValid())
{ {
QMessageBox::critical(this, tr("OpenGL error"), tr("Could not initialize OpenGL 3.3 context. Ensure that proper GPU driver is installed.")); QMessageBox::critical(this, tr("OpenGL error"), tr("Could not initialize OpenGL 3.3 context. Ensure that proper GPU driver is installed."));
QCoreApplication::exit(-1); QCoreApplication::exit(-1);
} }
}); });
setMouseTracking(true); setMouseTracking(true);
} }
ImageWidget::~ImageWidget() ImageWidgetGL::~ImageWidgetGL()
{ {
makeCurrent(); makeCurrent();
} }
void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index) void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
{ {
m_currentImg = index; m_currentImg = index;
@@ -174,12 +168,12 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
else setOffset(m_dx, m_dy); else setOffset(m_dx, m_dy);
} }
void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs) void ImageWidgetGL::setWCS(std::shared_ptr<WCSData> wcs)
{ {
m_wcs = wcs; m_wcs = wcs;
} }
void ImageWidget::zoom(int zoom, const QPointF &mousePos) void ImageWidgetGL::zoom(int zoom, const QPointF &mousePos)
{ {
m_bestFit = false; m_bestFit = false;
if(zoom != 0) if(zoom != 0)
@@ -203,14 +197,14 @@ void ImageWidget::zoom(int zoom, const QPointF &mousePos)
setOffset(m_dx * r + focus.x() * (r - 1), m_dy * r + focus.y() * (r - 1)); setOffset(m_dx * r + focus.x() * (r - 1), m_dy * r + focus.y() * (r - 1));
} }
void ImageWidget::bestFit() void ImageWidgetGL::bestFit()
{ {
m_bestFit = true; m_bestFit = true;
m_scale = std::min((float)m_width/m_imgWidth, (float)m_height/m_imgHeight); m_scale = std::min((float)m_width/m_imgWidth, (float)m_height/m_imgHeight);
setOffset(0, 0); setOffset(0, 0);
} }
void ImageWidget::allocateThumbnails(const QStringList &paths) void ImageWidgetGL::allocateThumbnails(const QStringList &paths)
{ {
makeCurrent(); makeCurrent();
int count = paths.size(); int count = paths.size();
@@ -234,7 +228,7 @@ void ImageWidget::allocateThumbnails(const QStringList &paths)
m_thumbnailTexture->allocateStorage(); m_thumbnailTexture->allocateStorage();
} }
QVector2D ImageWidget::getImagePixelCoord(const QVector2D &pos) QVector2D ImageWidgetGL::getImagePixelCoord(const QVector2D &pos)
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
@@ -247,7 +241,7 @@ QVector2D ImageWidget::getImagePixelCoord(const QVector2D &pos)
return (pos + offset) / m_scale; return (pos + offset) / m_scale;
} }
void ImageWidget::setBayerMask(int mask) void ImageWidgetGL::setBayerMask(int mask)
{ {
m_firstRed[0] = mask & 0x1; m_firstRed[0] = mask & 0x1;
m_firstRed[1] = (mask & 0x2) >> 1; m_firstRed[1] = (mask & 0x2) >> 1;
@@ -259,13 +253,13 @@ void ImageWidget::setBayerMask(int mask)
update(); update();
} }
void ImageWidget::setMTFParams(const MTFParam &params) void ImageWidgetGL::setMTFParams(const MTFParam &params)
{ {
m_mtfParams = params; m_mtfParams = params;
update(); update();
} }
void ImageWidget::setOffset(float dx, float dy) void ImageWidgetGL::setOffset(float dx, float dy)
{ {
m_dx = std::clamp(dx, 0.0f, std::max(0.0f, m_imgWidth * m_scale - m_width)); m_dx = std::clamp(dx, 0.0f, std::max(0.0f, m_imgWidth * m_scale - m_width));
if(m_showThumbnails) if(m_showThumbnails)
@@ -276,25 +270,25 @@ void ImageWidget::setOffset(float dx, float dy)
update(); update();
} }
void ImageWidget::superPixel(bool enable) void ImageWidgetGL::superPixel(bool enable)
{ {
m_superpixel = enable; m_superpixel = enable;
update(); update();
} }
void ImageWidget::invert(bool enable) void ImageWidgetGL::invert(bool enable)
{ {
m_invert = enable; m_invert = enable;
update(); update();
} }
void ImageWidget::falseColor(bool enable) void ImageWidgetGL::falseColor(bool enable)
{ {
m_falseColor = enable; m_falseColor = enable;
update(); update();
} }
QImage ImageWidget::renderToImage() QImage ImageWidgetGL::renderToImage()
{ {
if(m_imgWidth < 0)return QImage(); if(m_imgWidth < 0)return QImage();
makeCurrent(); makeCurrent();
@@ -302,6 +296,7 @@ QImage ImageWidget::renderToImage()
fbo.bind(); fbo.bind();
f->glViewport(0, 0, m_imgWidth, m_imgHeight); f->glViewport(0, 0, m_imgWidth, m_imgHeight);
m_vao->bind();
m_program->bind(); m_program->bind();
m_program->setUniformValue("viewport", (float)m_imgWidth, (float)m_imgHeight); m_program->setUniformValue("viewport", (float)m_imgWidth, (float)m_imgHeight);
@@ -309,16 +304,20 @@ QImage ImageWidget::renderToImage()
m_program->setUniformValue("zoom", 1.0f); m_program->setUniformValue("zoom", 1.0f);
if(m_superpixel && m_debayerTex) if(m_superpixel && m_debayerTex)
{
f->glActiveTexture(GL_TEXTURE0);
f->glBindTexture(GL_TEXTURE_2D, m_debayerTex); f->glBindTexture(GL_TEXTURE_2D, m_debayerTex);
}
else else
m_image->bind(0); m_image->bind(0);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_vao->release();
fbo.bindDefault(); fbo.bindDefault();
return fbo.toImage(true); return fbo.toImage(true);
} }
void ImageWidget::thumbnailLoaded(const Image *image) void ImageWidgetGL::thumbnailLoaded(const Image *image)
{ {
if(image->number() >= m_maxArrayLayers) if(image->number() >= m_maxArrayLayers)
return; return;
@@ -336,13 +335,13 @@ void ImageWidget::thumbnailLoaded(const Image *image)
if(!m_updateTimer->isActive())m_updateTimer->start(); if(!m_updateTimer->isActive())m_updateTimer->start();
} }
void ImageWidget::showThumbnail(bool enable) void ImageWidgetGL::showThumbnail(bool enable)
{ {
m_showThumbnails = enable; m_showThumbnails = enable;
setOffset(m_dx, m_dy); setOffset(m_dx, m_dy);
} }
void ImageWidget::paintGL() void ImageWidgetGL::paintGL()
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
@@ -455,7 +454,7 @@ void ImageWidget::paintGL()
} }
void ImageWidget::resizeGL(int w, int h) void ImageWidgetGL::resizeGL(int w, int h)
{ {
m_width = w; m_width = w;
m_height = h; m_height = h;
@@ -464,7 +463,7 @@ void ImageWidget::resizeGL(int w, int h)
updateScrollBars(); updateScrollBars();
} }
void ImageWidget::initializeGL() void ImageWidgetGL::initializeGL()
{ {
f = context()->functions(); f = context()->functions();
fx = context()->extraFunctions(); fx = context()->extraFunctions();
@@ -483,11 +482,11 @@ void ImageWidget::initializeGL()
if(OpenGLES) if(OpenGLES)
{ {
src = "#version 300 es\n" src = "#version 300 es\n"
"precision highp float;\n" "precision highp float;\n"
"precision highp sampler2D;\n" "precision highp sampler2D;\n"
"precision highp sampler2DArray;\n" "precision highp sampler2DArray;\n"
"precision highp sampler3D;\n" "precision highp sampler3D;\n"
"#line 1\n"; "#line 1\n";
} }
else else
{ {
@@ -507,9 +506,9 @@ void ImageWidget::initializeGL()
logger->initialize(); logger->initialize();
logger->startLogging(); logger->startLogging();
connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage &message) connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage &message)
{ {
qDebug() << message; qDebug() << message;
}); });
qDebug() << "Vendor:" << (char*)f->glGetString(GL_VENDOR); qDebug() << "Vendor:" << (char*)f->glGetString(GL_VENDOR);
qDebug() << "Renderer:" << (char*)f->glGetString(GL_RENDERER); qDebug() << "Renderer:" << (char*)f->glGetString(GL_RENDERER);
@@ -524,9 +523,9 @@ void ImageWidget::initializeGL()
// each vertex is x,y 2D position and s,t texture coordinates // each vertex is x,y 2D position and s,t texture coordinates
float vertexs[] = {-1.0f, -1.0f, 0.0f, 1.0f, float vertexs[] = {-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f,}; 1.0f, 1.0f, 1.0f, 0.0f,};
m_buffer = std::unique_ptr<QOpenGLBuffer>(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)); m_buffer = std::unique_ptr<QOpenGLBuffer>(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
m_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw); m_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
m_buffer->create(); m_buffer->create();
@@ -616,13 +615,13 @@ void ImageWidget::initializeGL()
setImage(m_rawImage, m_currentImg); setImage(m_rawImage, m_currentImg);
} }
void ImageWidget::dragEnterEvent(QDragEnterEvent *event) void ImageWidgetGL::dragEnterEvent(QDragEnterEvent *event)
{ {
if(event->mimeData()->hasUrls() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction)) if(event->mimeData()->hasUrls() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction))
event->acceptProposedAction(); event->acceptProposedAction();
} }
void ImageWidget::dropEvent(QDropEvent *event) void ImageWidgetGL::dropEvent(QDropEvent *event)
{ {
if(event->mimeData()->hasUrls() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction)) if(event->mimeData()->hasUrls() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction))
{ {
@@ -639,7 +638,7 @@ void ImageWidget::dropEvent(QDropEvent *event)
event->ignore(); event->ignore();
} }
void ImageWidget::mousePressEvent(QMouseEvent *event) void ImageWidgetGL::mousePressEvent(QMouseEvent *event)
{ {
if(m_showThumbnails && event->button() == Qt::LeftButton && event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) if(m_showThumbnails && event->button() == Qt::LeftButton && event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier))
m_selecting = true; m_selecting = true;
@@ -655,7 +654,7 @@ void ImageWidget::mousePressEvent(QMouseEvent *event)
} }
} }
void ImageWidget::mouseMoveEvent(QMouseEvent *event) void ImageWidgetGL::mouseMoveEvent(QMouseEvent *event)
{ {
if(m_selecting) if(m_selecting)
{ {
@@ -690,7 +689,7 @@ void ImageWidget::mouseMoveEvent(QMouseEvent *event)
} }
} }
void ImageWidget::mouseReleaseEvent(QMouseEvent *event) void ImageWidgetGL::mouseReleaseEvent(QMouseEvent *event)
{ {
if(m_selecting) if(m_selecting)
{ {
@@ -721,7 +720,7 @@ void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
} }
} }
void ImageWidget::wheelEvent(QWheelEvent *event) void ImageWidgetGL::wheelEvent(QWheelEvent *event)
{ {
if(m_showThumbnails) if(m_showThumbnails)
{ {
@@ -734,7 +733,7 @@ void ImageWidget::wheelEvent(QWheelEvent *event)
} }
} }
void ImageWidget::thumbSelect(QMouseEvent *event) void ImageWidgetGL::thumbSelect(QMouseEvent *event)
{ {
QPoint p = event->pos(); QPoint p = event->pos();
const int off = (THUMB_SIZE_BORDER - THUMB_SIZE) / 2; const int off = (THUMB_SIZE_BORDER - THUMB_SIZE) / 2;
@@ -763,7 +762,7 @@ void ImageWidget::thumbSelect(QMouseEvent *event)
} }
} }
void ImageWidget::debayer() void ImageWidgetGL::debayer()
{ {
if(m_debayerTex > 0 || !m_superpixel || !m_bwImg || m_imgWidth < 0)return; if(m_debayerTex > 0 || !m_superpixel || !m_bwImg || m_imgWidth < 0)return;
@@ -786,99 +785,10 @@ void ImageWidget::debayer()
f->glGenerateMipmap(GL_TEXTURE_2D); f->glGenerateMipmap(GL_TEXTURE_2D);
} }
void ImageWidget::updateScrollBars() void ImageWidgetGL::updateScrollBars()
{ {
if(m_showThumbnails) if(m_showThumbnails)
emit scrollBarsUpdate(0, 0, -1, m_dy, m_height, (m_thumbnailCount / (m_width / THUMB_SIZE_BORDER) + 2) * THUMB_SIZE_BORDER_Y - m_height); emit scrollBarsUpdate(0, 0, -1, m_dy, m_height, (m_thumbnailCount / (m_width / THUMB_SIZE_BORDER) + 2) * THUMB_SIZE_BORDER_Y - m_height);
else else
emit scrollBarsUpdate(m_dx, m_width, m_imgWidth * m_scale - m_width, m_dy, m_height, m_imgHeight * m_scale - m_height); emit scrollBarsUpdate(m_dx, m_width, m_imgWidth * m_scale - m_width, m_dy, m_height, m_imgHeight * m_scale - m_height);
} }
ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent)
{
QGridLayout *layout = new QGridLayout(this);
setLayout(layout);
m_imageWidget = new ImageWidget(database, this);
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
layout->setSpacing(0);
layout->addWidget(m_imageWidget, 0, 0);
layout->addWidget(m_verticalScrollBar, 0, 1);
layout->addWidget(m_horizontalScrollBar, 1, 0);
connect(m_verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
connect(m_horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollEvent()));
connect(m_imageWidget, &ImageWidget::scrollBarsUpdate, this, &ImageScrollAreaGL::updateScrollbars);
}
ImageScrollAreaGL::~ImageScrollAreaGL()
{
}
void ImageScrollAreaGL::setImage(Image *image)
{
if(image && image->rawImage())
{
m_imageWidget->setImage(image->rawImage(), image->number());
m_imageWidget->setWCS(image->info().wcs);
}
}
ImageWidget *ImageScrollAreaGL::imageWidget()
{
return m_imageWidget;
}
void ImageScrollAreaGL::updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV)
{
if(maxH > 0)
{
m_horizontalScrollBar->show();
m_horizontalScrollBar->setRange(0, maxH);
m_horizontalScrollBar->setPageStep(stepH);
m_horizontalScrollBar->setValue(valueH);
}
else
m_horizontalScrollBar->hide();
if(maxV > 0)
{
m_verticalScrollBar->show();
m_verticalScrollBar->setRange(0, maxV);
m_verticalScrollBar->setPageStep(stepV);
m_verticalScrollBar->setValue(valueV);
}
else
m_verticalScrollBar->hide();
}
void ImageScrollAreaGL::zoomIn()
{
m_imageWidget->zoom(1);
}
void ImageScrollAreaGL::zoomOut()
{
m_imageWidget->zoom(-1);
}
void ImageScrollAreaGL::bestFit()
{
m_horizontalScrollBar->hide();
m_verticalScrollBar->hide();
m_imageWidget->bestFit();
}
void ImageScrollAreaGL::oneToOne()
{
m_imageWidget->zoom(0);
}
void ImageScrollAreaGL::scrollEvent()
{
m_imageWidget->setOffset(m_horizontalScrollBar->value(), m_verticalScrollBar->value());
}
+49 -52
View File
@@ -1,21 +1,42 @@
#ifndef IMAGESCROLLAREAGL_H #ifndef IMAGEWIDGET_H
#define IMAGESCROLLAREAGL_H #define IMAGEWIDGET_H
#include <memory> #include <memory>
#include <QObject>
#include <QOpenGLWidget> #include <QOpenGLWidget>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QScrollBar>
#include <QTimer>
#include "rawimage.h"
#include "imageringlist.h"
#include "database.h"
#include "stretchtoolbar.h"
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions> #include "database.h"
#include "rawimage.h"
#include "imageinfo.h"
#include "stretchtoolbar.h"
class ImageWidget
{
public:
ImageWidget(){}
virtual ~ImageWidget(){}
virtual void setImage(std::shared_ptr<RawImage> image, int index) = 0;
virtual void setWCS(std::shared_ptr<WCSData> wcs) = 0;
virtual void zoom(int zoom, const QPointF &mousePos = QPointF()) = 0;
virtual void bestFit() = 0;
virtual void setBayerMask(int mask) = 0;
virtual void setOffset(float dx, float dy) = 0;
virtual void allocateThumbnails(const QStringList &paths) = 0;
virtual void setMTFParams(const MTFParam &params) = 0;
virtual void superPixel(bool enable) = 0;
virtual void invert(bool enable) = 0;
virtual void falseColor(bool enable) = 0;
virtual QImage renderToImage() = 0;
virtual void thumbnailLoaded(const Image *image) = 0;
virtual void showThumbnail(bool enable) = 0;
};
struct ImageThumb struct ImageThumb
{ {
@@ -26,7 +47,7 @@ struct ImageThumb
bool dirty; bool dirty;
}; };
class ImageWidget : public QOpenGLWidget class ImageWidgetGL : public QOpenGLWidget, public ImageWidget
{ {
Q_OBJECT Q_OBJECT
QOpenGLFunctions *f = nullptr; QOpenGLFunctions *f = nullptr;
@@ -71,25 +92,23 @@ class ImageWidget : public QOpenGLWidget
QPointF m_lastPos; QPointF m_lastPos;
QString m_error; QString m_error;
public: public:
explicit ImageWidget(Database *database, QWidget *parent = nullptr); explicit ImageWidgetGL(Database *database, QWidget *parent = nullptr);
~ImageWidget() override; ~ImageWidgetGL() override;
void setImage(std::shared_ptr<RawImage> image, int index); void setImage(std::shared_ptr<RawImage> image, int index) override;
void setImage(const QPixmap &pixmap); void setWCS(std::shared_ptr<WCSData> wcs) override;
void setWCS(std::shared_ptr<WCSData> wcs); void zoom(int zoom, const QPointF &mousePos = QPointF()) override;
void zoom(int zoom, const QPointF &mousePos = QPointF()); void bestFit() override;
void bestFit(); void allocateThumbnails(const QStringList &paths) override;
void allocateThumbnails(const QStringList &paths);
QVector2D getImagePixelCoord(const QVector2D &pos); QVector2D getImagePixelCoord(const QVector2D &pos);
void setBayerMask(int mask); void setBayerMask(int mask) override;
public slots: void setOffset(float dx, float dy) override;
void setMTFParams(const MTFParam &params); void setMTFParams(const MTFParam &params) override;
void setOffset(float dx, float dy); void superPixel(bool enable) override;
void superPixel(bool enable); void invert(bool enable) override;
void invert(bool enable); void falseColor(bool enable) override;
void falseColor(bool enable); QImage renderToImage() override;
QImage renderToImage(); void thumbnailLoaded(const Image *image) override;
void thumbnailLoaded(const Image *image); void showThumbnail(bool enable) override;
void showThumbnail(bool enable);
protected: protected:
void paintGL() override; void paintGL() override;
void resizeGL(int w, int h) override; void resizeGL(int w, int h) override;
@@ -109,26 +128,4 @@ signals:
void scrollBarsUpdate(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV); void scrollBarsUpdate(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
}; };
class ImageScrollAreaGL : public QWidget #endif // IMAGEWIDGET_H
{
Q_OBJECT
QScrollBar *m_verticalScrollBar;
QScrollBar *m_horizontalScrollBar;
ImageWidget *m_imageWidget;
public:
explicit ImageScrollAreaGL(Database *database, QWidget *parent = nullptr);
~ImageScrollAreaGL() override;
void setImage(Image *image);
ImageWidget* imageWidget();
protected:
void updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
public slots:
void zoomIn();
void zoomOut();
void bestFit();
void oneToOne();
protected slots:
void scrollEvent();
};
#endif // IMAGESCROLLAREAGL_H
+22 -30
View File
@@ -76,19 +76,19 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
if(!m_database->init()) if(!m_database->init())
QMessageBox::critical(this, tr("Can't open DB"), tr("Can't open SQLITE database")); QMessageBox::critical(this, tr("Can't open DB"), tr("Can't open SQLITE database"));
m_imageGL = new ImageScrollAreaGL(m_database, this); m_image = new ImageScrollArea(m_database, this);
setCentralWidget(m_imageGL); setCentralWidget(m_image);
StatusBar *statusBar = new StatusBar(this); StatusBar *statusBar = new StatusBar(this);
setStatusBar(statusBar); setStatusBar(statusBar);
connect(m_imageGL->imageWidget(), &ImageWidget::status, statusBar, &StatusBar::newStatus); connect(m_image, &ImageScrollArea::status, statusBar, &StatusBar::newStatus);
m_stretchPanel = new StretchToolbar(this); m_stretchPanel = new StretchToolbar(this);
connect(m_stretchPanel, &StretchToolbar::paramChanged, m_imageGL->imageWidget(), &ImageWidget::setMTFParams); connect(m_stretchPanel, &StretchToolbar::paramChanged, m_image, &ImageScrollArea::setMTFParams);
connect(m_stretchPanel, &StretchToolbar::autoStretch, [&](){ m_stretchPanel->stretchImage(m_ringList->currentImage().get()); }); connect(m_stretchPanel, &StretchToolbar::autoStretch, [&](){ m_stretchPanel->stretchImage(m_ringList->currentImage().get()); });
connect(m_stretchPanel, &StretchToolbar::invert, m_imageGL->imageWidget(), &ImageWidget::invert); connect(m_stretchPanel, &StretchToolbar::invert, m_image, &ImageScrollArea::invert);
connect(m_stretchPanel, &StretchToolbar::superPixel, m_imageGL->imageWidget(), &ImageWidget::superPixel); connect(m_stretchPanel, &StretchToolbar::superPixel, m_image, &ImageScrollArea::superPixel);
connect(m_stretchPanel, &StretchToolbar::falseColor, m_imageGL->imageWidget(), &ImageWidget::falseColor); connect(m_stretchPanel, &StretchToolbar::falseColor, m_image, &ImageScrollArea::falseColor);
m_ringList = new ImageRingList(m_database, nameFilter, this); m_ringList = new ImageRingList(m_database, nameFilter, this);
m_filesystem = new FilesystemWidget(m_ringList, this); m_filesystem = new FilesystemWidget(m_ringList, this);
@@ -133,14 +133,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
setWindowTitle(tr("Tenmon")); setWindowTitle(tr("Tenmon"));
connect(m_ringList, SIGNAL(pixmapLoaded(Image*)), this, SLOT(pixmapLoaded(Image*))); connect(m_ringList, &ImageRingList::pixmapLoaded, m_image, &ImageScrollArea::imageLoaded);
connect(m_ringList, SIGNAL(currentImageChanged(int)), this, SLOT(updateWindowTitle())); connect(m_ringList, &ImageRingList::currentImageChanged, this, &MainWindow::updateWindowTitle);
connect(m_ringList, SIGNAL(infoLoaded(ImageInfoData)), m_info, SLOT(setInfo(const ImageInfoData&))); connect(m_ringList, &ImageRingList::infoLoaded, m_info, &ImageInfo::setInfo);
connect(m_ringList, SIGNAL(currentImageChanged(int)), m_filesystem, SLOT(selectFile(int))); connect(m_ringList, &ImageRingList::currentImageChanged, m_filesystem, &FilesystemWidget::selectFile);
connect(m_ringList, &ImageRingList::thumbnailLoaded, m_imageGL->imageWidget(), &ImageWidget::thumbnailLoaded); connect(m_ringList, &ImageRingList::thumbnailLoaded, m_image, &ImageScrollArea::thumbnailLoaded);
connect(m_ringList, &ImageRingList::pixmapLoaded, m_stretchPanel, &StretchToolbar::imageLoaded); connect(m_ringList, &ImageRingList::pixmapLoaded, m_stretchPanel, &StretchToolbar::imageLoaded);
connect(m_ringList, &ImageRingList::pixmapLoaded, histogram, &Histogram::imageLoaded); connect(m_ringList, &ImageRingList::pixmapLoaded, histogram, &Histogram::imageLoaded);
connect(m_imageGL->imageWidget(), &ImageWidget::fileDropped, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile)); connect(m_image, &ImageScrollArea::fileDropped, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile));
QMenu *fileMenu = new QMenu(tr("File"), this); QMenu *fileMenu = new QMenu(tr("File"), this);
fileMenu->addAction(tr("Open"), QKeySequence::Open, this, SLOT(loadFile())); fileMenu->addAction(tr("Open"), QKeySequence::Open, this, SLOT(loadFile()));
@@ -171,10 +171,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
menuBar()->addMenu(editMenu); menuBar()->addMenu(editMenu);
QMenu *viewMenu = new QMenu(tr("View"), this); QMenu *viewMenu = new QMenu(tr("View"), this);
viewMenu->addAction(tr("Zoom In"), QKeySequence::ZoomIn, m_imageGL, SLOT(zoomIn())); viewMenu->addAction(tr("Zoom In"), QKeySequence::ZoomIn, m_image, &ImageScrollArea::zoomIn);
viewMenu->addAction(tr("Zoom Out"), QKeySequence::ZoomOut, m_imageGL, SLOT(zoomOut())); viewMenu->addAction(tr("Zoom Out"), QKeySequence::ZoomOut, m_image, &ImageScrollArea::zoomOut);
viewMenu->addAction(tr("Best Fit"), QKeySequence("Ctrl+1"), m_imageGL, SLOT(bestFit())); viewMenu->addAction(tr("Best Fit"), QKeySequence("Ctrl+1"), m_image, &ImageScrollArea::bestFit);
viewMenu->addAction(tr("100%"), m_imageGL, SLOT(oneToOne())); viewMenu->addAction(tr("100%"), m_image, &ImageScrollArea::oneToOne);
viewMenu->addSeparator(); viewMenu->addSeparator();
QMenu *bayerMenu = viewMenu->addMenu(tr("Bayer mask")); QMenu *bayerMenu = viewMenu->addMenu(tr("Bayer mask"));
QActionGroup *bayerActionGroup = new QActionGroup(this); QActionGroup *bayerActionGroup = new QActionGroup(this);
@@ -190,15 +190,15 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
viewMenu->addMenu(bayerMenu); viewMenu->addMenu(bayerMenu);
connect(bayerActionGroup, &QActionGroup::triggered, [this](QAction *action){ connect(bayerActionGroup, &QActionGroup::triggered, [this](QAction *action){
int data = action->data().toInt(); int data = action->data().toInt();
m_imageGL->imageWidget()->setBayerMask(data); m_image->setBayerMask(data);
QSettings settings; QSettings settings;
settings.setValue("mainwindow/bayermask", data); settings.setValue("mainwindow/bayermask", data);
}); });
QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), Qt::Key_F2, [this](bool checked){ QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), Qt::Key_F2, [this](bool checked){
if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails(); if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails();
m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageNames()); m_image->allocateThumbnails(m_ringList->imageNames());
m_imageGL->imageWidget()->showThumbnail(checked); m_image->showThumbnail(checked);
if(checked)m_ringList->loadThumbnails(); if(checked)m_ringList->loadThumbnails();
else m_ringList->stopLoading(); else m_ringList->stopLoading();
}); });
@@ -295,7 +295,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
} }
} }
m_imageGL->setFocus(); m_image->setFocus();
// workaround for nasty wayland backend bug https://bugreports.qt.io/browse/QTBUG-87332 // workaround for nasty wayland backend bug https://bugreports.qt.io/browse/QTBUG-87332
if(static_cast<QGuiApplication*>(QCoreApplication::instance())->platformName() == "wayland") if(static_cast<QGuiApplication*>(QCoreApplication::instance())->platformName() == "wayland")
@@ -451,14 +451,6 @@ void MainWindow::socketNotify()
socketNotifier->setEnabled(true); socketNotifier->setEnabled(true);
} }
void MainWindow::pixmapLoaded(Image *image)
{
if(image->rawImage())
{
m_imageGL->setImage(image);
}
}
void MainWindow::loadFile() void MainWindow::loadFile()
{ {
QString file = QFileDialog::getOpenFileName(this, QString file = QFileDialog::getOpenFileName(this,
@@ -557,7 +549,7 @@ void MainWindow::saveAs()
} }
else else
{ {
QImage img = m_imageGL->imageWidget()->renderToImage(); QImage img = m_image->renderToImage();
if(!img.isNull()) if(!img.isNull())
img.save(file, filterToFormat(file, selectedFilter)); img.save(file, filterToFormat(file, selectedFilter));
} }
+1 -4
View File
@@ -4,10 +4,9 @@
#include <QMainWindow> #include <QMainWindow>
#include <QSocketNotifier> #include <QSocketNotifier>
#include "imageringlist.h" #include "imageringlist.h"
#include "imagescrollarea.h"
#include "database.h" #include "database.h"
#include "imageinfo.h" #include "imageinfo.h"
#include "imagescrollareagl.h" #include "imagescrollarea.h"
#include "filesystemwidget.h" #include "filesystemwidget.h"
#include "stretchtoolbar.h" #include "stretchtoolbar.h"
#include "databaseview.h" #include "databaseview.h"
@@ -16,7 +15,6 @@ class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
ImageScrollArea *m_image; ImageScrollArea *m_image;
ImageScrollAreaGL *m_imageGL;
ImageRingList *m_ringList; ImageRingList *m_ringList;
StretchToolbar *m_stretchPanel; StretchToolbar *m_stretchPanel;
Database *m_database; Database *m_database;
@@ -44,7 +42,6 @@ protected:
protected slots: protected slots:
void socketNotify(); void socketNotify();
void updateWindowTitle(); void updateWindowTitle();
void pixmapLoaded(Image *image);
void loadFile(); void loadFile();
void loadFile(const QString &path); void loadFile(const QString &path);
void loadFile(int row); void loadFile(int row);