Improved zoom and scrolling

This commit is contained in:
Dušan Poizl 2023-03-12 13:45:07 +01:00
parent 74aee15f80
commit 26666ee36d
3 changed files with 129 additions and 141 deletions

@ -162,7 +162,9 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
f->glDeleteTextures(1, &m_debayerTex);
m_debayerTex = 0;
}
update();
if(m_bestFit)bestFit();
else setOffset(m_dx, m_dy);
}
void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs)
@ -170,10 +172,35 @@ void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs)
m_wcs = wcs;
}
void ImageWidget::setScale(float scale)
void ImageWidget::zoom(int zoom, const QPointF &mousePos)
{
m_scale = scale;
update();
m_bestFit = false;
if(zoom != 0)
m_scaleStop = std::clamp(m_scaleStop + (zoom > 0 ? 1 : -1), -10, 10);
else
m_scaleStop = 0;
QPointF focus(m_width * 0.5f, m_height * 0.5f);
if(!mousePos.isNull())
focus = mousePos;
if(width() > m_image->width() * m_scale)
m_dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f;
if(height() > m_image->height() * m_scale)
m_dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f;
float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop));
float r = newScale / m_scale;
m_scale = newScale;
setOffset(m_dx * r + focus.x() * (r - 1), m_dy * r + focus.y() * (r - 1));
}
void ImageWidget::bestFit()
{
m_bestFit = true;
m_scale = std::min((float)m_width/m_imgWidth, (float)m_height/m_imgHeight);
setOffset(0, 0);
}
void ImageWidget::blockRepaint(bool block)
@ -203,6 +230,19 @@ void ImageWidget::allocateThumbnails(const QStringList &paths)
m_thumbnailTexture->allocateStorage();
}
QVector2D ImageWidget::getImagePixelCoord(const QVector2D &pos)
{
float dx = m_dx;
float dy = m_dy;
if(m_width > m_image->width()*m_scale)
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
if(m_height > m_image->height()*m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
QVector2D offset(dx, dy);
return (pos + offset) / m_scale;
}
void ImageWidget::setMTFParams(float low, float mid, float high)
{
m_low = low;
@ -211,10 +251,14 @@ void ImageWidget::setMTFParams(float low, float mid, float high)
update();
}
void ImageWidget::setOffset(int dx, int dy)
void ImageWidget::setOffset(float dx, float dy)
{
m_dx = dx;
m_dy = dy;
m_dx = std::clamp(dx, 0.0f, m_imgWidth * m_scale - m_width);
if(m_showThumbnails)
m_dy = std::clamp(dy, 0.0f, (float)((m_thumbnailCount / (m_width / THUMB_SIZE_BORDER) + 2) * THUMB_SIZE_BORDER_Y - m_height));
else
m_dy = std::clamp(dy, 0.0f, m_imgHeight * m_scale - m_height);
updateScrollBars();
update();
}
@ -269,6 +313,7 @@ void ImageWidget::thumbnailLoaded(const Image *image)
void ImageWidget::showThumbnail(bool enable)
{
m_showThumbnails = enable;
updateScrollBars();
update();
}
@ -278,10 +323,10 @@ void ImageWidget::paintGL()
float dx = m_dx;
float dy = m_dy;
if(width() > m_image->width()*m_scale)
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
if(height() > m_image->height()*m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
if(m_width > m_image->width() * m_scale)
dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f;
if(m_height > m_image->height() * m_scale)
dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f;
QBrush highlight = style()->standardPalette().highlight();
if(m_showThumbnails)
@ -374,6 +419,8 @@ void ImageWidget::resizeGL(int w, int h)
m_width = w;
m_height = h;
f->glViewport(0, 0, w, h);
if(m_bestFit)bestFit();
updateScrollBars();
}
void ImageWidget::initializeGL()
@ -536,7 +583,10 @@ void ImageWidget::mousePressEvent(QMouseEvent *event)
thumbSelect(event);
}
else
event->ignore();
{
if(event->button() == Qt::LeftButton)
m_lastPos = event->localPos();
}
}
void ImageWidget::mouseMoveEvent(QMouseEvent *event)
@ -545,21 +595,17 @@ void ImageWidget::mouseMoveEvent(QMouseEvent *event)
{
thumbSelect(event);
}
else
event->ignore();
else if(!m_lastPos.isNull())
{
QPointF off = event->localPos() - m_lastPos;
m_lastPos = event->localPos();
setOffset(m_dx - off.x(), m_dy - off.y());
return;
}
if(!m_showThumbnails && m_rawImage)
{
float dx = m_dx;
float dy = m_dy;
if(width() > m_image->width()*m_scale)
dx = -width()*0.5f + m_image->width()*m_scale*0.5f;
if(height() > m_image->height()*m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
QVector2D offset(dx, dy);
QVector2D pos = QVector2D(event->pos());
QVector2D pix = (pos + offset) / m_scale;
QVector2D pix = getImagePixelCoord(QVector2D(event->pos()));
QVector3D rgb;
SkyPoint sky;
@ -604,7 +650,24 @@ void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
m_database->unmark(unmark);
}
else
event->ignore();
{
m_lastPos = QPointF();
}
}
void ImageWidget::wheelEvent(QWheelEvent *event)
{
if(m_showThumbnails)
{
m_dy = std::clamp(m_dy - event->angleDelta().y(), 0.0f, (float)m_thumbnailCount / (width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
update();
updateScrollBars();
}
else
{
if(event->angleDelta().y() != 0)
zoom(event->angleDelta().y(), event->modifiers() & Qt::ShiftModifier ? QPointF() : event->posF());
}
}
void ImageWidget::thumbSelect(QMouseEvent *event)
@ -671,6 +734,16 @@ void ImageWidget::debayer()
m_whiteBalance[2] = maxRGB / pixel[2];
}
void ImageWidget::updateScrollBars()
{
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);
else
{
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);
@ -680,9 +753,6 @@ ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWid
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
m_scale = 1.0f;
m_bestFit = false;
m_thumbCount = 0;
layout->setSpacing(0);
layout->addWidget(m_imageWidget, 0, 0);
@ -691,6 +761,7 @@ ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWid
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()
@ -704,10 +775,6 @@ void ImageScrollAreaGL::setImage(Image *image)
{
m_imageWidget->setImage(image->rawImage(), image->number());
m_imageWidget->setWCS(image->info().wcs);
m_imgWidth = image->rawImage()->width();
m_imgHeight = image->rawImage()->height();
if(m_bestFit)bestFit();
updateScrollbars();
}
}
@ -716,124 +783,49 @@ ImageWidget *ImageScrollAreaGL::imageWidget()
return m_imageWidget;
}
void ImageScrollAreaGL::setThumbnails(int count)
void ImageScrollAreaGL::updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV)
{
m_thumbCount = count;
if(m_thumbCount)
if(maxH > 0)
{
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
m_horizontalScrollBar->show();
m_horizontalScrollBar->setRange(0, maxH);
m_horizontalScrollBar->setPageStep(stepH);
m_horizontalScrollBar->setValue(valueH);
}
else
{
m_verticalScrollBar->setPageStep(m_imageWidget->height());
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
}
updateScrollbars();
}
void ImageScrollAreaGL::updateScrollbars(bool zoom)
{
if(m_thumbCount)
{
m_horizontalScrollBar->hide();
if(maxV > 0)
{
m_verticalScrollBar->show();
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setRange(0, maxV);
m_verticalScrollBar->setPageStep(stepV);
m_verticalScrollBar->setValue(valueV);
}
else
{
if(zoom)
{
setScrollRange(m_verticalScrollBar, m_imgHeight*m_scale);
setScrollRange(m_horizontalScrollBar, m_imgWidth*m_scale);
}
else
{
m_verticalScrollBar->setRange(0, m_imgHeight*m_scale - m_verticalScrollBar->pageStep());
m_horizontalScrollBar->setRange(0, m_imgWidth*m_scale - m_horizontalScrollBar->pageStep());
}
}
}
void ImageScrollAreaGL::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
if(m_thumbCount)
{
m_verticalScrollBar->setRange(0, m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) * THUMB_SIZE_BORDER_Y);
m_verticalScrollBar->setPageStep(THUMB_SIZE_BORDER_Y);
}
else
{
m_verticalScrollBar->setPageStep(m_imageWidget->height());
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
}
updateScrollbars();
}
void ImageScrollAreaGL::mouseMoveEvent(QMouseEvent *event)
{
QPoint delta = m_lastPos - event->pos();
if(m_thumbCount == 0)m_horizontalScrollBar->setValue(m_horizontalScrollBar->value() + delta.x());
m_verticalScrollBar->setValue(m_verticalScrollBar->value() + delta.y());
m_lastPos = event->pos();
}
void ImageScrollAreaGL::mousePressEvent(QMouseEvent *event)
{
m_lastPos = event->pos();
}
void ImageScrollAreaGL::wheelEvent(QWheelEvent *event)
{
if(m_thumbCount)
{
m_verticalScrollBar->setValue(m_verticalScrollBar->value() - event->angleDelta().y());
}
else
{
m_bestFit = false;
if(event->angleDelta().y() != 0)
zoom(event->angleDelta().y() / 1200.0f);
}
}
void ImageScrollAreaGL::zoom(float delta)
{
if((m_scale >= 8.0f && delta > 0) || (m_scale <= 0.1f && delta < 0))return;
m_scale += delta;
m_imageWidget->blockRepaint(true);
m_imageWidget->setScale(m_scale);
updateScrollbars(true);
m_imageWidget->blockRepaint(false);
m_verticalScrollBar->hide();
}
void ImageScrollAreaGL::zoomIn()
{
zoom(0.1f);
m_bestFit = false;
m_imageWidget->zoom(1);
}
void ImageScrollAreaGL::zoomOut()
{
zoom(-0.1f);
m_bestFit = false;
m_imageWidget->zoom(-1);
}
void ImageScrollAreaGL::bestFit()
{
m_bestFit = true;
m_scale = std::min((float)m_imageWidget->width()/m_imgWidth, (float)m_imageWidget->height()/m_imgHeight);
zoom(0.0f);
m_horizontalScrollBar->hide();
m_verticalScrollBar->hide();
m_imageWidget->bestFit();
}
void ImageScrollAreaGL::oneToOne()
{
m_scale = 1.0f;
zoom(0.0f);
m_bestFit = false;
m_imageWidget->zoom(0);
}
void ImageScrollAreaGL::scrollEvent()

