# extract image slice from vtkImageData and convert it to qimage, which make unexpected result

**URL:** https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623
**Category:** Support
**Created:** [January 12, 2022, 9:19am UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623 "2022-01-12T09:19:30Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![xianger.qi](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/x/f14d63/32.png) [@xianger.qi](https://discourse.vtk.org/u/xianger.qi)
#### Post date: [January 12, 2022, 9:19am UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/1 "2022-01-12T09:19:30Z")

</div>

Hello guys:  
I extract a slice from vtkImageData with vtkImageReslice filter, then display the output of vtkImageReslice in renderwindow, meanwhile i convert the output of vtkImageReslice to qimage. BUT The result of qimage is different with picture displayed in renderwindow. PICTURE BELOW:

vtkimage displayed in renderwindow

 ![vtkimage](https://discourse.vtk.org/uploads/default/original/2X/e/ea501a62f2f27b16d0a1e57cdb977f43a42146cf.png)

qimage:  
[test.bmp](https://discourse.vtk.org/uploads/short-url/eduux0LSHrgInQSRxh8Mmg6m1B3.bmp) (656.1 KB)

reslice matrix:  
0.989176 0.0549455 0.136054 258.621  
0.133589 0.0463236 0.989954 138.063  
0.0606961 0.997414 0.0384822 521.809  
0 0 0 1

function converting vtkimage to qimage:  
QImage convert\_vtkimagedata\_to\_qimage(vtkImageData \*raw, float scalar\_min, float scalar\_max, double \*spacing)  
{  
int x\_dims = \*raw-\>GetDimensions();  
int y\_dims = \*(raw-\>GetDimensions()+1);  
int z\_dims = \*(raw-\>GetDimensions()+2);

```
double spacing_x = spacing[0];
double spacing_y = spacing[1];
double spacing_z = spacing[2];

int scale_y = x_dims * spacing_x;
int scale_z = y_dims * spacing_z;

float scalar_range = scalar_max - scalar_min;

QImage img(x_dims, y_dims, QImage::Format_Grayscale8);

for(int i = 0; i < y_dims; ++i)
{
    for(int j = 0; j < x_dims; ++j)
    {
        float val = raw->GetScalarComponentAsFloat(j, i, 0, 0);
        int res = (int)(((val - scalar_min) / scalar_range) * 255.0);
        uchar *p = img.bits() + (i * x_dims + j);
        *p = res;
    }
}
QImage image_scaled = img.scaled(scale_y, scale_z);
img.save("/home/xianger/Pictures/test.bmp");
return image_scaled;

```

}

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [January 12, 2022, 7:57pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/2 "2022-01-12T19:57:12Z")

</div>

Hello,

It seems to me that the number of pixels widthwise should be greater and the scan order is upside down. I’d rewrite your scanning loop with something like this (redim arrays as needed):

```cpp
for(int i = 0; i < y_dims; ++i)
{
    for(int j = 0; j < x_dims-1; ++j) //dimension widthwise should ensure correct vertical alignment
    {
        float val = raw->GetScalarComponentAsFloat(j, i, 0, 0);
        int res = (int)(((val - scalar_min) / scalar_range) * 255.0);
        uchar *p = img.bits() + ( (y_dims-1-i) * x_dims + j); //vertical scan order seems to differ between Qt and VTK
        *p = res;
    }
}

```

I hope this helps,

Paulo

---

<div class="post-metadata">

### Author: ![xianger.qi](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/x/f14d63/32.png) [@xianger.qi](https://discourse.vtk.org/u/xianger.qi)
#### Post date: [January 13, 2022, 3:04am UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/3 "2022-01-13T03:04:30Z")

</div>

Thanks a lot, I have try the code supplied by you, and THANKFULLY that was worked!  
but i wonder why the x\_dims should minus one? could you tell me the reason? THANKS!

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [January 13, 2022, 2:04pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/4 "2022-01-13T14:04:23Z")

</div>

It’s because the dimensions of `vtkImageData` referes to its _vertices_ (mesh corners) and not its _cells_. So, to accomodate a 10x10x10 data array, you have to crate an 11x11x11 `vtkImageData`.

Here’s how I create my `vtkImageData`:

```cpp
    //create a volumetric object (regular 3D grid)
    vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
    imageData->SetSpacing( dX, dY, dZ );
    imageData->SetOrigin( X0frame, Y0frame, Z0frame );
    imageData->SetDimensions( nX+1, nY+1, nZ+1 ); 

```

Then, how I populate it with values for rendering (notice how I allocate the `values` array with one dimension less for each axis):

```cpp
    //read sample values
    values->Allocate( nX*nY*nZ );
    for( int k = 0; k < nZ; ++k){
        for( int j = 0; j < nY; ++j){
            for( int i = 0; i < nX; ++i){
                // sample value
                double value = cartesianGrid->getDataValueIJK( variable_index, i, j, k );
                values->InsertNextValue( value );
            }
        }
    }

    //assign the grid values to the volume cells
    imageData->GetCellData()->SetScalars( values );

```

Edit: It’s most likely you need to use `y_dims-1` too. I wonder why you don’t get a crash.

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [January 13, 2022, 2:05pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/5 "2022-01-13T14:05:13Z")

</div>

Conversely, when you extract an orthoslice, you get an 11x11 grid.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [January 13, 2022, 3:25pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/6 "2022-01-13T15:25:29Z")

</div>

Hi Paulo,

You are assuming that the scalars are associated with the cells:

> [@Paulo\_Carvalho](#):
>
> ` imageData->GetCellData()->SetScalars( values );`

For the original question, however, I am 99% certain that the scalars are associated with the points. Hence, the `-1` is not needed. It should loop like this:

```auto
    for(int j = 0; j < x_dims; ++j)

```

---

<div class="post-metadata">

### Author: ![xianger.qi](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/x/f14d63/32.png) [@xianger.qi](https://discourse.vtk.org/u/xianger.qi)
#### Post date: [January 13, 2022, 3:37pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/7 "2022-01-13T15:37:50Z")

</div>

yes, the scalars are associated with the points. the vtkimagedata is structed point which is from ct data. for mine application, i change the function which convert vtkimagedata to qimage and i get the correct result finally. But i can’t explain the reason for that, could you tell me? thanks a lot!

the function below:  
QImage convert\_vtkimagedata\_to\_qimage(vtkImageData \*raw, float scalar\_min, float scalar\_max, double \*spacing)  
{  
int width = \*raw-\>GetDimensions();  
int height = \*(raw-\>GetDimensions()+1);

```
double spacing_x = spacing[0];
double spacing_y = spacing[1];
double spacing_z = spacing[2];

int scale_width = width * spacing_y;
int scale_height = height * spacing_y;

float scalar_range = scalar_max - scalar_min;

vtkShortArray* scalars =
        vtkShortArray::SafeDownCast(raw->GetPointData()->GetScalars());

QImage qImage(width, height, QImage::Format_ARGB32);
vtkIdType tupleIndex=0;
int qImageBitIndex=0;

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

for(int j=0; j<height; j++)
{
    for(int i=0; i<width; i++)
    {
        short* tuple = scalarTuples+(tupleIndex++);
        int v = ((*tuple - scalar_min) / scalar_range ) *255.0;
        QRgb color = qRgba(v, v, v, 255);
        *(qImageBits+(qImageBitIndex++))=color;
    }
}

```

// qImage = qImage.mirrored(false, true);  
qImage = qImage.scaled(scale\_width, scale\_height);  
// qImage.save("/home/xianger/Pictures/asdq.bmp");

```
return qImage;

```

}

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [January 13, 2022, 4:29pm UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/8 "2022-01-13T16:29:26Z")

</div>

> [@xianger.qi](#):
>
> But i can’t explain the reason for that, could you tell me?

The main difference seems to be this:

```c++
    float val = raw->GetScalarComponentAsFloat(j, i, 0, 0);

```

The index for images does not always begin at zero. It begins at the start of the extent, and if the start of the extent is not zero, then an offset is needed:

```auto
int* extent = raw->GetExtent();
int x_min = extent[0];
int x_max = extent[1];
int y_min = extent[2];
int y_max = extent[3];
for(int i = y_min; i <= y_max; ++i)
{
    for(int j = x_min; j <= x_max; ++j)
    {
        float val = raw->GetScalarComponentAsFloat(j, i, 0, 0);
        int res = (int)(((val - scalar_min) / scalar_range) * 255.0);
        uchar *p = img.bits() + ((i - y_min) * x_dims + (j - x_min));
        *p = res;
    }
}

```

In this code vtkImageData index starts at `x_start` and the QImage index starts at `0`.

* * *

Edit: Ugh! I had to fix my example code. I had an off-by-one error on the extent. Sigh…  
The code is fixed now… maybe…

* * *

Edit: I actually think your new code is better than my example. The only change I recommend is this, so that you do not need to `SafeDownCast()` the scalars:

```diff
- short* tuple = scalarTuples+(tupleIndex++);
- int v = ((*tuple - scalar_min) / scalar_range ) *255.0;
+ double scalar_val = scalars->GetComponent(tupleIndex++, 0);
+ int v = ((scalar_val - scalar_min) / scalar_range ) * 255.0;

```

I don’t like to use `GetScalarComponentAsFloat()` because it is a very inefficient function.

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [January 14, 2022, 4:53am UTC](https://discourse.vtk.org/t/extract-image-slice-from-vtkimagedata-and-convert-it-to-qimage-which-make-unexpected-result/7623/9 "2022-01-14T04:53:26Z")

</div>

We use the vtkImageDataToQImage implementation in CTK.

> <https://github.com/commontk/CTK/blob/4839f18fb7cf1486b0f16e88f031137ce15ff550/Libs/Visualization/VTK/Widgets/ctkVTKWidgetsUtils.cpp#L89-L130>

CTK has lots of other useful tools for implementing medical imaging applications (DICOM browser, slice and 3D viewer widgets, volume rendering transfer function editor, and many other widgets), and you can save even more time by building your application on higher-level VTK-based frameworks, such as 3D Slicer or MITK.
