Add box resize algorithm
This commit is contained in:
+5
-2
@@ -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
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user