Support really big images 50000px

This commit is contained in:
2024-11-30 21:51:47 +01:00
parent 9b7837e9fb
commit be1e65251d
3 changed files with 66 additions and 48 deletions
+19 -19
View File
@@ -190,10 +190,10 @@ void ImageWidgetGL::zoom(int zoom, const QPointF &mousePos)
if(!mousePos.isNull()) if(!mousePos.isNull())
focus = mousePos; focus = mousePos;
if(width() > m_image->width() * m_scale) if(width() > m_imgWidth * m_scale)
m_dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f; m_dx = -width() * 0.5f + m_imgWidth * m_scale * 0.5f;
if(height() > m_image->height() * m_scale) if(height() > m_imgHeight * m_scale)
m_dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f; m_dy = -height() * 0.5f + m_imgHeight * m_scale * 0.5f;
float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop)); float newScale = std::sqrt(std::pow(2.0f, (float)m_scaleStop));
float r = newScale / m_scale; float r = newScale / m_scale;
@@ -237,10 +237,10 @@ QVector2D ImageWidgetGL::getImagePixelCoord(const QVector2D &pos)
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
if(m_width > m_image->width()*m_scale) if(m_width > m_imgWidth * m_scale)
dx = -width()*0.5f + m_image->width()*m_scale*0.5f; dx = -width()*0.5f + m_imgWidth*m_scale * 0.5f;
if(m_height > m_image->height()*m_scale) if(m_height > m_imgHeight * m_scale)
dy = -height()*0.5f + m_image->height()*m_scale*0.5f; dy = -height()*0.5f + m_imgHeight*m_scale * 0.5f;
QVector2D offset(dx, dy); QVector2D offset(dx, dy);
return (pos + offset) / m_scale; return (pos + offset) / m_scale;
@@ -353,8 +353,8 @@ void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scal
int height = widget->height(); int height = widget->height();
QImage img(width, height, QImage::Format_RGB32); QImage img(width, height, QImage::Format_RGB32);
img.fill(Qt::gray); img.fill(Qt::gray);
int ox = dx; int64_t ox = dx;
int oy = dy; int64_t oy = dy;
auto mtf = [&mtfParams](int i, float x) auto mtf = [&mtfParams](int i, float x)
{ {
@@ -376,18 +376,18 @@ void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scal
float r[4]; float r[4];
float g[4]; float g[4];
float b[4]; float b[4];
for(int y = std::max(0, -oy); y < height; y++) for(int64_t y = std::max((int64_t)0, -oy); y < height; y++)
{ {
uint32_t *pixels = (uint32_t*)(img.scanLine(y)); uint32_t *pixels = (uint32_t*)(img.scanLine(y));
float iptr; float iptr;
float fy = std::modf((y + oy) * iscale - 0.5f, &iptr); float fy = std::modf((y + oy) * iscale - 0.5f, &iptr);
int py = iptr; int64_t py = iptr;
uint32_t w = py * rawImage->widthBytes(); int64_t w = py * rawImage->widthBytes();
uint32_t w2 = w; int64_t w2 = w;
if(py+1 < imgHeight)w2 += rawImage->widthBytes(); if(py+1 < imgHeight)w2 += rawImage->widthBytes();
if(py >= imgHeight)break; if(py >= imgHeight)break;
for(int x = std::max(0, -ox); x < width; x++) for(int64_t x = std::max((int64_t)0, -ox); x < width; x++)
{ {
float fx = std::modf((x + ox) * iscale - 0.5f, &iptr); float fx = std::modf((x + ox) * iscale - 0.5f, &iptr);
int px = iptr; int px = iptr;
@@ -467,10 +467,10 @@ void ImageWidgetGL::paintGL()
{ {
float dx = m_dx; float dx = m_dx;
float dy = m_dy; float dy = m_dy;
if(m_width > m_image->width() * m_scale) if(m_width > m_imgWidth * m_scale)
dx = -width() * 0.5f + m_image->width() * m_scale * 0.5f; dx = -width() * 0.5f + m_imgWidth * m_scale * 0.5f;
if(m_height > m_image->height() * m_scale) if(m_height > m_imgHeight * m_scale)
dy = -height() * 0.5f + m_image->height() * m_scale * 0.5f; dy = -height() * 0.5f + m_imgHeight * m_scale * 0.5f;
QBrush highlight = style()->standardPalette().highlight(); QBrush highlight = style()->standardPalette().highlight();
f->glClear(GL_COLOR_BUFFER_BIT); f->glClear(GL_COLOR_BUFFER_BIT);
+46 -28
View File
@@ -45,7 +45,7 @@ void RawImage::allocate(uint32_t w, uint32_t h, uint32_t ch, DataType type)
m_channels = ch; m_channels = ch;
m_ch = ch == 3 ? 4 : ch; m_ch = ch == 3 ? 4 : ch;
m_origType = m_type = type; m_origType = m_type = type;
m_pixels = std::make_unique<PixelType[]>(m_width * m_height * m_ch * typeSize(type)); m_pixels = std::make_unique<PixelType[]>((size_t)m_width * m_height * m_ch * typeSize(type));
} }
RawImage::RawImage() RawImage::RawImage()
@@ -60,7 +60,7 @@ RawImage::RawImage(uint32_t w, uint32_t h, uint32_t ch, DataType type)
RawImage::RawImage(const RawImage &d) RawImage::RawImage(const RawImage &d)
{ {
allocate(d.m_width, d.m_height, d.m_channels, d.m_type); allocate(d.m_width, d.m_height, d.m_channels, d.m_type);
std::memcpy(m_pixels.get(), d.m_pixels.get(), m_width * m_height * m_ch * typeSize(m_type)); std::memcpy(m_pixels.get(), d.m_pixels.get(), (size_t)m_width * m_height * m_ch * typeSize(m_type));
m_stats = d.m_stats; m_stats = d.m_stats;
} }
@@ -118,6 +118,24 @@ RawImage::RawImage(const QImage &img)
for(int i=0; i<img.height(); i++) for(int i=0; i<img.height(); i++)
std::memcpy(data(i), img.scanLine(i), img.width()*2); std::memcpy(data(i), img.scanLine(i), img.width()*2);
} }
else if(img.format() == QImage::Format_RGB32 || img.format() == QImage::Format_ARGB32)
{
allocate(img.width(), img.height(), 4, UINT8);
for(int i=0; i<img.height(); i++)
{
uint32_t *src = (uint32_t*)img.scanLine(i);
uint32_t *dst = (uint32_t*)data(i);
for(int o=0; o<img.width(); o++)
{
uint32_t p = src[o];
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
dst[o] = (p & 0xff000000) | (p >> 16 & 0xff) | (p & 0xff00) | (p << 16 & 0xff0000);
#else
dst[o] = (p >> 24) | (p << 8 & 0xffffff00);
#endif
}
}
}
else else
{ {
QImage tmp = img.convertToFormat(QImage::Format_RGBA8888); QImage tmp = img.convertToFormat(QImage::Format_RGBA8888);
@@ -294,9 +312,9 @@ uint32_t RawImage::channels() const
return m_channels; return m_channels;
} }
uint32_t RawImage::size() const uint64_t RawImage::size() const
{ {
return width()*height(); return (uint64_t)width()*height();
} }
RawImage::DataType RawImage::type() const RawImage::DataType RawImage::type() const
@@ -336,12 +354,12 @@ const void *RawImage::data() const
void *RawImage::data(uint32_t row, uint32_t col) void *RawImage::data(uint32_t row, uint32_t col)
{ {
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
const void *RawImage::data(uint32_t row, uint32_t col) const const void *RawImage::data(uint32_t row, uint32_t col) const
{ {
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
const void *RawImage::origData() const const void *RawImage::origData() const
@@ -356,12 +374,12 @@ const void *RawImage::origData(uint32_t row, uint32_t col) const
{ {
if(m_original) if(m_original)
{ {
col = col * m_origWidth / m_width; col = (uint64_t)col * m_origWidth / m_width;
row = row * m_origHeight / m_height; row = (uint64_t)row * m_origHeight / m_height;
return m_original.get() + (m_origWidth * row * m_ch + col * m_ch) * typeSize(m_origType); return m_original.get() + ((size_t)m_origWidth * row * m_ch + (size_t)col * m_ch) * typeSize(m_origType);
} }
else else
return m_pixels.get() + (m_width * row * m_ch + col * m_ch) * typeSize(m_type); return m_pixels.get() + ((size_t)m_width * row * m_ch + (size_t)col * m_ch) * typeSize(m_type);
} }
bool RawImage::planar() const bool RawImage::planar() const
@@ -381,12 +399,12 @@ void RawImage::convertToThumbnail()
auto loop = [&](F16 *out, auto *in, float scale) auto loop = [&](F16 *out, auto *in, float scale)
{ {
for(int i=0; i<THUMB_SIZE; i++) for(int64_t i=0; i<THUMB_SIZE; i++)
{ {
for(int o=0; o<THUMB_SIZE; o++) for(int64_t o=0; o<THUMB_SIZE; o++)
{ {
int idx = (i*THUMB_SIZE + o)*4; int64_t idx = (i*THUMB_SIZE + o)*4;
int idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch; int64_t idx2 = ((i * m_height / THUMB_SIZE * m_width) + (o * m_width / THUMB_SIZE)) * m_ch;
if(m_channels == 1) if(m_channels == 1)
{ {
@@ -442,21 +460,21 @@ void RawImage::convertToGLFormat()
} }
template<typename T, typename U> template<typename T, typename U>
void convertType2(uint32_t size, const T *src, U *dst) void convertType2(size_t size, const T *src, U *dst)
{ {
if constexpr((std::is_floating_point_v<T> || std::is_same_v<T, F16>) && (std::is_floating_point_v<U> || std::is_same_v<T, F16>)) if constexpr((std::is_floating_point_v<T> || std::is_same_v<T, F16>) && (std::is_floating_point_v<U> || std::is_same_v<T, F16>))
{ {
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i]; dst[i] = src[i];
} }
if constexpr(std::is_integral_v<T> && std::is_integral_v<U>) if constexpr(std::is_integral_v<T> && std::is_integral_v<U>)
{ {
if constexpr(sizeof(T) > sizeof(U)) if constexpr(sizeof(T) > sizeof(U))
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8); dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8);
else else
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = static_cast<U>(src[i]) << ((sizeof(U) - sizeof(T)) * 8); dst[i] = static_cast<U>(src[i]) << ((sizeof(U) - sizeof(T)) * 8);
} }
@@ -464,20 +482,20 @@ void convertType2(uint32_t size, const T *src, U *dst)
{ {
U max = std::numeric_limits<U>::max(); U max = std::numeric_limits<U>::max();
T scale = (T)(max); T scale = (T)(max);
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = src[i] * scale; dst[i] = src[i] * scale;
} }
if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>)) if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>))
{ {
U scale = (U)(1.0 / (double)std::numeric_limits<T>::max()); U scale = (U)(1.0 / (double)std::numeric_limits<T>::max());
for(uint32_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = (U)src[i] * scale; dst[i] = (U)src[i] * scale;
} }
} }
template<typename T> template<typename T>
void convertType(uint32_t size, RawImage::DataType dstType, const T *src, void *dst) void convertType(size_t size, RawImage::DataType dstType, const T *src, void *dst)
{ {
switch(dstType) switch(dstType)
{ {
@@ -514,7 +532,7 @@ void RawImage::convertToType(DataType type)
allocate(m_width, m_height, m_channels, type); allocate(m_width, m_height, m_channels, type);
m_origType = origType; m_origType = origType;
uint32_t s = size() * m_ch; size_t s = size() * m_ch;
switch(m_origType) switch(m_origType)
{ {
case UINT8: case UINT8:
@@ -656,15 +674,15 @@ void boxResample(uint32_t w, uint32_t h, uint32_t ch, uint32_t oldw, uint32_t ol
float sx = (float)w / oldw; float sx = (float)w / oldw;
float sy = (float)h / oldh; float sy = (float)h / oldh;
for(uint32_t y = 0; y < h; y++)//iterate over destination Y for(uint64_t y = 0; y < h; y++)//iterate over destination Y
{ {
for(uint32_t x = 0; x < w; x++)//iterate over destination X for(uint64_t x = 0; x < w; x++)//iterate over destination X
{ {
U p[4] = {0.0f}; U p[4] = {0.0f};
uint32_t xx = x * oldw / w;//calculate source rect uint64_t xx = x * oldw / w;//calculate source rect
uint32_t yy = y * oldh / h; uint64_t yy = y * oldh / h;
uint32_t xe = std::min((x + 1) * oldw / w, oldw - 1); uint64_t xe = std::min((x + 1) * oldw / w, (uint64_t)oldw - 1);
uint32_t ye = std::min((y + 1) * oldh / h, oldh - 1); uint64_t ye = std::min((y + 1) * oldh / h, (uint64_t)oldh - 1);
for(uint32_t o = yy; o <= ye; o++)//iterate over source Y for(uint32_t o = yy; o <= ye; o++)//iterate over source Y
{ {
float cy = o * sy - y; float cy = o * sy - y;
+1 -1
View File
@@ -89,7 +89,7 @@ public:
uint32_t width() const; uint32_t width() const;
uint32_t height() const; uint32_t height() const;
uint32_t channels() const; uint32_t channels() const;
uint32_t size() const; uint64_t size() const;
DataType type() const; DataType type() const;
uint32_t norm() const; uint32_t norm() const;
uint32_t widthBytes() const; uint32_t widthBytes() const;