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:
Magne Sjaastad 2013-09-30 13:17:05 +02:00
parent a5a1dfe701
commit 15eab9b261
3 changed files with 82 additions and 22 deletions

View File

@ -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()));
}

View File

@ -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);
}
}
}
}

View File

@ -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);
};
}