[vtkusers] Fast element access of vtkImageData?

Dominique Töpfer dominique at toepfer-web.de
Thu Jul 28 13:46:25 EDT 2011


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