Add thumbnails

This commit is contained in:
2022-04-18 07:16:46 +02:00
parent 2c95364fc4
commit 4e6230eef2
14 changed files with 347 additions and 39 deletions
+154 -23
View File
@@ -55,6 +55,8 @@ ImageWidget::ImageWidget(QWidget *parent) : QOpenGLWidget(parent)
m_range = UINT16_MAX;
m_imgWidth = m_imgHeight = -1;
m_superpixel = m_invert = false;
m_showThumbnails = false;
m_thumbnailCount = 0;
setAcceptDrops(true);
}
@@ -115,6 +117,19 @@ void ImageWidget::blockRepaint(bool block)
if(!block)update();
}
void ImageWidget::allocateThumbnails(int count)
{
m_thumbnailTexture->destroy();
m_thumbnailTexture->create();
m_thumbnailTexture->setFormat(QOpenGLTexture::RGB16_UNorm);
m_thumbnailTexture->setSize(THUMB_SIZE, THUMB_SIZE);
m_thumbnailTexture->setLayers(count);
m_thumbnailTexture->allocateStorage();
m_bufferSizes->bind();
m_bufferSizes->allocate(count * sizeof(float)*3);
m_thumbnailCount = count;
}
void ImageWidget::setMTFParams(float low, float mid, float high)
{
m_low = low;
@@ -164,6 +179,23 @@ QImage ImageWidget::renderToImage()
return fbo.toImage(true);
}
void ImageWidget::thumbnailLoaded(const Image *image)
{
const RawImage *raw = image->thumbnail();
m_thumbnailTexture->setData(0, image->number(), QOpenGLTexture::RGB, QOpenGLTexture::UInt16, raw->data(), m_transferOptions.get());
float a = raw->thumbAspect();
int sizes[3] = { std::max(1, a > 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE * a)), std::max(1, a < 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE / a)), image->number() };
m_bufferSizes->bind();
m_bufferSizes->write(image->number() * sizeof(sizes), sizes, sizeof(sizes));
update();
}
void ImageWidget::showThumbnail(bool enable)
{
m_showThumbnails = enable;
update();
}
void ImageWidget::paintGL()
{
if(m_blockRepaint)return;
@@ -175,16 +207,35 @@ void ImageWidget::paintGL()
if(height() > m_image->height()*m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
m_program->bind();
m_program->setUniformValue("viewport", (float)width(), (float)height());
m_program->setUniformValue("offset", dx, dy);
m_program->setUniformValue("mtf_param", m_low, m_mid, m_high);
m_program->setUniformValue("zoom", 1.0f/m_scale);
m_program->setUniformValue("bw", m_bwImg);
m_program->setUniformValue("invert", m_invert);
if(m_showThumbnails)
{
m_vaoThumb->bind();
m_thumbnailTexture->bind(1);
m_thumbnailProgram->bind();
f->glUniform3i(m_thumbnailProgram->uniformLocation("viewport_row"), width(), height(), width()/THUMB_SIZE_BORDER);
m_thumbnailProgram->setUniformValue("mtf_param", m_low, m_mid, m_high);
m_thumbnailProgram->setUniformValue("invert", m_invert);
m_thumbnailProgram->setUniformValue("offset", m_dx, m_dy);
f3->glVertexAttribDivisor(m_thumbnailProgram->attributeLocation("imageSize_num"), 1);
QMatrix4x4 mvp;
mvp.ortho(rect());
m_thumbnailProgram->setUniformValue("mvp", mvp);
if(f3)f3->glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_thumbnailCount);
}
else
{
m_vao->bind();
m_image->bind(0);
m_program->bind();
m_program->setUniformValue("viewport", (float)width(), (float)height());
m_program->setUniformValue("offset", dx, dy);
m_program->setUniformValue("mtf_param", m_low, m_mid, m_high);
m_program->setUniformValue("zoom", 1.0f/m_scale);
m_program->setUniformValue("bw", m_bwImg);
m_program->setUniformValue("invert", m_invert);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
m_image->bind(0);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void ImageWidget::resizeGL(int w, int h)
@@ -198,10 +249,12 @@ void ImageWidget::initializeGL()
{
f = context()->functions();
f->glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
QOpenGLFunctions_3_2_Core *f3 = context()->versionFunctions<QOpenGLFunctions_3_2_Core>();
f3 = context()->versionFunctions<QOpenGLFunctions_3_3_Core>();
m_vao = std::unique_ptr<QOpenGLVertexArrayObject>(new QOpenGLVertexArrayObject);
m_vaoThumb = std::unique_ptr<QOpenGLVertexArrayObject>(new QOpenGLVertexArrayObject);
m_vao->create();
m_vaoThumb->create();
m_vao->bind();
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
@@ -228,7 +281,7 @@ void ImageWidget::initializeGL()
m_buffer->create();
m_buffer->bind();
m_buffer->allocate(vertexs, sizeof(vertexs));
f->glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(float)*4, 0);
// f->glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(float)*4, 0);
m_program = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/image.vert");
@@ -247,6 +300,33 @@ void ImageWidget::initializeGL()
m_program->setUniformValue("qt_Texture0", (GLuint)0);
m_program->setUniformValue("scale", 1.0f, 0.0f);
m_vaoThumb->bind();
m_thumbnailProgram = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
m_thumbnailProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/thumb.vert");
m_thumbnailProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/thumb.frag");
if(f3)f3->glBindFragDataLocation(m_program->programId(), 0, "color");
m_thumbnailProgram->bind();
m_thumbnailProgram->enableAttributeArray("qt_Vertex");
m_thumbnailProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4);
m_thumbnailProgram->enableAttributeArray("qt_MultiTexCoord0");
m_thumbnailProgram->setAttributeBuffer("qt_MultiTexCoord0", GL_FLOAT, sizeof(float)*2, 2, sizeof(float)*4);
if(!m_thumbnailProgram->link())
{
qDebug() << "Link failed" << m_thumbnailProgram->log();
}
m_thumbnailProgram->setUniformValue("qt_Texture0", (GLuint)1);
m_bufferSizes = std::unique_ptr<QOpenGLBuffer>(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
m_bufferSizes->setUsagePattern(QOpenGLBuffer::StaticDraw);
m_bufferSizes->create();
m_bufferSizes->bind();
m_bufferSizes->allocate(12);
m_thumbnailProgram->enableAttributeArray("imageSize_num");
m_thumbnailProgram->setAttributeBuffer("imageSize_num", GL_FLOAT, 0, 3);
f3->glVertexAttribDivisor(m_thumbnailProgram->attributeLocation("imageSize_num"), 1);
m_image = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QOpenGLTexture::Target2D));
m_image->setFormat(QOpenGLTexture::RGB8U);
m_image->allocateStorage();
@@ -254,6 +334,15 @@ void ImageWidget::initializeGL()
m_image->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
m_image->setMagnificationFilter(QOpenGLTexture::Linear);
m_thumbnailTexture = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QOpenGLTexture::Target2DArray));
m_thumbnailTexture->setFormat(QOpenGLTexture::RGB16_UNorm);
m_thumbnailTexture->setSize(THUMB_SIZE, THUMB_SIZE);
m_thumbnailTexture->setLayers(1);
m_thumbnailTexture->allocateStorage();
m_thumbnailTexture->bind(1);
m_thumbnailTexture->setMinificationFilter(QOpenGLTexture::Linear);
m_thumbnailTexture->setMinificationFilter(QOpenGLTexture::Linear);
m_transferOptions = std::unique_ptr<QOpenGLPixelTransferOptions>(new QOpenGLPixelTransferOptions);
m_transferOptions->setAlignment(1);
}
@@ -292,6 +381,7 @@ ImageScrollAreaGL::ImageScrollAreaGL(QWidget *parent) : QWidget(parent)
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);
@@ -330,32 +420,66 @@ ImageWidget *ImageScrollAreaGL::imageWidget()
return m_imageWidget;
}
void ImageScrollAreaGL::updateScrollbars(bool zoom)
void ImageScrollAreaGL::setThumbnails(int count)
{
if(zoom)
m_thumbCount = count;
if(m_thumbCount)
{
setScrollRange(m_verticalScrollBar, m_imgHeight*m_scale);
setScrollRange(m_horizontalScrollBar, m_imgWidth*m_scale);
m_verticalScrollBar->setRange(0, (m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) + 1) * THUMB_SIZE_BORDER);
m_verticalScrollBar->setPageStep(THUMB_SIZE);
}
else
{
m_verticalScrollBar->setRange(0, m_imgHeight*m_scale - m_verticalScrollBar->pageStep());
m_horizontalScrollBar->setRange(0, m_imgWidth*m_scale - m_horizontalScrollBar->pageStep());
m_verticalScrollBar->setPageStep(m_imageWidget->height());
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
}
updateScrollbars();
}
void ImageScrollAreaGL::updateScrollbars(bool zoom)
{
if(m_thumbCount)
{
m_horizontalScrollBar->hide();
m_verticalScrollBar->show();
m_verticalScrollBar->setRange(0, (m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) + 1) * THUMB_SIZE_BORDER);
m_verticalScrollBar->setPageStep(128);
}
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);
m_verticalScrollBar->setPageStep(m_imageWidget->height());
m_horizontalScrollBar->setPageStep(m_imageWidget->width());
if(m_thumbCount)
{
m_verticalScrollBar->setRange(0, (m_thumbCount / (m_imageWidget->width() / THUMB_SIZE_BORDER) + 1) * THUMB_SIZE_BORDER);
m_verticalScrollBar->setPageStep(128);
}
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();
m_horizontalScrollBar->setValue(m_horizontalScrollBar->value() + delta.x());
if(m_thumbCount == 0)m_horizontalScrollBar->setValue(m_horizontalScrollBar->value() + delta.x());
m_verticalScrollBar->setValue(m_verticalScrollBar->value() + delta.y());
m_lastPos = event->pos();
}
@@ -367,9 +491,16 @@ void ImageScrollAreaGL::mousePressEvent(QMouseEvent *event)
void ImageScrollAreaGL::wheelEvent(QWheelEvent *event)
{
m_bestFit = false;
if(event->angleDelta().y() != 0)
zoom(event->angleDelta().y() / 1200.0f);
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)