Compare commits

..

2 Commits

Author SHA1 Message Date
nou 5249b277ec Add integer resample 2025-02-25 17:41:29 +01:00
nou e4b9fefa5a Move MTFParam 2025-02-25 17:35:55 +01:00
8 changed files with 119 additions and 10 deletions
+1
View File
@@ -46,6 +46,7 @@ set(TENMON_SRC
main.cpp
mainwindow.cpp mainwindow.h
markedfiles.cpp markedfiles.h
mtfparam.h
rawimage.cpp rawimage.h
rawimage_sse.cpp
scriptengine.cpp scriptengine.h
+1 -1
View File
@@ -359,7 +359,7 @@ void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scal
auto mtf = [&mtfParams](int i, float x)
{
x = (x - mtfParams.blackPoint[i]) / (mtfParams.whitePoint[i] - mtfParams.blackPoint[i]);
x = std::min(std::max(x, 0.0f), 1.0f);
x = std::clamp(x, 0.0f, 1.0f);
return ((mtfParams.midPoint[i] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[i] - 1.0f) * x - mtfParams.midPoint[i]);
};
+40
View File
@@ -191,6 +191,17 @@ void ConvertRunable::run()
QFileInfo info(m_outfile);
info.dir().mkpath(".");
if(m_params.binning > 1)
{
rawimage->resizeInt(m_params.binning, m_params.average);
}
else if(m_params.resize.isValid() && !m_params.resize.isEmpty())
{
QSize imgSize(rawimage->width(), rawimage->height());
imgSize = imgSize.scaled(m_params.resize, m_params.aspect);
rawimage->resize(imgSize.width(), imgSize.height());
}
if(rawimage)
{
if(m_format == "xisf")
@@ -323,4 +334,33 @@ ConvertRunable::ConvertParams::ConvertParams(const QVariantMap &map)
if(map.contains("compressionType"))
compressionType = map["compressionType"].toString();
if(map.contains("binning"))
binning = map["binning"].toInt();
if(map.contains("average"))
average = map["average"].toBool();
if(map.contains("resize"))
{
QVariantMap size = map["resize"].toMap();
if(size.contains("width") && size.contains("height"))
{
int w = size["width"].toInt();
int h = size["height"].toInt();
resize = QSize(w, h);
}
}
if(map.contains("aspect"))
{
QString aspectStr = map["aspect"].toString();
if(aspectStr == "keep")
aspect = Qt::KeepAspectRatio;
else if(aspectStr == "expand")
aspect = Qt::KeepAspectRatioByExpanding;
else if(aspectStr == "ignore")
aspect = Qt::IgnoreAspectRatio;
}
}
+5
View File
@@ -4,6 +4,7 @@
#include <QRunnable>
#include <QString>
#include <QSemaphore>
#include <QSize>
#include "imageinfodata.h"
class Image;
@@ -26,6 +27,10 @@ public:
{
int compressionLevel = -1;
QString compressionType;
int binning = 0;
bool average = true;
QSize resize;
Qt::AspectRatioMode aspect = Qt::KeepAspectRatio;
ConvertParams(){}
ConvertParams(const QVariantMap &map);
};
+11
View File
@@ -0,0 +1,11 @@
#ifndef MTFPARAM_H
#define MTFPARAM_H
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};
};
#endif // MTFPARAM_H
+59 -2
View File
@@ -9,10 +9,9 @@
using F16 = qfloat16;
#else
#include <algorithm>
using F16 = uint16_t;
using F16 = _Float16;
#endif
int THUMB_SIZE = 128;
int THUMB_SIZE_BORDER = 138;
int THUMB_SIZE_BORDER_Y = 158;
@@ -755,6 +754,64 @@ void RawImage::resize(uint32_t w, uint32_t h)
}
}
template<typename T, typename U>
void integerResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t down, bool avg, const uint8_t *in_, uint8_t *out_)
{
const T *in = reinterpret_cast<const T*>(in_);
T *out = reinterpret_cast<T*>(out_);
uint32_t down2 = down * down;
U m = std::numeric_limits<T>::max();
if constexpr(std::is_floating_point_v<T>)m = down2;
for(uint64_t i = 0; i < h; i++)
{
for(uint64_t o = 0; o < w; o++)
{
for(uint64_t p = 0; p < ch; p++)
{
U pix = 0;
for(uint32_t y = 0; y < down; y++)
for(uint32_t x = 0; x < down; x++)
pix += in[((i * down) + y) * oldw * ch + ((o * down) + x) * ch + p];
if (avg)
out[(i * w + o) * ch + p] = pix / down2;
else
out[(i * w + o) * ch + p] = std::min(pix, m);
}
}
}
}
void RawImage::resizeInt(int downsample, bool avg)
{
uint32_t oldw = m_width;
std::unique_ptr<PixelType[]> old_pixels = std::move(m_pixels);
allocate(m_width / downsample, m_height / downsample, m_channels, m_type);
switch(m_type)
{
case RawImage::UINT8:
integerResample<uint8_t, uint32_t>(m_width, m_height, m_ch, oldw, downsample, avg, old_pixels.get(), m_pixels.get());
break;
case RawImage::UINT16:
integerResample<uint16_t, uint32_t>(m_width, m_height, m_ch, oldw, downsample, avg, old_pixels.get(), m_pixels.get());
break;
case RawImage::UINT32:
integerResample<uint32_t, uint64_t>(m_width, m_height, m_ch, oldw, downsample, avg, old_pixels.get(), m_pixels.get());
break;
case RawImage::FLOAT32:
integerResample<float, double>(m_width, m_height, m_ch, oldw, downsample, avg, old_pixels.get(), m_pixels.get());
break;
case RawImage::FLOAT64:
integerResample<double, double>(m_width, m_height, m_ch, oldw, downsample, avg, old_pixels.get(), m_pixels.get());
break;
default:
break;
}
}
std::pair<float, float> RawImage::unitScale() const
{
float min = *std::min_element(m_stats.m_min, m_stats.m_min + 4);
+1
View File
@@ -111,6 +111,7 @@ public:
float thumbAspect() const;
bool pixel(int x, int y, double &r, double &g, double &b) const;
void resize(uint32_t w, uint32_t h);
void resizeInt(int downsample, bool avg);
std::pair<float, float> unitScale() const;
void flip();
+1 -7
View File
@@ -4,16 +4,10 @@
#include <QToolBar>
#include <QStackedWidget>
#include "stfslider.h"
#include "mtfparam.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