[vtkusers] Fast element access of vtkImageData?

Joseph D. Wieber Jr. jdwieber at gmail.com
Thu Jul 28 10:49:54 EDT 2011


Hi Dominique,

Thanks for the reply, and meaningful example.  I changed my 
implementation to use GetScalarPointer() instead of GetScalarPointer( 
int,int,int), and now it works great.  The final method is below (for 
the next person that reads this thread).

//-----------------------------------------------------------------------------
     //N.B.  The image data object must be correctly set up and scalars 
allocated
     //before calling this method. That is: Allocate the object, set the 
dimensions,
     //set the scalar type, and set the number of components.
     template< typename T >
     void
     fillImageData( vtkSmartPointer< vtkImageData > pImageData, const T& 
val )
     {
         int dims[ 3 ];
         pImageData->GetDimensions ( dims );
         const int numComponents = 
pImageData->GetNumberOfScalarComponents ();
         const int numElements = dims[ 0 ] * dims[ 1 ] * dims[ 2 ] * 
numComponents;
         T* pPixel = static_cast< T* >( pImageData->GetScalarPointer () );
         for( int elemCnt = 0; elemCnt < numElements; ++elemCnt )
         {
             pPixel[ elemCnt ] = val;
         }
     }

Regards,

Joseph

On 07/28/2011 01:46 PM, Dominique Töpfer wrote:
> Hi Joseph,
>
> I use GetScalarPointer to get a pointer to the first element. You then 
> can use simple formulas to pick the desired point and component: If 
> there's only two dimensions and one scalar component the index to the 
> array is y * dim_x + x (or you may use GetScalarPointer(x, y, 1)). If 
> you have four components you have 4*(y*dim_x+x)+i for the i-th 
> component at (x,y). I don't know if there is also a way to get 
> GetScalarPointer(x, y, z) working for more than one scalar component.
>
>   vtkSmartPointer<vtkImageData> pxImage = 
> vtkSmartPointer<vtkImageData>::New();
>   pxImage->SetDimensions(512, 512, 1);
>   pxImage->SetOrigin(0.0, 0.0, 0.0);
>   pxImage->SetSpacing(1.0, 1.0, 1.0);
>   pxImage->SetScalarTypeToUnsignedChar();
>   pxImage->SetNumberOfScalarComponents(4);
>   pxImage->AllocateScalars();
>
>   unsigned char *pxImageData = static_cast<unsigned char 
> *>(pxImage->GetScalarPointer());
>
>   for(unsigned int x = 0; x < 512; x++)
>   {
>       for(unsigned int y = 0; y < 512; y++)
>       {
>          pxImageData[4 * (y * 512 + x) + 0] = x / 2;   // R
>          pxImageData[4 * (y * 512 + x) + 1] = y / 2;   // G
>          pxImageData[4 * (y * 512 + x) + 2] = 128;     // B
>          pxImageData[4 * (y * 512 + x) + 3] = 128;     // A
>       }
>   }
>
>   vtkSmartPointer<vtkBMPWriter> writer = 
> vtkSmartPointer<vtkBMPWriter>::New();
>   writer->SetInput(pxImage);
>   writer->SetFileName("test.bmp");
>   writer->Write();
>
> HTH
> Dominique
>
>
> On 07/28/2011 02:48 AM, Joseph D. Wieber Jr. wrote:
>> Hi Dominique,
>>
>> Thanks for your response.  What should I expect from 
>> GetScalarPointer()?  For example, if I have a vtkImageData object 
>> with four float components (say RGBA), should I expect to be able to 
>> cast the void* to float* and have it point to an array of four 
>> floats?  I modified my template to the below, but it didn't work.  Am 
>> I expecting the wrong return?
>>
>>     //ImageDataPtr is: typedef vtkSmartPointer< vtkImageData > 
>> ImageDataPtr;
>>
>>     template< typename T >
>>     void
>>     fillImageData(  ImageDataPtr pImageData, const T& val )
>>     {
>>         int dims[ 3 ];
>>         pImageData->GetDimensions ( dims );
>>         int& xMax = dims[ 0 ];
>>         int& yMax = dims[ 1 ];
>>         int& zMax = dims[ 2 ];
>>         int numComponents = pImageData->GetNumberOfScalarComponents ();
>>
>>         for( int z = 0; z < zMax; ++z )
>>         {
>>             for ( int y = 0; y < yMax; ++y )
>>             {
>>                 for( int x = 0; x < xMax; ++x )
>>                 {
>>                     T* ptr = static_cast< T* >( 
>> pImageData->GetScalarPointer (x, y, z) );
>>
>>                     for( int c = 0; c < numComponents; ++c )
>>                     {
>>                         *ptr = val;  //*ptr++ = val;
>>                         ++ptr;
>>                     }
>>                 }
>>             }
>>         }
>>     }
>>
>> Thanks again.
>>
>> Regards,
>> Joseph
>>
>>
>> On 07/27/2011 04:22 PM, Dominique Töpfer wrote:
>>> Hi Joseph,
>>>
>>> you could use GetScalarPointer(), which gives you a void * pointer 
>>> to the actual image data. After casting it to the pixel type you are 
>>> using, you can access the array directly, which should be much 
>>> faster. To access a certain point you could use ComputePointID() to 
>>> get the correct index.
>>>
>>> HTH
>>> Dominique
>>>
>>> On 27.07.2011 22:07, Joseph D. Wieber Jr. wrote:
>>>>
>>>> Hello,
>>>>
>>>> Is there a fast way to access (get and set) elements in a 
>>>> vtkImageData object?  For instance I have two image data object 
>>>> with dimensions 512x512x1 that I'm using as part of a cost table 
>>>> (it's convenient) for an algorithm.  One of them gets the output of 
>>>> a convolution filter and I do lookups into it.  The other one has 
>>>> to be initialized to all 1.0 values at the beginning of the 
>>>> algorithm.  Then based on information from the first one, I set 
>>>> values in the second one.  The algorithm is a specialized Laplacian 
>>>> zero crossing.  I've been using the following template to 
>>>> initialize all the values to 1.0:
>>>>
>>>> //----------------------------------------------------------------------------- 
>>>>
>>>> //TODO: This is horribly slow.  Find a smarter way!
>>>>
>>>> template< typename T >
>>>> void
>>>> fillImageData(  ImageDataPtr pImageData, const T& val )
>>>> {
>>>>     int dims[ 3 ];
>>>>     pImageData->GetDimensions ( dims );
>>>>     int& xMax = dims[ 0 ];
>>>>     int& yMax = dims[ 1 ];
>>>>     int& zMax = dims[ 2 ];
>>>>     int numComponents = pImageData->GetNumberOfScalarComponents ();
>>>>
>>>>     for( int z = 0; z < zMax; ++z )
>>>>     {
>>>>         for ( int y = 0; y < yMax; ++y )
>>>>         {
>>>>             for( int x = 0; x < xMax; ++x )
>>>>             {
>>>>                 for( int c = 0; c < numComponents; ++c )
>>>>                 {
>>>>                     pImageData->SetScalarComponentFromFloat ( x, y, 
>>>> z, c, val );
>>>>                 }
>>>>             }
>>>>         }
>>>>     }
>>>> }
>>>>
>>>> To get and set values during the zero crossing computation I've 
>>>> been using combinations of GetScalarComponentAsFloat, and 
>>>> SetScalarComponentFromFloat and this part is also very slow.
>>>>
>>>> Can someone please point me to an example that accomplishes similar 
>>>> tasks in a more efficient manner, or offer a suggestion on where to 
>>>> look?  Thank you.
>>>>
>>>> Regards,
>>>>
>>>> Joseph
>>>>
>>>> _______________________________________________
>>>> Powered by www.kitware.com
>>>>
>>>> Visit other Kitware open-source projects at 
>>>> http://www.kitware.com/opensource/opensource.html
>>>>
>>>> Please keep messages on-topic and check the VTK FAQ at: 
>>>> http://www.vtk.org/Wiki/VTK_FAQ
>>>>
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://www.vtk.org/mailman/listinfo/vtkusers
>>>
>>>
>>>
>
>



More information about the vtkusers mailing list