Add box resize algorithm

This commit is contained in:
2024-01-14 14:28:28 +01:00
parent 0e0d29320e
commit 6539c78c57
3 changed files with 94 additions and 10 deletions
+5 -2
View File
@@ -478,15 +478,18 @@ void LoadRunable::run()
if(m_thumbnail) if(m_thumbnail)
{ {
if(rawImage) if(rawImage && rawImage->valid())
{ {
rawImage->resize(THUMB_SIZE, THUMB_SIZE);
rawImage->convertToThumbnail(); rawImage->convertToThumbnail();
}
QMetaObject::invokeMethod(m_receiver, "thumbnailLoadFinish", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage)); QMetaObject::invokeMethod(m_receiver, "thumbnailLoadFinish", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage));
} }
}
else else
{
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage), Q_ARG(ImageInfoData, info)); QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage), Q_ARG(ImageInfoData, info));
} }
}
catch(std::exception e) catch(std::exception e)
{ {
qDebug() << e.what(); qDebug() << e.what();
+86 -6
View File
@@ -388,6 +388,10 @@ const void *RawImage::origData(uint32_t row, uint32_t col) const
void RawImage::convertToThumbnail() void RawImage::convertToThumbnail()
{ {
if(!valid())
return;
if(m_thumbAspect == 0.0f)
m_thumbAspect = (float)width() / height(); m_thumbAspect = (float)width() / height();
std::unique_ptr<PixelType[]> outptr = std::make_unique<PixelType[]>(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(uint16_t)); std::unique_ptr<PixelType[]> outptr = std::make_unique<PixelType[]>(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(uint16_t));
uint16_t *out = reinterpret_cast<uint16_t*>(outptr.get()); uint16_t *out = reinterpret_cast<uint16_t*>(outptr.get());
@@ -400,6 +404,7 @@ void RawImage::convertToThumbnail()
{ {
int idx = (i*THUMB_SIZE + o)*4; int idx = (i*THUMB_SIZE + o)*4;
int idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch; int idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch;
if(m_channels == 1) if(m_channels == 1)
{ {
out[idx] = out[idx + 1] = out[idx + 2] = in[idx2] * scale; out[idx] = out[idx + 1] = out[idx + 2] = in[idx2] * scale;
@@ -559,14 +564,84 @@ bool RawImage::pixel(int x, int y, double &r, double &g, double &b) const
return true; return true;
} }
void RawImage::downscaleTo(uint32_t size) template<typename T>
void boxResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t oldh, const uint8_t *in_, uint8_t *out_)
{ {
/*if(size < width() || size < height()) if(oldw == 0 || oldh == 0)return;
const T *in = reinterpret_cast<const T*>(in_);
T *out = reinterpret_cast<T*>(out_);
float max = 255.0f;
if constexpr(std::is_same<T, uint16_t>::value)
max = UINT16_MAX;
float sx = (float)oldw / w;
float sy = (float)oldh / h;
float sx_ = (float)w / oldw;
float sy_ = (float)h / oldh;
float s = 1.0 / (sx * sy);
for(uint32_t y = 0; y < h; y++)
{ {
double s = (double)size / std::max(width(), height()); for(uint32_t x = 0; x < w; x++)
cv::Size dsize(std::floor(width() * s), std::floor(height() * s)); {
cv::resize(m_img, m_img, dsize, 0, 0, cv::INTER_AREA); float p[4] = {0.0f};
}*/ uint32_t xx = x * oldw / w;
uint32_t yy = y * oldh / h;
uint32_t xe = std::min((x + 1) * oldw / w, oldw - 1);
uint32_t ye = std::min((y + 1) * oldh / h, oldh - 1);
for(uint32_t o = yy; o <= ye; o++)
{
float cy = o * sy_ - y;
if(cy < 0.0f)cy = 1.0f + cy * sy;
else if(sy_ + cy > 1.0f)cy = (1.0f - cy) * sy;
else cy = 1.0f;
if(yy==ye)cy = sy;
for(uint32_t i = xx; i <= xe; i++)
{
float cx = i * sx_ - x;
if(cx < 0.0f)cx = 1.0f + cx * sx;
else if(sx_ + cx > 1.0f)cx = (1.0f - cx) * sx;
else cx = 1.0f;
if(xx==xe)cx = sx;
for(uint32_t z = 0; z < ch; z++)
p[z] += in[(o * oldw + i) * ch + z] * cy * cx;
}
}
for(uint32_t z = 0; z < ch; z++)
if constexpr(std::is_floating_point<T>::value)
out[(y * w + x) * ch + z] = p[z] * s;
else
out[(y * w + x) * ch + z] = std::clamp(std::round(p[z] * s), 0.0f, max);
}
}
}
void RawImage::resize(uint32_t w, uint32_t h)
{
if(!valid())return;
std::unique_ptr<PixelType[]> old_pixels = std::move(m_pixels);
uint32_t oldw = m_width;
uint32_t oldh = m_height;
m_thumbAspect = (float)m_width / m_height;
allocate(w, h, m_channels, m_type);
switch(m_type)
{
case RawImage::UINT8:
boxResample<uint8_t>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
break;
case RawImage::UINT16:
boxResample<uint16_t>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
break;
case RawImage::FLOAT32:
boxResample<float>(w, h, m_ch, oldw, oldh, old_pixels.get(), m_pixels.get());
break;
default:
qWarning() << "Resizing format not supported";
break;
}
} }
std::pair<float, float> RawImage::unitScale() const std::pair<float, float> RawImage::unitScale() const
@@ -692,3 +767,8 @@ std::vector<RawImage> RawImage::split() const
return planes; return planes;
} }
bool RawImage::valid() const
{
return m_width > 0 && m_height > 0;
}
+2 -1
View File
@@ -97,13 +97,14 @@ public:
void convertToGLFormat(); void convertToGLFormat();
float thumbAspect() const; float thumbAspect() const;
bool pixel(int x, int y, double &r, double &g, double &b) const; bool pixel(int x, int y, double &r, double &g, double &b) const;
void downscaleTo(uint32_t size); void resize(uint32_t w, uint32_t h);
std::pair<float, float> unitScale() const; std::pair<float, float> unitScale() const;
static std::shared_ptr<RawImage> fromPlanar(const RawImage &img); static std::shared_ptr<RawImage> fromPlanar(const RawImage &img);
static std::shared_ptr<RawImage> fromPlanar(const void *pixels, uint32_t w, uint32_t h, uint32_t ch, DataType type); static std::shared_ptr<RawImage> fromPlanar(const void *pixels, uint32_t w, uint32_t h, uint32_t ch, DataType type);
static size_t typeSize(DataType type); static size_t typeSize(DataType type);
std::vector<RawImage> split() const; std::vector<RawImage> split() const;
bool valid() const;
}; };
//Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr); //Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr);