[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