mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Performance: Added Utils::copyFromQImage() in cvfqtUtils. Optimized copy
for QImage::Format_ARGB32, and use this function from the paint event in cafViewer.
This commit is contained in:
parent
a5a1dfe701
commit
15eab9b261
@ -454,28 +454,13 @@ void caf::Viewer::paintEvent(QPaintEvent* event)
|
||||
// Convert the QImage into the cvf::TextureImage,
|
||||
// handling vertical mirroring and (possible) byteswapping
|
||||
|
||||
if (((int)m_overlayTextureImage->height()) != this->height() || ((int)m_overlayTextureImage->width() != this->width()))
|
||||
if (((int)m_overlayTextureImage->height()) != this->height() || ((int)m_overlayTextureImage->width() != this->width()))
|
||||
{
|
||||
m_overlayTextureImage->allocate(this->width(), this->height());
|
||||
}
|
||||
|
||||
int height = m_overlayTextureImage->height();
|
||||
int width = m_overlayTextureImage->width();
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int y = 0 ; y < height; ++y)
|
||||
{
|
||||
int negy = height - 1 - y;
|
||||
for (int x = 0 ; x < width; ++x)
|
||||
{
|
||||
// Should probably do direct conversion on byte level. Would be faster
|
||||
// QImage.bits() and cvf::TextureImage.ptr() (casting away const)
|
||||
QRgb qtRgbaVal = m_overlayPaintingQImage.pixel(x, negy);
|
||||
cvf::Color4ub cvfRgbVal(qRed(qtRgbaVal), qGreen(qtRgbaVal), qBlue(qtRgbaVal), qAlpha(qtRgbaVal));
|
||||
m_overlayTextureImage->setPixel(x, y, cvfRgbVal);
|
||||
}
|
||||
}
|
||||
|
||||
cvfqt::Utils::copyFromQImage(m_overlayTextureImage.p(), m_overlayPaintingQImage);
|
||||
|
||||
m_overlayImage->setImage(m_overlayTextureImage.p());
|
||||
m_overlayImage->setPixelSize(cvf::Vec2ui(this->width(), this->height()));
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfTextureImage.h"
|
||||
|
||||
#include "cvfqtUtils.h"
|
||||
|
||||
@ -89,14 +90,14 @@ cvf::String Utils::fromQString(const QString& qtString)
|
||||
{
|
||||
if (qtString.length() == 0)
|
||||
{
|
||||
return cvf::String();
|
||||
return cvf::String();
|
||||
}
|
||||
|
||||
if (sizeof(wchar_t) == 2)
|
||||
{
|
||||
const wchar_t* strPtr = reinterpret_cast<const wchar_t*>(qtString.utf16());
|
||||
|
||||
return cvf::String(strPtr);
|
||||
return cvf::String(strPtr);
|
||||
}
|
||||
else if (sizeof(wchar_t) == 4)
|
||||
{
|
||||
@ -104,11 +105,78 @@ cvf::String Utils::fromQString(const QString& qtString)
|
||||
ucs4Str.push_back(0);
|
||||
const wchar_t* strPtr = reinterpret_cast<const wchar_t*>(ucs4Str.data());
|
||||
|
||||
return cvf::String(strPtr);
|
||||
return cvf::String(strPtr);
|
||||
}
|
||||
|
||||
CVF_FAIL_MSG("Unexpected sizeof wchar_t");
|
||||
return cvf::String();
|
||||
return cvf::String();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Utils::copyFromQImage(cvf::TextureImage* textureImage, const QImage& qtImage)
|
||||
{
|
||||
CVF_ASSERT(textureImage);
|
||||
|
||||
if (qtImage.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (((int)textureImage->height()) != qtImage.height() || ((int)textureImage->width() != qtImage.width()))
|
||||
{
|
||||
textureImage->allocate(qtImage.width(), qtImage.height());
|
||||
}
|
||||
|
||||
int height = textureImage->height();
|
||||
int width = textureImage->width();
|
||||
|
||||
// Check if QImage has format QImage::Format_ARGB32, and perform a direct memory copy of image data
|
||||
if (qtImage.format() == QImage::Format_ARGB32)
|
||||
{
|
||||
cvf::ubyte* dataPtr = const_cast<cvf::ubyte*>(textureImage->ptr());
|
||||
|
||||
int negy = 0;
|
||||
uint idx = 0;
|
||||
QRgb qtRgbaVal = 0;
|
||||
|
||||
// This loop is a candidate for multi-threading. Testing with OpenMP has so far indicated
|
||||
// quite large variance in performance (Windows Intel i7 with 8 cores).
|
||||
// When this function is called from the paint event,
|
||||
// the user experience is considered better when the paint time is consistent.
|
||||
for (int y = 0 ; y < height; ++y)
|
||||
{
|
||||
negy = height - 1 - y;
|
||||
const uchar* s = qtImage.scanLine(negy);
|
||||
|
||||
for (int x = 0 ; x < width; ++x)
|
||||
{
|
||||
qtRgbaVal = ((QRgb*)s)[x]; // Taken from QImage::pixel(int x, int y)
|
||||
|
||||
idx = 4*(y*width + x);
|
||||
dataPtr[idx] = qRed(qtRgbaVal);
|
||||
dataPtr[idx + 1] = qGreen(qtRgbaVal);
|
||||
dataPtr[idx + 2] = qBlue(qtRgbaVal);
|
||||
dataPtr[idx + 3] = qAlpha(qtRgbaVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0 ; y < height; ++y)
|
||||
{
|
||||
int negy = height - 1 - y;
|
||||
QRgb qtRgbaVal;
|
||||
cvf::Color4ub cvfRgbVal;
|
||||
for (int x = 0 ; x < width; ++x)
|
||||
{
|
||||
qtRgbaVal = qtImage.pixel(x, negy);
|
||||
cvfRgbVal.set(qRed(qtRgbaVal), qGreen(qtRgbaVal), qBlue(qtRgbaVal), qAlpha(qtRgbaVal));
|
||||
textureImage->setPixel(x, y, cvfRgbVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,6 +40,11 @@
|
||||
#include "cvfString.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QImage>
|
||||
|
||||
namespace cvf {
|
||||
class TextureImage;
|
||||
}
|
||||
|
||||
namespace cvfqt {
|
||||
|
||||
@ -54,6 +59,8 @@ class Utils
|
||||
public:
|
||||
static QString toQString(const cvf::String& ceeString);
|
||||
static cvf::String fromQString(const QString& qtString);
|
||||
|
||||
static void copyFromQImage(cvf::TextureImage* textureImage, const QImage& qtImage);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user