@ -52,6 +52,8 @@ class ImageWidget : public QOpenGLWidget
float m_range;
float m_dx, m_dy;
float m_scale;
int m_scaleStop = 0;
bool m_bestFit = false;
float m_whiteBalance[3] = {1.0f, 1.0f, 1.0f};
bool m_blockRepaint;
bool m_bwImg;
@ -66,18 +68,21 @@ class ImageWidget : public QOpenGLWidget
int m_maxArrayLayers;
QVector<ImageThumb> m_thumnails;
Database *m_database;
QPointF m_lastPos;
public:
explicit ImageWidget(Database *database, QWidget *parent = nullptr);
~ImageWidget() override;
void setImage(std::shared_ptr<RawImage> image, int index);
void setImage(const QPixmap &pixmap);
void setWCS(std::shared_ptr<WCSData> wcs);
void setScale(float scale);
void zoom(int zoom, const QPointF &mousePos = QPointF());
void bestFit();
void blockRepaint(bool block);
void allocateThumbnails(const QStringList &paths);
QVector2D getImagePixelCoord(const QVector2D &pos);
public slots:
void setMTFParams(float low, float mid, float high);
void setOffset(int dx, int dy);
void setOffset(float dx, float dy);
void superPixel(bool enable);
void invert(bool enable);
QImage renderToImage();
@ -92,11 +97,14 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void thumbSelect(QMouseEvent *event);
void debayer();
void updateScrollBars();
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);
};
class ImageScrollAreaGL : public QWidget
@ -105,24 +113,13 @@ class ImageScrollAreaGL : public QWidget
QScrollBar *m_verticalScrollBar;
QScrollBar *m_horizontalScrollBar;
ImageWidget *m_imageWidget;
int m_imgWidth, m_imgHeight;
QPoint m_lastPos;
float m_scale;
bool m_bestFit;
int m_thumbCount;
public:
explicit ImageScrollAreaGL(Database *database, QWidget *parent = nullptr);
~ImageScrollAreaGL() override;
void setImage(Image *image);
ImageWidget* imageWidget();
void setThumbnails(int count);
protected:
void updateScrollbars(bool zoom = false);
void resizeEvent(QResizeEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void zoom(float delta);
void updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV);
public slots:
void zoomIn();
void zoomOut();

@ -160,7 +160,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails();
m_imageGL->imageWidget()->allocateThumbnails(m_ringList->imageNames());
m_imageGL->imageWidget()->showThumbnail(checked);
m_imageGL->setThumbnails(checked ? m_ringList->imageCount() : 0);
if(checked)m_ringList->loadThumbnails();
else m_ringList->stopLoading();
}, Qt::Key_F2);