Prepare for three channels STF

This commit is contained in:
2023-10-10 22:48:40 +02:00
parent 0c2c5f908c
commit 0a803ace10
10 changed files with 125 additions and 41 deletions
+4 -6
View File
@@ -225,11 +225,9 @@ QVector2D ImageWidget::getImagePixelCoord(const QVector2D &pos)
return (pos + offset) / m_scale;
}
void ImageWidget::setMTFParams(float low, float mid, float high)
void ImageWidget::setMTFParams(const MTFParam &params)
{
m_low = low;
m_mid = mid;
m_high = high;
m_mtfParams = params;
update();
}
@@ -339,7 +337,7 @@ void ImageWidget::paintGL()
m_thumbnailProgram->bind();
f->glUniform3i(m_thumbnailProgram->uniformLocation("viewport_row"), width(), height(), width()/THUMB_SIZE_BORDER);
f->glUniform3i(m_thumbnailProgram->uniformLocation("thumb_size"), THUMB_SIZE_BORDER/2, THUMB_SIZE_BORDER, THUMB_SIZE_BORDER_Y);
m_thumbnailProgram->setUniformValue("mtf_param", m_low, m_mid, m_high);
m_thumbnailProgram->setUniformValueArray("mtf_param", m_mtfParams.blackPoint, 3, 3);
m_thumbnailProgram->setUniformValue("invert", m_invert);
m_thumbnailProgram->setUniformValue("offset", 0, m_dy);
QMatrix4x4 mvp;
@@ -388,7 +386,7 @@ void ImageWidget::paintGL()
m_program->bind();
m_program->setUniformValue("viewport", (float)width(), (float)height());
m_program->setUniformValue("offset", std::floor(dx), std::floor(dy));
m_program->setUniformValue("mtf_param", m_low, m_mid, m_high);
m_program->setUniformValueArray("mtf_param", m_mtfParams.blackPoint, 3, 3);
m_program->setUniformValue("zoom", 1.0f/m_scale);
m_program->setUniformValue("bw", m_bwImg && !m_superpixel);
m_program->setUniformValue("false_color", m_falseColor && m_bwImg);
+3 -4
View File
@@ -14,6 +14,7 @@
#include "rawimage.h"
#include "imageringlist.h"
#include "database.h"
#include "stretchtoolbar.h"
struct ImageThumb
{
@@ -46,9 +47,7 @@ class ImageWidget : public QOpenGLWidget
int m_width, m_height;
int m_imgWidth = -1, m_imgHeight = -1;
int m_currentImg = 0;
float m_low = 0.0f;
float m_mid = 0.5f;
float m_high = 1.0;
MTFParam m_mtfParams;
float m_dx = 0, m_dy = 0;
float m_scale = 1.0f;
int m_scaleStop = 0;
@@ -81,7 +80,7 @@ public:
void allocateThumbnails(const QStringList &paths);
QVector2D getImagePixelCoord(const QVector2D &pos);
public slots:
void setMTFParams(float low, float mid, float high);
void setMTFParams(const MTFParam &params);
void setOffset(float dx, float dy);
void superPixel(bool enable);
void invert(bool enable);
+1 -1
View File
@@ -80,7 +80,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
connect(m_imageGL->imageWidget(), &ImageWidget::status, statusBar, &StatusBar::newStatus);
m_stretchPanel = new StretchToolbar(this);
connect(m_stretchPanel, SIGNAL(paramChanged(float,float,float)), m_imageGL->imageWidget(), SLOT(setMTFParams(float,float,float)));
connect(m_stretchPanel, &StretchToolbar::paramChanged, m_imageGL->imageWidget(), &ImageWidget::setMTFParams);
connect(m_stretchPanel, &StretchToolbar::autoStretch, [&](){ m_stretchPanel->stretchImage(m_ringList->currentImage().get()); });
connect(m_stretchPanel, &StretchToolbar::invert, m_imageGL->imageWidget(), &ImageWidget::invert);
connect(m_stretchPanel, &StretchToolbar::superPixel, m_imageGL->imageWidget(), &ImageWidget::superPixel);
-1
View File
@@ -183,7 +183,6 @@ void calcStats(const T *data, size_t n, RawImage::Stats &stats)
uint32_t median = findMedian(histogram[i]);
stats.m_median[i] = median;
qDebug() << i << median << median / 65535;
uint32_t madHist[65536] = {0};
madHist[0] = histogram[i][median];
for(size_t o = 1; o < histSize; o++)
+5 -8
View File
@@ -1,12 +1,11 @@
#version 330
uniform sampler2D qt_Texture0;
uniform vec3 mtf_param;
uniform vec3 mtf_param[3];
uniform bool bw;
uniform bool invert;
uniform bool srgb;
uniform bool false_color;
uniform vec3 whiteBalance;
in vec2 qt_TexCoord0;
layout(location = 0) out vec4 color;
@@ -17,11 +16,11 @@ vec3 Linear2sRGB(vec3 color)
greaterThan(color, vec3(0.0031308)));
}
vec4 MTF(vec4 x, vec3 m)
vec4 MTF(vec4 x, vec4 low, vec4 mid, vec4 high)
{
x = (x - m.x) / (m.z - m.x);
x = (x - low) / (high - low);
x = clamp(x, vec4(0.0), vec4(1.0));
return ((m.y - 1) * x) / ((2 * m.y - 1) * x - m.y);
return ((mid - 1) * x) / ((2 * mid - 1) * x - mid);
}
vec3 falsecolor(float color)
@@ -48,7 +47,7 @@ void main(void)
{
color = texture(qt_Texture0, qt_TexCoord0);
if(bw)color = color.rrra;
color = MTF(color, mtf_param);
color = MTF(color, vec4(mtf_param[0], 0.0), vec4(mtf_param[1], 0.5), vec4(mtf_param[2], 1.0));
if(false_color)color.rgb = falsecolor(color.r);
if(invert)color.rgb = vec3(1.0) - color.rgb;
@@ -57,8 +56,6 @@ void main(void)
if(srgb)color.rgb = Linear2sRGB(color.rgb);
color.rgb *= whiteBalance;
if(any(lessThan(qt_TexCoord0, vec2(0.0))) || any(greaterThan(qt_TexCoord0, vec2(1.0))))
color = vec4(0.0, 0.0, 0.0, 1.0);
+5 -5
View File
@@ -1,22 +1,22 @@
#version 330
uniform sampler2DArray qt_Texture0;
uniform vec3 mtf_param;
uniform vec3 mtf_param[3];
uniform bool invert;
in vec3 qt_TexCoord0;
layout(location = 0) out vec4 color;
vec4 MTF(vec4 x, vec3 m)
vec4 MTF(vec4 x, vec4 low, vec4 mid, vec4 high)
{
x = (x - m.x) / (m.z - m.x);
x = (x - low) / (high - low);
x = clamp(x, vec4(0.0), vec4(1.0));
return ((m.y - 1) * x) / ((2 * m.y - 1) * x - m.y);
return ((mid - 1) * x) / ((2 * mid - 1) * x - mid);
}
void main(void)
{
color = texture(qt_Texture0, qt_TexCoord0);
color = MTF(color, mtf_param);
color = MTF(color, vec4(mtf_param[0], 0.0), vec4(mtf_param[1], 0.5), vec4(mtf_param[2], 1.0));
if(invert)color = vec4(1.0) - color;
color.a = 1.0;
}
+21 -5
View File
@@ -10,18 +10,34 @@ static float clamp(float x)
return std::min(std::max(x, 0.0f), 1.0f);
}
STFSlider::STFSlider(QWidget *parent) : QWidget(parent)
STFSlider::STFSlider(const QColor &color, QWidget *parent) : QWidget(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setMinimumWidth(100);
setMinimumHeight(15);
setMaximumHeight(15);
setMouseTracking(true);
if(color == Qt::white)
{
setMaximumHeight(15);
setMinimumHeight(15);
}
else
{
setMaximumHeight(7);
setMinimumHeight(7);
}
m_blackPoint = 0;
m_midPoint = 0.5;
m_whitePoint = 1;
m_grabbed = -1;
m_fineTune = false;
m_color = color;
if(color == Qt::blue || color == Qt::red)
m_threshold = 1.1f;
else if(color == Qt::green)
m_threshold = 0.8f;
else
m_threshold = 0.4f;
setToolTip(tr("Press Shift for fine tuning"));
}
@@ -60,7 +76,7 @@ void STFSlider::paintEvent(QPaintEvent *event)
{
qreal p = i/32.0f;
qreal c = std::pow(p, 1.0/2.2)*255;
gradient.setColorAt(p, QColor(c, c, c));
gradient.setColorAt(p, QColor(m_color.redF()*c, m_color.greenF()*c, m_color.blueF()*c));
}
QPainterPath tick(QPointF(0, 0));
@@ -75,7 +91,7 @@ void STFSlider::paintEvent(QPaintEvent *event)
auto drawTick = [&](qreal p)
{
painter.setPen(p < 0.4 ? Qt::white : Qt::black);
painter.setPen(p < m_threshold ? Qt::white : Qt::black);
painter.resetTransform();
painter.translate(w*p, 0);
painter.drawPath(tick);
+3 -1
View File
@@ -13,8 +13,10 @@ class STFSlider : public QWidget
int m_grabbed;
bool m_fineTune;
float m_fineTuneX;
QColor m_color;
float m_threshold;
public:
explicit STFSlider(QWidget *parent = nullptr);
explicit STFSlider(const QColor &color = Qt::white, QWidget *parent = nullptr);
float blackPoint() const;
float midPoint() const;
float whitePoint() const;
+69 -9
View File
@@ -18,13 +18,55 @@ float MTF(float x, float m)
StretchToolbar::StretchToolbar(QWidget *parent) : QToolBar(tr("Stretch toolbar"), parent)
{
setObjectName("stretchtoolbar");
m_stfSlider = new STFSlider(this);
addWidget(m_stfSlider);
connect(m_stfSlider, SIGNAL(paramChanged(float, float, float)), this, SIGNAL(paramChanged(float,float,float)));
QWidget *lum = new QWidget(this);
QVBoxLayout *vbox1 = new QVBoxLayout(lum);
m_stfSlider = new STFSlider(Qt::white, this);
vbox1->addWidget(m_stfSlider);
/*m_stfSliderR = new STFSlider(Qt::red, this);
m_stfSliderG = new STFSlider(Qt::green, this);
m_stfSliderB = new STFSlider(Qt::blue, this);
QWidget *rgb = new QWidget(this);
QVBoxLayout *vbox2 = new QVBoxLayout(rgb);
vbox2->setSpacing(0);
vbox2->addWidget(m_stfSliderR);
vbox2->addWidget(m_stfSliderG);
vbox2->addWidget(m_stfSliderB);*/
m_stack = new QStackedWidget(this);
m_stack->addWidget(lum);
//m_stack->addWidget(rgb);
//m_stack->setCurrentIndex(0);
addWidget(m_stack);
connect(m_stfSlider, &STFSlider::paramChanged, [this](float blackPoint, float midPoint, float whitePoint){
m_mtfParam.blackPoint[0] = m_mtfParam.blackPoint[1] = m_mtfParam.blackPoint[2] = blackPoint;
m_mtfParam.midPoint[0] = m_mtfParam.midPoint[1] = m_mtfParam.midPoint[2] = midPoint;
m_mtfParam.whitePoint[0] = m_mtfParam.whitePoint[1] = m_mtfParam.whitePoint[2] = whitePoint;
emit paramChanged(m_mtfParam);
});
/*connect(m_stfSliderR, &STFSlider::paramChanged, [this](float blackPoint, float midPoint, float whitePoint){
m_mtfParam.blackPoint[0] = blackPoint;
m_mtfParam.midPoint[0] = midPoint;
m_mtfParam.whitePoint[0] = whitePoint;
emit paramChanged(m_mtfParam);
});
connect(m_stfSliderG, &STFSlider::paramChanged, [this](float blackPoint, float midPoint, float whitePoint){
m_mtfParam.blackPoint[1] = blackPoint;
m_mtfParam.midPoint[1] = midPoint;
m_mtfParam.whitePoint[1] = whitePoint;
emit paramChanged(m_mtfParam);
});
connect(m_stfSliderB, &STFSlider::paramChanged, [this](float blackPoint, float midPoint, float whitePoint){
m_mtfParam.blackPoint[2] = blackPoint;
m_mtfParam.midPoint[2] = midPoint;
m_mtfParam.whitePoint[2] = whitePoint;
emit paramChanged(m_mtfParam);
});*/
QAction *autoStretchButton = addAction(QIcon(":/nuke.png"), tr("Auto Stretch F12"));
autoStretchButton->setShortcut(Qt::Key_F12);
connect(autoStretchButton, SIGNAL(triggered()), this, SIGNAL(autoStretch()));
connect(autoStretchButton, &QAction::triggered, this, &StretchToolbar::autoStretch);
QAction *resetButton = addAction(style()->standardIcon(QStyle::SP_DialogResetButton), tr("Reset Screen Transfer Function F11"));
resetButton->setShortcut(Qt::Key_F11);
@@ -69,20 +111,40 @@ void StretchToolbar::stretchImage(Image *img)
if(max>1.0f)max = 1.0f;
float bp = median + mad * BLACK_POINT_SIGMA * MAD_TO_SIGMA;
float mid = MTF(median - bp, TARGET_BACKGROUND);
m_mtfParam.blackPoint[i] = bp;
m_mtfParam.midPoint[i] = mid;
m_mtfParam.whitePoint[i] = max;
bp2 += bp;
mid2 += mid;
max2 += max;
}
m_stfSlider->setMTFParams(bp2 / ch, mid2 / ch, max2 / ch);
emit paramChanged(m_stfSlider->blackPoint(), m_stfSlider->midPoint(), m_stfSlider->whitePoint());
if(m_stack->currentIndex() == 0)
{
m_mtfParam.blackPoint[0] = m_mtfParam.blackPoint[1] = m_mtfParam.blackPoint[2] = bp2 / ch;
m_mtfParam.midPoint[0] = m_mtfParam.midPoint[1] = m_mtfParam.midPoint[2] = mid2 / ch;
m_mtfParam.whitePoint[0] = m_mtfParam.whitePoint[1] = m_mtfParam.whitePoint[2] = max2 / ch;
m_stfSlider->setMTFParams(m_mtfParam.blackPoint[0], m_mtfParam.midPoint[0], m_mtfParam.whitePoint[0]);
}
else
{
m_stfSliderR->setMTFParams(m_mtfParam.blackPoint[0], m_mtfParam.midPoint[0], m_mtfParam.whitePoint[0]);
m_stfSliderG->setMTFParams(m_mtfParam.blackPoint[1], m_mtfParam.midPoint[1], m_mtfParam.whitePoint[1]);
m_stfSliderB->setMTFParams(m_mtfParam.blackPoint[2], m_mtfParam.midPoint[2], m_mtfParam.whitePoint[2]);
}
emit paramChanged(m_mtfParam);
}
}
}
void StretchToolbar::resetMTF()
{
MTFParam params;
m_mtfParam = params;
m_stfSlider->setMTFParams(0, 0.5, 1);
emit paramChanged(0, 0.5, 1);
m_stfSliderR->setMTFParams(0, 0.5, 1);
m_stfSliderG->setMTFParams(0, 0.5, 1);
m_stfSliderB->setMTFParams(0, 0.5, 1);
emit paramChanged(params);
}
void StretchToolbar::imageLoaded(Image *img)
@@ -90,5 +152,3 @@ void StretchToolbar::imageLoaded(Image *img)
if(m_autoStretchOnLoad->isChecked())
stretchImage(img);
}
+14 -1
View File
@@ -2,15 +2,28 @@
#define STRETCHTOOLBAR_H
#include <QToolBar>
#include <QStackedWidget>
#include "stfslider.h"
class Image;
struct MTFParam
{
float blackPoint[3] = {0.0f, 0.0f, 0.0f};
float midPoint[3] = {0.5f, 0.5f, 0.5f};
float whitePoint[3] = {1.0f, 1.0f, 1.0f};
};
class StretchToolbar : public QToolBar
{
Q_OBJECT
STFSlider *m_stfSlider;
STFSlider *m_stfSliderR;
STFSlider *m_stfSliderG;
STFSlider *m_stfSliderB;
QAction *m_autoStretchOnLoad;
QStackedWidget *m_stack;
MTFParam m_mtfParam;
public:
explicit StretchToolbar(QWidget *parent = nullptr);
public slots:
@@ -18,7 +31,7 @@ public slots:
void resetMTF();
void imageLoaded(Image *img);
signals:
void paramChanged(float low, float mid, float high);
void paramChanged(const MTFParam &params);
void autoStretch();
void invert(bool enable);
void superPixel(bool enable);