Prepare for three channels STF
This commit is contained in:
@@ -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 ¶ms)
|
||||
{
|
||||
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
@@ -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 ¶ms);
|
||||
void setOffset(float dx, float dy);
|
||||
void superPixel(bool enable);
|
||||
void invert(bool enable);
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 ¶ms);
|
||||
void autoStretch();
|
||||
void invert(bool enable);
|
||||
void superPixel(bool enable);
|
||||
|
||||
Reference in New Issue
Block a user