From 26d1af6077713eb84c1112de9e9e0a886ffdaf46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Wed, 14 Dec 2022 20:27:56 +0100 Subject: [PATCH] Add debayer --- imagescrollareagl.cpp | 56 +++++++++++++++++++++++++++++++++++++++---- imagescrollareagl.h | 3 +++ resources.qrc | 2 ++ shaders/debayer.frag | 41 +++++++++++++++++++++++++++++++ shaders/debayer.vert | 18 ++++++++++++++ 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 shaders/debayer.frag create mode 100644 shaders/debayer.vert diff --git a/imagescrollareagl.cpp b/imagescrollareagl.cpp index 4c4f961..a263df0 100644 --- a/imagescrollareagl.cpp +++ b/imagescrollareagl.cpp @@ -153,7 +153,11 @@ void ImageWidget::setImage(std::shared_ptr image, int index) } else m_image->generateMipMaps(); - m_image->setLevelOfDetailRange(m_superpixel ? 1 : 0, m_image->mipMaxLevel()); + if(m_debayerTex) + { + f->glDeleteTextures(1, &m_debayerTex); + m_debayerTex = 0; + } update(); } @@ -212,7 +216,6 @@ void ImageWidget::setOffset(int dx, int dy) void ImageWidget::superPixel(bool enable) { m_superpixel = enable; - m_image->setLevelOfDetailRange(enable ? 1 : 0, m_image->mipMaxLevel()); update(); } @@ -332,14 +335,20 @@ void ImageWidget::paintGL() } else { + debayer(); + m_vao->bind(); - m_image->bind(0); + if(m_superpixel && m_debayerTex) + f->glBindTexture(GL_TEXTURE_2D, m_debayerTex); + else + 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("bw", m_bwImg && !m_superpixel); m_program->setUniformValue("invert", m_invert); #ifdef COLOR_MANAGMENT m_program->setUniformValue("srgb", m_srgb); @@ -416,12 +425,27 @@ void ImageWidget::initializeGL() m_program->setUniformValue("qt_Texture0", (GLuint)0); m_program->setUniformValue("scale", 1.0f, 0.0f); + m_debayerProgram = std::unique_ptr(new QOpenGLShaderProgram); + m_debayerProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/debayer.vert"); + m_debayerProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/debayer.frag"); + if(f3)f3->glBindFragDataLocation(m_debayerProgram->programId(), 0, "color"); + m_debayerProgram->bind(); + m_debayerProgram->enableAttributeArray("qt_Vertex"); + m_debayerProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4); + m_debayerProgram->enableAttributeArray("qt_MultiTexCoord0"); + m_debayerProgram->setAttributeBuffer("qt_MultiTexCoord0", GL_FLOAT, sizeof(float)*2, 2, sizeof(float)*4); + m_debayerProgram->setUniformValue("qt_Texture0", (GLuint)0); + if(!m_debayerProgram->link()) + { + qDebug() << "Link failed" << m_debayerProgram->log(); + } + m_vaoThumb->bind(); m_thumbnailProgram = std::unique_ptr(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"); + if(f3)f3->glBindFragDataLocation(m_thumbnailProgram->programId(), 0, "color"); m_thumbnailProgram->bind(); m_thumbnailProgram->enableAttributeArray("qt_Vertex"); m_thumbnailProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4); @@ -595,6 +619,28 @@ void ImageWidget::thumbSelect(QMouseEvent *event) } } +void ImageWidget::debayer() +{ + if(m_debayerTex > 0 || !m_superpixel || !m_bwImg || m_imgWidth < 0)return; + + QOpenGLFramebufferObject fbo(m_imgWidth, m_imgHeight, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGBA16); + fbo.bind(); + + f->glViewport(0, 0, m_imgWidth, m_imgHeight); + + m_debayerProgram->bind(); + m_image->bind(0); + f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + fbo.release(); + f->glViewport(0, 0, m_width, m_height); + m_debayerTex = fbo.takeTexture(); + f->glBindTexture(GL_TEXTURE_2D, m_debayerTex); + f->glGenerateMipmap(GL_TEXTURE_2D); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); +} + ImageScrollAreaGL::ImageScrollAreaGL(Database *database, QWidget *parent) : QWidget(parent) { QGridLayout *layout = new QGridLayout(this); diff --git a/imagescrollareagl.h b/imagescrollareagl.h index b365ade..3b3ab21 100644 --- a/imagescrollareagl.h +++ b/imagescrollareagl.h @@ -32,6 +32,7 @@ class ImageWidget : public QOpenGLWidget QTimer *m_updateTimer; std::unique_ptr m_program; std::unique_ptr m_thumbnailProgram; + std::unique_ptr m_debayerProgram; std::unique_ptr m_buffer; std::unique_ptr m_bufferSizes; std::unique_ptr m_image; @@ -39,6 +40,7 @@ class ImageWidget : public QOpenGLWidget std::unique_ptr m_vaoThumb; std::unique_ptr m_transferOptions; std::unique_ptr m_thumbnailTexture; + GLuint m_debayerTex = 0; std::shared_ptr m_rawImage; std::shared_ptr m_wcs; int m_width, m_height; @@ -88,6 +90,7 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void thumbSelect(QMouseEvent *event); + void debayer(); signals: void fileDropped(const QString &path); void status(const QString &value, const QString &pixelCoords, const QString &celestialCoords); diff --git a/resources.qrc b/resources.qrc index 288ea51..514a55e 100644 --- a/resources.qrc +++ b/resources.qrc @@ -16,6 +16,8 @@ shaders/image.vert shaders/thumb.frag shaders/thumb.vert + shaders/debayer.frag + shaders/debayer.vert about/help_en diff --git a/shaders/debayer.frag b/shaders/debayer.frag new file mode 100644 index 0000000..9241586 --- /dev/null +++ b/shaders/debayer.frag @@ -0,0 +1,41 @@ +#version 330 + +uniform sampler2D qt_Texture0; +in vec2 qt_TexCoord0; +in vec4 center; +out vec4 color; + +#define f(x, y) texelFetch(qt_Texture0, icenter + ivec2(x, y), 0).r + +void main(void) +{ + ivec2 texSize = textureSize(qt_Texture0, 0); + ivec2 icenter = ivec2(center.zw); + ivec2 alternate = icenter % 2; + + // cross, checker, theta, phi + const vec4 kA = vec4(-1.0, -1.5, 0.5, -1.0) / 8.0; + const vec4 kB = vec4( 2.0, 0.0, 0.0, 4.0) / 8.0; + const vec4 kC = vec4( 4.0, 6.0, 5.0, 5.0) / 8.0; + const vec4 kD = vec4( 0.0, 2.0, -1.0, -1.0) / 8.0; + const vec4 kE = vec4(-1.0, -1.5, -1.0, 0.5) / 8.0; + const vec4 kF = vec4( 2.0, 0.0, 4.0, 0.0) / 8.0; + + float A = f(0,2) + f(0,-2); + float B = f(0,1) + f(0,-1); + float C = f(0,0); + float D = f(1,1) + f(-1,1) + f(-1,-1) + f(-1,-1); + float E = f(2,0) + f(0,2); + float F = f(1,0) + f(-1,0); + + vec4 P = kA*A + kB*B + kC*C + kD*D + kE*E + kF*F; + + color.rgb = alternate.y == 0 ? + (alternate.x == 0 ? vec3(C, P.xy) : // even row even col + vec3(P.z, C, P.w)) : // even row odd col + (alternate.x == 0 ? vec3(P.w, C, P.z) : // odd row even col + vec3(P.yx, C)); // odd row odd col + + color.a = 1.0; +} + diff --git a/shaders/debayer.vert b/shaders/debayer.vert new file mode 100644 index 0000000..f746538 --- /dev/null +++ b/shaders/debayer.vert @@ -0,0 +1,18 @@ +#version 330 + +uniform sampler2D qt_Texture0; +in vec2 qt_Vertex; +in vec2 qt_MultiTexCoord0; +out vec2 qt_TexCoord0; +out vec4 center; +uniform vec2 viewport; + +void main(void) +{ + vec2 texSize = vec2(textureSize(qt_Texture0, 0)); + gl_Position = vec4(qt_Vertex, 0.0, 1.0); + qt_TexCoord0 = qt_MultiTexCoord0; + qt_TexCoord0.y = 1.0 - qt_TexCoord0.y; + center.xy = qt_TexCoord0; + center.zw = qt_TexCoord0 * texSize.xy; +}