[vtkusers] Fast conversion from vtkImageData to QImage?

Prashanth Udupa prashanth.udupa at gmail.com
Fri Jan 29 09:30:55 EST 2010


Thanks Michael, John and Jeff for the really useful tips :-)


Based on the inputs, first I wrote a simple Qt/C++ profiler class.

#include <QTime>

class FunctionProfiler
{
public:
    FunctionProfiler(const QString& func) {
        m_function = QMetaObject::normalizedSignature( qPrintable(func) );
        m_function = m_function.remove("__thiscall");
        m_function = m_function.remove("__stdcall");
        m_function = m_function.remove("__cdecl");

        m_startTime = QTime::currentTime();
    }

    ~FunctionProfiler() {
        qint32 msecs = m_startTime.msecsTo( QTime::currentTime() );
        qDebug("PROFILE: (%5d) %s", msecs, qPrintable(m_function));
    }

private:
    QString m_function;
    QTime m_startTime;
};

#define PROFILE_THIS_FUNCTION FunctionProfiler functionProfiler(Q_FUNC_INFO);

Now, I can just insert the PROFILE_THIS_FUNCTION macro on the first
line of any function to get atleast an approximate idea of the time
spent in the createQImage() function.

Initially the createQImage() function [based on code from my previous
email] was taking as much as 48 milliseconds for a 512 x 512 image.
Now it takes 4-6 milliseconds (as shown by the qDebug() output below)

PROFILE: (    5) class QImage
RadGUI::VTKImageGraphicsViewData::createQImage(int,int,vtkUnsignedCharArray*)const

Jeff Baumes: Thanks for the tip. I did take a look at
vtkQImageToImageSource::RequestData() implementation. For me, the
pointer math was a little difficult to get. But I am sure
reverse-implementing the function could possibly make the conversion
from vtkImageData to QImage still faster. I will give it a try in the
coming days.

-----------------------------------
// This is the code that I am currently using

QImage createQImage(vtkImageData* imageData)
{
    PROFILE_THIS_FUNCTION;

    if(!imageData)
        return QImage();

    int width = imageData->GetDimensions()[0];
    int height = imageData->GetDimensions()[1];
    vtkUnsignedCharArray* scalars =
        vtkUnsignedCharArray::SafeDownCast(imageData->GetPointData()->GetScalars());

    if(!width || !height || !scalars)
        return QImage();

    switch(scalars->GetNumberOfComponents())
    {
    case 1:
        return createQImage1(width, height, scalars);
    case 2:
        return createQImage2(width, height, scalars);
    case 3:
        return createQImage3(width, height, scalars);
    case 4:
        return createQImage4(width, height, scalars);
    }

    return QImage();
}

QImage createQImage1(int width, int height, vtkUnsignedCharArray* scalars)
{
    QImage qImage(width, height, QImage::Format_ARGB32);
    vtkIdType tupleIndex=0;
    int qImageBitIndex=0;

    QRgb* qImageBits = (QRgb*)qImage.bits();
    unsigned char* scalarTuples = scalars->GetPointer(0);

    for(int j=0; j<height; j++)
    {
        for(int i=0; i<width; i++)
        {
            unsigned char* tuple = scalarTuples+(tupleIndex++);

            QRgb color = qRgba(tuple[0], tuple[0], tuple[0], 255);
            *(qImageBits+(qImageBitIndex++))=color;
        }
    }

    return qImage;
}

QImage createQImage2(int width, int height, vtkUnsignedCharArray* scalars)
{
    QImage qImage(width, height, QImage::Format_ARGB32);
    vtkIdType tupleIndex=0;
    int qImageBitIndex=0;

    QRgb* qImageBits = (QRgb*)qImage.bits();
    unsigned char* scalarTuples = scalars->GetPointer(0);

    for(int j=0; j<height; j++)
    {
        for(int i=0; i<width; i++)
        {
            unsigned char* tuple = scalarTuples+(tupleIndex++*2);

            QRgb color = qRgba(tuple[0], tuple[0], tuple[0], tuple[1]);
            *(qImageBits+(qImageBitIndex++))=color;
        }
    }

    return qImage;
}

QImage createQImage3(int width, int height, vtkUnsignedCharArray* scalars)
{
    QImage qImage(width, height, QImage::Format_ARGB32);
    vtkIdType tupleIndex=0;
    int qImageBitIndex=0;

    QRgb* qImageBits = (QRgb*)qImage.bits();
    unsigned char* scalarTuples = scalars->GetPointer(0);

    for(int j=0; j<height; j++)
    {
        for(int i=0; i<width; i++)
        {
            unsigned char* tuple = scalarTuples+(tupleIndex++*3);

            QRgb color = qRgba(tuple[0], tuple[1], tuple[2], 255);
            *(qImageBits+(qImageBitIndex++))=color;
        }
    }

    return qImage;
}

QImage createQImage4(int width, int height, vtkUnsignedCharArray* scalars)
{
    QImage qImage(width, height, QImage::Format_ARGB32);
    vtkIdType tupleIndex=0;
    int qImageBitIndex=0;

    QRgb* qImageBits = (QRgb*)qImage.bits();
    unsigned char* scalarTuples = scalars->GetPointer(0);

    for(int j=0; j<height; j++)
    {
        for(int i=0; i<width; i++)
        {
            unsigned char* tuple = scalarTuples+(tupleIndex++*4);

            QRgb color = qRgba(tuple[0], tuple[1], tuple[2], tuple[3]);
            *(qImageBits+(qImageBitIndex++))=color;
        }
    }

    return qImage;
}
-----------------------------------

Thanks and Regards,
Prashanth



More information about the vtkusers mailing list