Add box resize algorithm
This commit is contained in:
+5
-2
@@ -478,14 +478,17 @@ void LoadRunable::run()
|
||||
|
||||
if(m_thumbnail)
|
||||
{
|
||||
if(rawImage)
|
||||
if(rawImage && rawImage->valid())
|
||||
{
|
||||
rawImage->resize(THUMB_SIZE, THUMB_SIZE);
|
||||
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
|
||||
{
|
||||
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(std::shared_ptr<RawImage>, rawImage), Q_ARG(ImageInfoData, info));
|
||||
}
|
||||
}
|
||||
catch(std::exception e)
|
||||
{
|
||||
|
||||
+87
-7
@@ -388,7 +388,11 @@ const void *RawImage::origData(uint32_t row, uint32_t col) const
|
||||
|
||||
void RawImage::convertToThumbnail()
|
||||
{
|
||||
m_thumbAspect = (float)width() / height();
|
||||
if(!valid())
|
||||
return;
|
||||
|
||||
if(m_thumbAspect == 0.0f)
|
||||
m_thumbAspect = (float)width() / height();
|
||||
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());
|
||||
|
||||
@@ -400,6 +404,7 @@ void RawImage::convertToThumbnail()
|
||||
{
|
||||
int idx = (i*THUMB_SIZE + o)*4;
|
||||
int idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch;
|
||||
|
||||
if(m_channels == 1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
cv::Size dsize(std::floor(width() * s), std::floor(height() * s));
|
||||
cv::resize(m_img, m_img, dsize, 0, 0, cv::INTER_AREA);
|
||||
}*/
|
||||
for(uint32_t x = 0; x < w; x++)
|
||||
{
|
||||
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
|
||||
@@ -692,3 +767,8 @@ std::vector<RawImage> RawImage::split() const
|
||||
|
||||
return planes;
|
||||
}
|
||||
|
||||
bool RawImage::valid() const
|
||||
{
|
||||
return m_width > 0 && m_height > 0;
|
||||
}
|
||||
|
||||
+2
-1
@@ -97,13 +97,14 @@ public:
|
||||
void convertToGLFormat();
|
||||
float thumbAspect() 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;
|
||||
|
||||
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 size_t typeSize(DataType type);
|
||||
std::vector<RawImage> split() const;
|
||||
bool valid() const;
|
||||
};
|
||||
|
||||
//Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr);
|
||||
|
||||
Reference in New Issue
Block a user