diff --git a/imagescrollarea.cpp b/imagescrollarea.cpp index b350db3..260a416 100644 --- a/imagescrollarea.cpp +++ b/imagescrollarea.cpp @@ -58,6 +58,11 @@ void ImageScrollArea::setBayerMask(int mask) m_imageWidget->setBayerMask(mask); } +void ImageScrollArea::setColormap(int colormap) +{ + m_imageWidget->setColormap(colormap); +} + void ImageScrollArea::updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV) { if(maxH > 0) diff --git a/imagescrollarea.h b/imagescrollarea.h index 6ddb6f2..1ff9a5a 100644 --- a/imagescrollarea.h +++ b/imagescrollarea.h @@ -16,6 +16,7 @@ public: void allocateThumbnails(const QStringList &paths); void showThumbnail(bool enable); void setBayerMask(int mask); + void setColormap(int colormap); protected: void updateScrollbars(int valueH, int stepH, int maxH, int valueV, int stepV, int maxV); public slots: diff --git a/imagewidget.cpp b/imagewidget.cpp index 6f2e6ea..f69d3be 100644 --- a/imagewidget.cpp +++ b/imagewidget.cpp @@ -258,6 +258,12 @@ void ImageWidgetGL::setBayerMask(int mask) update(); } +void ImageWidgetGL::setColormap(int colormap) +{ + m_colormapIdx = colormap; + update(); +} + void ImageWidgetGL::setMTFParams(const MTFParam ¶ms) { m_mtfParams = params; @@ -600,6 +606,7 @@ void ImageWidgetGL::paintGL() m_program->setUniformValue("filtering", m_scale > 1.0f ? FILTERING : 1); m_program->setUniformValue("lut_table", 2); m_program->setUniformValue("srgb", m_srgb); + m_program->setUniformValue("colormapIdx", m_colormapIdx); f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); m_vao->release(); } @@ -702,6 +709,7 @@ void ImageWidgetGL::initializeGL() m_program->setAttributeBuffer("qt_MultiTexCoord0", GL_FLOAT, sizeof(float)*2, 2, sizeof(float)*4); m_program->setUniformValue("qt_Texture0", (GLuint)0); m_program->setUniformValue("lut_table", (GLuint)2); + m_program->setUniformValue("colormap", (GLuint)3); m_program->setUniformValue("scale", 1.0f, 0.0f); m_debayerProgram = std::unique_ptr(new QOpenGLShaderProgram); @@ -764,6 +772,21 @@ void ImageWidgetGL::initializeGL() m_lut->allocateStorage(); m_lut->bind(2); + QImage colormap(":/colormap.png"); + colormap = colormap.convertToFormat(QImage::Format_RGBA8888); + qDebug() << colormap; + m_colormap = std::make_unique(QOpenGLTexture::Target1DArray); + m_colormap->setSize(colormap.width()); + m_colormap->setLayers(colormap.height()); + m_colormap->setFormat(QOpenGLTexture::RGBA8_UNorm); + m_colormap->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); + m_colormap->setWrapMode(QOpenGLTexture::ClampToEdge); + m_colormap->allocateStorage(); + for(int i=0; isetData(0, i, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, colormap.scanLine(i)); + + m_colormap->bind(3); + if(m_rawImage) setImage(m_rawImage, m_currentImg); } diff --git a/imagewidget.h b/imagewidget.h index 648b3a7..946059a 100644 --- a/imagewidget.h +++ b/imagewidget.h @@ -26,6 +26,7 @@ public: virtual void bestFit() = 0; virtual void setBayerMask(int mask) = 0; + virtual void setColormap(int colormap) = 0; virtual void setOffset(float dx, float dy) = 0; virtual void allocateThumbnails(const QStringList &paths) = 0; @@ -63,6 +64,7 @@ class ImageWidgetGL : public QOpenGLWidget, public ImageWidget std::unique_ptr m_vaoThumb; std::unique_ptr m_thumbnailTexture; std::unique_ptr m_lut; + std::unique_ptr m_colormap; GLuint m_debayerTex = 0; std::shared_ptr m_rawImage; std::shared_ptr m_wcs; @@ -87,6 +89,7 @@ class ImageWidgetGL : public QOpenGLWidget, public ImageWidget int m_maxTextureSize = 0; int m_maxArrayLayers = 0; int m_firstRed[2] = {0, 0}; + int m_colormapIdx = 0; QVector m_thumnails; Database *m_database = nullptr; QPointF m_lastPos; @@ -102,6 +105,7 @@ public: void allocateThumbnails(const QStringList &paths) override; QVector2D getImagePixelCoord(const QVector2D &pos); void setBayerMask(int mask) override; + void setColormap(int colormap) override; void setOffset(float dx, float dy) override; void setMTFParams(const MTFParam ¶ms) override; void superPixel(bool enable) override; diff --git a/mainwindow.cpp b/mainwindow.cpp index d6b1fad..73bb658 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -207,6 +207,29 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) settings.setValue("mainwindow/bayermask", data); }); + QStringList colormaps = {"Autumn", "Bone", "Jet", "Winter", "Rainbow", "Ocean", "Summer", "Spring", "Cool", "HSV", "Pink", "Hot", "Parula", "Magma", + "Inferno", "Plasma", "Viridis", "Cividis", "Twilight", "Twilight shifted", "Turbo", "Deepgreen"}; + QMenu *colormapMenu = viewMenu->addMenu(tr("Colormap")); + QActionGroup *colormapActionGroup = new QActionGroup(this); + int idx = 0; + QImage cmImg(":/colormap.png"); + for(QString &colormap : colormaps) + { + QImage icon = cmImg.copy(0, idx, cmImg.width(), 1).scaled(32, 32); + QAction *action = colormapActionGroup->addAction(colormap); + action->setIcon(QPixmap::fromImage(icon)); + action->setCheckable(true); action->setData(idx++); + colormapMenu->addAction(action); + } + viewMenu->addMenu(colormapMenu); + connect(colormapActionGroup, &QActionGroup::triggered, [this](QAction *action){ + int data = action->data().toInt(); + m_image->setColormap(data); + QSettings settings; + settings.setValue("mainwindow/colormap", data); + }); + + QAction *thumbnailsAction = viewMenu->addAction(tr("Thumbnails"), Qt::Key_F2, [this](bool checked){ if(SettingsDialog::loadThumbsizes())m_ringList->clearThumbnails(); m_image->allocateThumbnails(m_ringList->imageNames()); @@ -291,6 +314,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) case 3: bggrAction->setChecked(true); break; } + int colormap = settings.value("mainwindow/colormap", 4).toInt(); + if(colormap >= 0 && colormap < colormapActionGroup->actions().size()) + colormapActionGroup->actions().at(colormap)->setChecked(true); + + m_image->setBayerMask(bayermask); + m_image->setColormap(colormap); QStringList standardLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); if(standardLocations.size()) diff --git a/resources/colormap.png b/resources/colormap.png new file mode 100644 index 0000000..1fc330b Binary files /dev/null and b/resources/colormap.png differ diff --git a/resources/resources.qrc b/resources/resources.qrc index 4a0c105..14d7c63 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -18,6 +18,7 @@ space.nouspiro.tenmon.png ../translations/tenmon_pt_BR.qm ../about/help_en + colormap.png ../about/help_en diff --git a/shaders/image.frag b/shaders/image.frag index aabf6ba..e311e7e 100644 --- a/shaders/image.frag +++ b/shaders/image.frag @@ -1,5 +1,6 @@ uniform sampler2D qt_Texture0; uniform sampler3D lut_table; +uniform sampler1DArray colormap; uniform vec3 mtf_param[3]; uniform vec2 unit_scale; uniform bool bw; @@ -7,6 +8,7 @@ uniform bool invert; uniform bool srgb; uniform bool false_color; uniform int filtering; +uniform int colormapIdx; in vec2 qt_TexCoord0; layout(location = 0) out vec4 color; @@ -26,17 +28,9 @@ vec4 MTF(vec4 x, vec4 low, vec4 mid, vec4 high) vec3 falsecolor(float color) { - const vec3 pallete[] = vec3[]( - vec3(1.0, 0.0, 1.0), //magneta - vec3(0.0, 0.0, 1.0), //blue - vec3(0.0, 1.0, 1.0), //cyan - vec3(0.0, 1.0, 0.0), //green - vec3(1.0, 1.0, 0.0), //yellow - vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0));//red - color *= 5.0; - int i = int(color); - float f = fract(color); - return mix(pallete[i], pallete[i+1], f);// * (f * 0.5 + 0.5); + color *= 255.0 / 256.0; + color += 0.5 / 256.0; + return texture(colormap, vec2(color, colormapIdx)).rgb; } vec3 checker()