[vtkusers] Fast element access of vtkImageData?

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


Just for completeness, the code comment below should end with "and call 
AllocateScallars".

On 07/28/2011 10:49 AM, Joseph D. Wieber Jr. wrote:
> 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