Rework stretch to use just MTF

This commit is contained in:
2022-04-06 13:12:47 +02:00
parent 31783dbdeb
commit 2ff1b993a1
8 changed files with 93 additions and 135 deletions
+9 -30
View File
@@ -2,43 +2,22 @@
uniform sampler2D qt_Texture0;
varying vec2 qt_TexCoord0;
uniform vec2 scale;
uniform float a;
uniform int stretch;
uniform vec3 mtf_param;
uniform bool bw;
vec4 MTF(vec4 x, vec3 m)
{
x = (x - m.x) / (m.z - m.x);
x = clamp(x, vec4(0.0), vec4(1.0));
return ((m.y - 1) * x) / ((2 * m.y - 1) * x - m.y);
}
void main(void)
{
vec4 color = texture2D(qt_Texture0, qt_TexCoord0);
if(bw)color = color.rrra;
color = color*scale.x + scale.y;
color = max(color, vec4(0.0f));
color = MTF(color, mtf_param);
switch(stretch)
{
case 0:
break;
case 1:
color = sqrt(color);
break;
case 2:
color = pow(color, vec4(a));
break;
case 3:
color = log(a*color + 1.0) / log(vec4(a+1));
break;
case 4:
{
//float l = color.r*0.2126f + color.g*0.7152f + color.b*0.0722f;
float l = (color.r+color.g+color.b)*0.33333;
float k = asinh(l*a)/(l*asinh(a));
color *= k;
}
break;
}
//color = color*scale.x + scale.y;
//float color = pow(c, 0.4545);
if(any(lessThan(qt_TexCoord0, vec2(0.0))) || any(greaterThan(qt_TexCoord0, vec2(1.0))))
color = vec4(0.0);
gl_FragColor = color;
+7 -26
View File
@@ -41,13 +41,13 @@ ImageWidget::ImageWidget(QWidget *parent) : QOpenGLWidget(parent)
setFocusPolicy(Qt::ClickFocus);
m_range = UINT16_MAX;
m_low = 0;
m_mid = 0.5;
m_high = 1;
m_dx = m_dy = 0;
m_scale = 1.0f;
m_blockRepaint = false;
m_range = UINT16_MAX;
m_imgWidth = m_imgHeight = -1;
m_stretch = 0;
}
ImageWidget::~ImageWidget()
@@ -67,6 +67,7 @@ void ImageWidget::setImage(RawImage *image)
m_image->destroy();
m_image->setFormat(rawImageType.textureFormat);
m_image->setSize(image->width(), image->height());
m_image->setMipLevels([&](){ int c = 0; int s = std::min(m_imgWidth, m_imgHeight); while(s>>=1)c++; return c; }());
m_image->allocateStorage();
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
@@ -105,28 +106,11 @@ void ImageWidget::blockRepaint(bool block)
if(!block)update();
}
void ImageWidget::setLow(int low)
void ImageWidget::setMTFParams(float low, float mid, float high)
{
m_low = low/m_range;
update();
}
void ImageWidget::setHigh(int high)
{
m_high = high/m_range;
update();
}
void ImageWidget::setStrech(int stretch)
{
m_stretch = stretch;
update();
}
void ImageWidget::setStretchParam(float param)
{
qDebug() << param;
m_param = param;
m_low = low;
m_mid = mid;
m_high = high;
update();
}
@@ -169,13 +153,10 @@ void ImageWidget::paintGL()
if(height() > m_image->height()*m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f;
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", dx, dy);
m_program->setUniformValue("stretch", m_stretch);
m_program->setUniformValue("a", m_param);
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);
+2 -6
View File
@@ -33,12 +33,11 @@ class ImageWidget : public QOpenGLWidget
int m_width, m_height;
int m_imgWidth, m_imgHeight;
float m_low;
float m_mid;
float m_high;
int m_stretch;
float m_range;
float m_dx, m_dy;
float m_scale;
float m_param;
bool m_blockRepaint;
bool m_bwImg;
public:
@@ -49,10 +48,7 @@ public:
void setScale(float scale);
void blockRepaint(bool block);
public slots:
void setLow(int low);
void setHigh(int high);
void setStrech(int stretch);
void setStretchParam(float param);
void setMTFParams(float low, float mid, float high);
void setOffset(int dx, int dy);
QImage renderToImage();
protected:
+1 -4
View File
@@ -43,10 +43,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
setCentralWidget(m_imageGL);
StretchPanel *stretchPanel = new StretchPanel(this);
connect(stretchPanel, SIGNAL(lowChanged(int)), m_imageGL->imageWidget(), SLOT(setLow(int)));
connect(stretchPanel, SIGNAL(highChanged(int)), m_imageGL->imageWidget(), SLOT(setHigh(int)));
connect(stretchPanel, SIGNAL(stretchChanged(int)), m_imageGL->imageWidget(), SLOT(setStrech(int)));
connect(stretchPanel, SIGNAL(paramChanged(float)), m_imageGL->imageWidget(), SLOT(setStretchParam(float)));
connect(stretchPanel, SIGNAL(paramChanged(float,float,float)), m_imageGL->imageWidget(), SLOT(setMTFParams(float,float,float)));
m_ringList = new ImageRingList(this);
m_filesystem = new FilesystemWidget(m_ringList, this);
+34 -1
View File
@@ -3,9 +3,15 @@
#include <QPainter>
#include <QPaintEvent>
static float clamp(float x)
{
return std::min(std::max(x, 0.0f), 1.0f);
}
STFSlider::STFSlider(QWidget *parent) : QWidget(parent)
{
setMinimumHeight(15);
setMaximumHeight(15);
setMouseTracking(true);
m_blackPoint = 0;
m_midPoint = 0.5;
@@ -13,6 +19,29 @@ STFSlider::STFSlider(QWidget *parent) : QWidget(parent)
m_grabbed = -1;
}
float STFSlider::blackPoint() const
{
return m_blackPoint;
}
float STFSlider::midPoint() const
{
return m_midPoint;
}
float STFSlider::whitePoint() const
{
return m_whitePoint;
}
void STFSlider::setMTFParams(float low, float mid, float high)
{
m_blackPoint = clamp(low);
m_midPoint = clamp(mid);
m_whitePoint = clamp(high);
update();
}
void STFSlider::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
@@ -77,7 +106,10 @@ void STFSlider::mouseMoveEvent(QMouseEvent *event)
break;
}
if(m_grabbed >= 0)
repaint();
{
emit paramChanged(m_blackPoint, midPoint(), m_whitePoint);
update();
}
}
void STFSlider::mousePressEvent(QMouseEvent *event)
@@ -95,4 +127,5 @@ void STFSlider::mousePressEvent(QMouseEvent *event)
void STFSlider::mouseReleaseEvent(QMouseEvent *)
{
m_grabbed = -1;
emit paramChanged(m_blackPoint, midPoint(), m_whitePoint);
}
+6
View File
@@ -13,6 +13,12 @@ class STFSlider : public QWidget
int m_grabbed;
public:
explicit STFSlider(QWidget *parent = nullptr);
float blackPoint() const;
float midPoint() const;
float whitePoint() const;
void setMTFParams(float low, float mid, float high);
signals:
void paramChanged(float blackPoint, float midPoint, float whitePoint);
protected:
void paintEvent(QPaintEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
+30 -56
View File
@@ -1,42 +1,33 @@
#include "stretchpanel.h"
#include <QVBoxLayout>
#include <QDebug>
#include <QPushButton>
#include "imageringlist.h"
#include "stfslider.h"
const float BLACK_POINT_SIGMA = -2.8f;
const float MAD_TO_SIGMA = 1.4826f;
const float TARGET_BACKGROUND = 0.25f;
float MTF(float x, float m)
{
if(x < 0)return 0;
if(x > 1)return 1;
return ((m - 1) * x) / ((2 * m - 1) * x - m);
}
StretchPanel::StretchPanel(QWidget *parent) : QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
QHBoxLayout *layout = new QHBoxLayout(this);
setLayout(layout);
m_lowSlider = new QSlider(Qt::Horizontal, this);
m_highSlider = new QSlider(Qt::Horizontal, this);
m_paramSlider = new QSlider(Qt::Horizontal, this);
m_stfSlider = new STFSlider(this);
layout->addWidget(m_stfSlider);
connect(m_stfSlider, SIGNAL(paramChanged(float, float, float)), this, SIGNAL(paramChanged(float,float,float)));
STFSlider *stfslider = new STFSlider(this);
m_lowSlider->setRange(0, UINT16_MAX);
m_lowSlider->setPageStep(512);
m_highSlider->setRange(0, UINT16_MAX);
m_highSlider->setPageStep(512);
m_highSlider->setValue(UINT16_MAX);
m_paramSlider->setRange(0, UINT16_MAX);
m_paramSlider->setPageStep(512);
m_stretchSelect = new QComboBox(this);
m_stretchSelect->addItems({tr("Linear"), tr("Square root"), tr("Power"), tr("Logarithm"), tr("Asinh")});
layout->addWidget(m_lowSlider);
layout->addWidget(m_highSlider);
layout->addWidget(m_paramSlider);
layout->addWidget(m_stretchSelect);
layout->addWidget(stfslider);
connect(m_lowSlider, SIGNAL(valueChanged(int)), this, SIGNAL(lowChanged(int)));
connect(m_highSlider, SIGNAL(valueChanged(int)), this, SIGNAL(highChanged(int)));
connect(m_paramSlider, SIGNAL(valueChanged(int)), this, SLOT(calculateParam()));
connect(m_stretchSelect, SIGNAL(activated(int)), this, SIGNAL(stretchChanged(int)));
connect(m_stretchSelect, SIGNAL(activated(int)), this, SLOT(calculateParam()));
QPushButton *resetButton = new QPushButton(tr("Reset STF"), this);
resetButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
layout->addWidget(resetButton);
connect(resetButton, SIGNAL(pressed()), this, SLOT(resetMTF()));
}
void StretchPanel::imageLoaded(Image *img)
@@ -47,36 +38,19 @@ void StretchPanel::imageLoaded(Image *img)
{
double mean, stdDev, median;
img->rawImage()->imageStats(&mean, &stdDev, &median, nullptr, nullptr);
double mad = img->rawImage()->MAD();
float l = median - mad;
m_lowSlider->setValue(l);
float p = std::log(0.25)/std::log(mean/UINT16_MAX);
m_paramSlider->setValue(p * UINT16_MAX);
qDebug() << "Low" << l << p;
median /= 65536;
double mad = img->rawImage()->MAD() / 65536;
float bp = median + mad * BLACK_POINT_SIGMA * MAD_TO_SIGMA;
float mid = MTF(median - bp, TARGET_BACKGROUND);
m_stfSlider->setMTFParams(bp, mid, 1.0f);
emit paramChanged(m_stfSlider->blackPoint(), m_stfSlider->midPoint(), 1.0f);
}
}
}
void StretchPanel::calculateParam()
void StretchPanel::resetMTF()
{
float val = m_paramSlider->value();
float param;
switch(m_stretchSelect->currentIndex())
{
case 2:
param = val/UINT16_MAX;
param = 1.0f / (param * 5.0f + 1);
break;
case 3:
param = val;
break;
case 4:
param = 1.0f/std::max(0.00001f, 1.0f-(val/UINT16_MAX));
//val += 100;
//param = val/100.0f;
break;
default:
return;
}
emit paramChanged(param);
m_stfSlider->setMTFParams(0, 0.5, 1);
emit paramChanged(0, 0.5, 1);
}
+4 -12
View File
@@ -2,29 +2,21 @@
#define STRETCHPANEL_H
#include <QWidget>
#include <QSlider>
#include <QComboBox>
#include "stfslider.h"
class Image;
class StretchPanel : public QWidget
{
Q_OBJECT
QSlider *m_lowSlider;
QSlider *m_highSlider;
QSlider *m_paramSlider;
QComboBox *m_stretchSelect;
STFSlider *m_stfSlider;
public:
explicit StretchPanel(QWidget *parent = nullptr);
public slots:
void imageLoaded(Image *img);
void resetMTF();
signals:
void lowChanged(int low);
void highChanged(int high);
void stretchChanged(int stretch);
void paramChanged(float param);
private slots:
void calculateParam();
void paramChanged(float low, float mid, float high);
};
#endif // STRETCHPANEL_H