Files
tenmon/imagescrollareagl.cpp
T
2020-05-10 21:03:10 +02:00

239 lines
7.0 KiB
C++

#include "imagescrollareagl.h"
#include <QOpenGLFunctions>
#include <QDebug>
#include <QKeyEvent>
#include <QOpenGLDebugLogger>
#include <QOpenGLPixelTransferOptions>
#include <QGridLayout>
ImageWidget::ImageWidget(QWidget *parent) : QOpenGLWidget(parent)
{
setFocusPolicy(Qt::ClickFocus);
m_range = UINT16_MAX;
m_low = 0;
m_high = 1;
m_dx = m_dy = 0;
}
ImageWidget::~ImageWidget()
{
makeCurrent();
}
void ImageWidget::setImage(RawImage *image)
{
if(image == nullptr)return;
m_image->destroy();
m_image->setFormat(QOpenGLTexture::R16_UNorm);
m_image->setSize(image->width(), image->height());
m_image->allocateStorage();
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->setWrapMode(QOpenGLTexture::ClampToBorder);
m_image->setBorderColor(0, 0, 0, 0);
switch(image->type())
{
case RawImage::UINT8:
m_image->setData(0, QOpenGLTexture::Red, QOpenGLTexture::UInt8, image->data(), m_transferOptions.get());
m_range = UINT8_MAX;
break;
case RawImage::UINT16:
m_image->setData(0, QOpenGLTexture::Red, QOpenGLTexture::UInt16, image->data(), m_transferOptions.get());
m_range = UINT16_MAX;
break;
case RawImage::FLOAT32:
break;
}
m_image->generateMipMaps();
repaint();
}
void ImageWidget::setImage(const QPixmap &pixmap)
{
QImage img = pixmap.toImage();
m_image->destroy();
m_image->setData(img);
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->setWrapMode(QOpenGLTexture::ClampToBorder);
m_image->setBorderColor(0, 0, 0, 0);
repaint();
}
void ImageWidget::setLow(int low)
{
m_low = low/m_range;
repaint();
}
void ImageWidget::setHigh(int high)
{
m_high = high/m_range;
repaint();
}
void ImageWidget::setOffset(int dx, int dy)
{
m_dx = dx;
m_dy = dy;
repaint();
}
void ImageWidget::paintGL()
{
float s = 1.0f/(m_high-m_low);
m_program->bind();
m_program->setUniformValue("scale", s, -m_low*s);
m_program->setUniformValue("viewport", (float)width(), (float)height());
m_program->setUniformValue("offset", m_dx, m_dy);
m_image->bind(0);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void ImageWidget::resizeGL(int w, int h)
{
m_width = w;
m_height = h;
f->glViewport(0, 0, w, h);
}
void ImageWidget::initializeGL()
{
f = context()->functions();
f->glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
m_vao = std::unique_ptr<QOpenGLVertexArrayObject>(new QOpenGLVertexArrayObject);
m_vao->create();
m_vao->bind();
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
logger->initialize();
logger->startLogging();
connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage &message)
{
qDebug() << message;
});
qDebug() << (char*)f->glGetString(GL_VENDOR);
qDebug() << (char*)f->glGetString(GL_RENDERER);
qDebug() << (char*)f->glGetString(GL_VERSION);
qDebug() << context()->format();
// each vertex is x,y 2D position and s,t texture coordinates
float vertexs[] = {-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f,};
m_buffer = std::unique_ptr<QOpenGLBuffer>(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
m_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
m_buffer->create();
m_buffer->bind();
m_buffer->allocate(vertexs, sizeof(vertexs));
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");
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/image.frag");
if(!m_program->link())
{
qDebug() << "Link failed" << m_program->log();
}
m_program->bind();
m_program->enableAttributeArray("qt_Vertex");
m_program->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4);
m_program->enableAttributeArray("qt_MultiTexCoord0");
m_program->setAttributeBuffer("qt_MultiTexCoord0", GL_FLOAT, sizeof(float)*2, 2, sizeof(float)*4);
m_program->setUniformValue("qt_Texture0", (GLuint)0);
m_program->setUniformValue("scale", 1.0f, 0.0f);
m_image = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QImage("/home/nou/Obrázky/1p6yap.jpg")));
m_image->bind(0);
m_image->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
m_image->setMagnificationFilter(QOpenGLTexture::Linear);
m_transferOptions = std::unique_ptr<QOpenGLPixelTransferOptions>(new QOpenGLPixelTransferOptions);
m_transferOptions->setAlignment(1);
}
ImageScrollAreaGL::ImageScrollAreaGL(QWidget *parent)
{
QGridLayout *layout = new QGridLayout(this);
setLayout(layout);
m_imageWidget = new ImageWidget(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()));
}
ImageScrollAreaGL::~ImageScrollAreaGL()
{
}
void ImageScrollAreaGL::setImage(RawImage *image)
{
m_imageWidget->setImage(image);
m_imgWidth = image->width();
m_imgHeight = image->height();
updateScrollbars();
}
void ImageScrollAreaGL::setImage(const QPixmap &pixmap)
{
m_imageWidget->setImage(pixmap);
m_imgWidth = pixmap.width();
m_imgHeight = pixmap.height();
updateScrollbars();
}
ImageWidget *ImageScrollAreaGL::imageWidget()
{
return m_imageWidget;
}
void ImageScrollAreaGL::updateScrollbars()
{
m_verticalScrollBar->setRange(0, m_imgHeight-m_verticalScrollBar->pageStep());
m_horizontalScrollBar->setRange(0, m_imgWidth-m_horizontalScrollBar->pageStep());
}
void ImageScrollAreaGL::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << "resize" << m_imageWidget->size();
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());
m_verticalScrollBar->setValue(m_verticalScrollBar->value() + delta.y());
m_lastPos = event->pos();
}
void ImageScrollAreaGL::mousePressEvent(QMouseEvent *event)
{
m_lastPos = event->pos();
}
void ImageScrollAreaGL::scrollEvent()
{
qDebug() << m_horizontalScrollBar->value() << m_verticalScrollBar->value();
m_imageWidget->setOffset(m_horizontalScrollBar->value(), m_verticalScrollBar->value());
}