SW rendering when image is too big for texture
This commit is contained in:
+136
-7
@@ -10,6 +10,7 @@
|
||||
#include <QDragEnterEvent>
|
||||
#include <QPainter>
|
||||
#include "imageringlist.h"
|
||||
#include <QFloat16>
|
||||
|
||||
int FILTERING = 1;
|
||||
bool OpenGLES = false;
|
||||
@@ -110,16 +111,15 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
|
||||
m_error.clear();
|
||||
makeCurrent();
|
||||
m_rawImage = image;
|
||||
if((int)image->width() > m_maxTextureSize || (int)image->height() > m_maxTextureSize)
|
||||
{
|
||||
uint32_t newW = std::min(image->width() * m_maxTextureSize / image->width(), image->width() * m_maxTextureSize / image->height());
|
||||
uint32_t newH = std::min(image->height() * m_maxTextureSize / image->width(), image->height() * m_maxTextureSize / image->height());
|
||||
m_rawImage->resize(newW, newH);
|
||||
}
|
||||
|
||||
m_imgWidth = image->width();
|
||||
m_imgHeight = image->height();
|
||||
|
||||
bool tooBig = false;
|
||||
if((int)image->width() > m_maxTextureSize || (int)image->height() > m_maxTextureSize)
|
||||
{
|
||||
tooBig = true;
|
||||
m_swPaint = true;
|
||||
}
|
||||
|
||||
if(!m_image)return;
|
||||
|
||||
@@ -133,6 +133,9 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
|
||||
m_lut->setData(0, 0, 0, LUT_SIZE, LUT_SIZE, LUT_SIZE, 0, QOpenGLTexture::RGBA, QOpenGLTexture::RGBA, QOpenGLTexture::Float16, image->getLUT().data());
|
||||
}
|
||||
|
||||
if(!tooBig)
|
||||
{
|
||||
while(f->glGetError() != GL_NO_ERROR);
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
m_image->destroy();
|
||||
@@ -148,6 +151,8 @@ void ImageWidgetGL::setImage(std::shared_ptr<RawImage> image, int index)
|
||||
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
f->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
qDebug() << "setImage" << timer.elapsed();
|
||||
m_swPaint = f->glGetError() != GL_NO_ERROR;
|
||||
}
|
||||
|
||||
m_unit_scale[0] = 1.0f;
|
||||
m_unit_scale[1] = 0.0f;
|
||||
@@ -341,6 +346,123 @@ void ImageWidgetGL::showThumbnail(bool enable)
|
||||
setOffset(m_dx, m_dy);
|
||||
}
|
||||
|
||||
void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scale, const MTFParam &mtfParams, QWidget *widget)
|
||||
{
|
||||
QPainter painter(widget);
|
||||
int width = widget->width();
|
||||
int height = widget->height();
|
||||
QImage img(width, height, QImage::Format_RGB32);
|
||||
img.fill(Qt::gray);
|
||||
int ox = dx;
|
||||
int oy = dy;
|
||||
|
||||
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);
|
||||
return ((mtfParams.midPoint[i] - 1.0f) * x) / ((2.0f * mtfParams.midPoint[i] - 1.0f) * x - mtfParams.midPoint[i]);
|
||||
};
|
||||
|
||||
int imgWidth = rawImage->width();
|
||||
int imgHeight = rawImage->height();
|
||||
|
||||
auto convert = [&](auto *src)
|
||||
{
|
||||
float s = 1.0f;
|
||||
if constexpr(std::numeric_limits<std::remove_reference_t<decltype(*src)>>::is_integer)
|
||||
s = (float)std::numeric_limits<std::remove_reference_t<decltype(*src)>>::max();
|
||||
|
||||
float iscale = 1.0f / scale;
|
||||
float r[4];
|
||||
float g[4];
|
||||
float b[4];
|
||||
for(int y = std::max(0, -oy); y < height; y++)
|
||||
{
|
||||
uint32_t *pixels = (uint32_t*)(img.scanLine(y));
|
||||
float iptr;
|
||||
float fy = std::modf((y + oy) * iscale - 0.5f, &iptr);
|
||||
int py = iptr;
|
||||
uint32_t w = py * rawImage->widthBytes();
|
||||
uint32_t w2 = w;
|
||||
if(py+1 < imgHeight)w2 += rawImage->widthBytes();
|
||||
if(py >= imgHeight)break;
|
||||
|
||||
for(int x = std::max(0, -ox); x < width; x++)
|
||||
{
|
||||
float fx = std::modf((x + ox) * iscale - 0.5f, &iptr);
|
||||
int px = iptr;
|
||||
int px2 = px + 1 < imgWidth ? px + 1 : px;
|
||||
if(px >= imgWidth)break;
|
||||
|
||||
|
||||
if(rawImage->channels() > 1)
|
||||
{
|
||||
r[0] = src[w + px * 4 + 0];
|
||||
g[0] = src[w + px * 4 + 1];
|
||||
b[0] = src[w + px * 4 + 2];
|
||||
r[1] = src[w + px2 * 4 + 0];
|
||||
g[1] = src[w + px2 * 4 + 1];
|
||||
b[1] = src[w + px2 * 4 + 2];
|
||||
r[2] = src[w2 + px * 4 + 0];
|
||||
g[2] = src[w2 + px * 4 + 1];
|
||||
b[2] = src[w2 + px * 4 + 2];
|
||||
r[3] = src[w2 + px2 * 4 + 0];
|
||||
g[3] = src[w2 + px2 * 4 + 1];
|
||||
b[3] = src[w2 + px2 * 4 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
r[0] = src[w + px];
|
||||
r[2] = src[w2 + px];
|
||||
r[1] = src[w + px2];
|
||||
r[3] = src[w2 + px2];
|
||||
}
|
||||
|
||||
uint32_t rgb = 0xff000000;
|
||||
if(rawImage->channels() > 1)
|
||||
{
|
||||
rgb |= (uint8_t)(mtf(0, ((r[3] * fx + r[2] * (1.0f - fx)) * fy + (r[1] * fx + r[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f) << 16;
|
||||
rgb |= (uint8_t)(mtf(1, ((g[3] * fx + g[2] * (1.0f - fx)) * fy + (g[1] * fx + g[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f) << 8;
|
||||
rgb |= (uint8_t)(mtf(1, ((b[3] * fx + b[2] * (1.0f - fx)) * fy + (b[1] * fx + b[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t v = (uint8_t)(mtf(0, ((r[3] * fx + r[2] * (1.0f - fx)) * fy + (r[1] * fx + r[0] * (1.0f - fx)) * (1.0f - fy)) / s) * 255.0f);
|
||||
rgb = 0xff000000 | (v << 16) | (v << 8) | v;
|
||||
}
|
||||
pixels[x] = rgb;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(rawImage)
|
||||
{
|
||||
switch(rawImage->type())
|
||||
{
|
||||
case RawImage::UINT8:
|
||||
convert(static_cast<uint8_t*>(rawImage->data()));
|
||||
break;
|
||||
case RawImage::UINT16:
|
||||
convert(static_cast<uint16_t*>(rawImage->data()));
|
||||
break;
|
||||
case RawImage::UINT32:
|
||||
convert(static_cast<uint32_t*>(rawImage->data()));
|
||||
break;
|
||||
case RawImage::FLOAT16:
|
||||
convert(static_cast<qfloat16*>(rawImage->data()));
|
||||
break;
|
||||
case RawImage::FLOAT32:
|
||||
convert(static_cast<float*>(rawImage->data()));
|
||||
break;
|
||||
case RawImage::FLOAT64:
|
||||
convert(static_cast<double*>(rawImage->data()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
painter.drawImage(0, 0, img);
|
||||
}
|
||||
|
||||
void ImageWidgetGL::paintGL()
|
||||
{
|
||||
float dx = m_dx;
|
||||
@@ -424,6 +546,12 @@ void ImageWidgetGL::paintGL()
|
||||
painter.drawText(0, 0, width(), height(), Qt::AlignCenter | Qt::AlignHCenter, m_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_swPaint)
|
||||
{
|
||||
swPaint(m_rawImage, dx, dy, m_scale, m_mtfParams, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vao->bind();
|
||||
debayer();
|
||||
@@ -451,6 +579,7 @@ void ImageWidgetGL::paintGL()
|
||||
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
m_vao->release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ class ImageWidgetGL : public QOpenGLWidget, public ImageWidget
|
||||
Database *m_database = nullptr;
|
||||
QPointF m_lastPos;
|
||||
QString m_error;
|
||||
bool m_swPaint = false;
|
||||
public:
|
||||
explicit ImageWidgetGL(Database *database, QWidget *parent = nullptr);
|
||||
~ImageWidgetGL() override;
|
||||
|
||||
Reference in New Issue
Block a user