[vtkusers] Changing level/window in LUT for ImageSlice: Unwanted clipping effects

David Gobbi david.gobbi at gmail.com
Thu Feb 2 19:24:04 EST 2017


Hi Sophonet,

I've created a bug report that includes a test program:
https://gitlab.kitware.com/vtk/vtk/issues/16966

The program shows the difference between calling SetTableValue() for each
color (which seems to work fine), versus calling SetTable() with a
vtkUnsignedCharArray (which results in the undesired transparency).

 - David


On Thu, Feb 2, 2017 at 3:56 PM, Sophonet <vtk12af6bc42 at kant.sophonet.de>
wrote:

> David, do you have a test program / test code that works on your end
> (preferrably with an external array similar to my setup)? I could try here
> and further trace down the problem I have. Python code would be fine as
> well.
>
> Thanks,
>
>    Sophonet
>
>
>
> Am 2017-02-02 20:12, schrieb David Gobbi:
>
>> Hi Sophonet,
>>
>> This code looks very fishy to me:
>>
>> colorMap_->GetTableValue(255, aboveColor);
>>
>> colorMap_->GetTableValue(0, belowColor);
>>
>> You shouldn't call GetTableValue() before you have built the table.
>> If you haven't built the table, how do you know what colors are stored
>> at positions 0 and 255?  They could be (0,0,0,0).
>>
>>  - David
>>
>> On Thu, Feb 2, 2017 at 11:51 AM, Sophonet
>> <vtk12af6bc42 at kant.sophonet.de> wrote:
>>
>> Hi David,
>>>
>>> here it is (needed to copy a few lines since the functionality is
>>> part of a class). Note that it contains your work-around twice,
>>> once, when setting an external colormap, and the second time when
>>> changing window/level.
>>>
>>> Oh, after pasting, it came into my mind that using an external
>>> color table might be the reason? In this case, I recall, Build() is
>>> not really needed anyway...
>>>
>>> Hope this helps. Thanks for looking into this so quickly,
>>>
>>>      Sophonet
>>>
>>> // Initialization
>>> vtkSmartPointer<vtkLookupTable> colorMap_ =
>>> vtkSmartPointer<vtkLookupTable>::New();
>>> vtkSmartPointer<vtkImageProperty> imageProperty_ =
>>> vtkSmartPointer<vtkImageProperty>::New();
>>> colorMap_->SetNumberOfTableValues(256);
>>> colorMap_->SetRange(0, 1);
>>>
>>> imageProperty_->SetLookupTable(colorMap_);
>>> imageProperty_->UseLookupTableScalarRangeOn();
>>>
>>> imageSlice_->SetProperty(imageProperty_);
>>>
>>> // Setting color map from external RGBA array
>>> colorMap_->SetTable(colorArray); // please see below how I have set
>>> up the array...
>>> double aboveColor[4];
>>> double belowColor[4];
>>> colorMap_->GetTableValue(255, aboveColor);
>>> colorMap_->SetAboveRangeColor(aboveColor);
>>> colorMap_->UseAboveRangeColorOn();
>>> colorMap_->GetTableValue(0, belowColor);
>>> colorMap_->SetBelowRangeColor(belowColor);
>>> colorMap_->UseBelowRangeColorOn();
>>> colorMap_->SetNumberOfTableValues(256);
>>> colorMap_->Build();
>>>
>>> // Callback for level / window
>>> double minmax[2];
>>> minmax[0] = windowLevel_[1] - 0.5*windowLevel_[0];
>>> minmax[1] = windowLevel_[1] + 0.5*windowLevel_[0];
>>> colorMap_->SetRange(minmax);
>>> double aboveColor[4];
>>> double belowColor[4];
>>> colorMap_->GetTableValue(255, aboveColor);
>>> colorMap_->SetAboveRangeColor(aboveColor);
>>> colorMap_->UseAboveRangeColorOn();
>>> colorMap_->GetTableValue(0, belowColor);
>>> colorMap_->SetBelowRangeColor(belowColor);
>>> colorMap_->UseBelowRangeColorOn();
>>> colorMap_->SetNumberOfTableValues(256);
>>> colorMap_->Build();
>>>
>>> //////////////////////////////////////
>>> const unsigned char grayscale[4*256] = {
>>> 0, 0, 0, 255, 1, 1, 1, 255,
>>> // you can imagine how things continue. I have other more useful
>>> arrays for other color scales as well
>>> // ...
>>> };
>>>
>>> vtkSmartPointer<vtkUnsignedCharArray> colorArray =
>>> vtkSmartPointer<vtkUnsignedCharArray>::New();
>>> newMap->SetNumberOfValues(256);
>>> newMap->SetNumberOfComponents(4);
>>> newMap->SetArray(const_cast<unsigned char *>(grayscale), 4 * 256,
>>> 1);
>>>
>>> Am 2017-02-02 18:51, schrieb David Gobbi:
>>> Hi Sophonet,
>>>
>>> Can you send the exact code that you use to set up the lookup
>>> table,
>>> including the call to Build(), so that I can check locally?
>>>
>>>  - David
>>>
>>> On Thu, Feb 2, 2017 at 10:42 AM, Sophonet
>>> <vtk12af6bc42 at kant.sophonet.de> wrote:
>>>
>>> Well, on my system your proposed change did not work, I still see
>>> transparent color when LUT clipping occurs, exactly as before. I
>>> have even copied your lines of your previous posting plus the
>>> Build() call below the SetRange() callback, in which I am doing
>>> level/windowing. Not sure why though - I might check again using
>>> the
>>> HEAD (I am on 7.1.0 release)
>>>
>>> - Sophonet
>>>
>>> Am 2017-02-02 18:08, schrieb David Gobbi:
>>> Okay, here is a very simple work-around for this issue: Just call
>>> Build() on the table after you have set all the other table
>>> parameters.  Please let me know if this fixes the issue.
>>>
>>> I've submitted a fix for mapper so that it will call Build()
>>> automatically.  I'm not sure why it didn't do this before.
>>>
>>>  - David
>>>
>>> On Thu, Feb 2, 2017 at 8:41 AM, David Gobbi <david.gobbi at gmail.com>
>>> wrote:
>>>
>>> I've discovered more about this issue.  The Above/Below colors
>>> will
>>> work if you call SetNumberOfColors after turning them on:
>>>
>>> table->SetBelowRangeColor(1,0,0,1);
>>> table->SetAboveRangeColor(0,1,0,1);
>>> table->UseAboveRangeColorOn();
>>> table->UseBelowRangeColorOn();
>>> table->SetNumberOfColors(256);
>>>
>>> I'm still investigating to see why this happens.
>>>
>>>  - David
>>>
>>> On Thu, Feb 2, 2017 at 7:20 AM, David Gobbi <david.gobbi at gmail.com>
>>> wrote:
>>>
>>> Hi Sophonet,
>>>
>>> I have confirmed that what you report is true: the
>>> vtkImageResliceMapper (and vtkImageSliceMapper) seem to ignore the
>>> AboveRangeColor and the BelowRangeColor.  This is also true for
>>> the
>>> current VTK master branch.  My current theory is that the mapper
>>> clamps the scalars to the range before they go through the lookup
>>> table.  Hopefully I'll have a fix for this soon.
>>>
>>> As a workaround (a inefficient workaround), you can use
>>> vtkImageMapToColors to apply the lookup table to the image before
>>> it
>>> goes to the mapper.
>>>
>>>  - David
>>>
>>>
>>> On Thu, Feb 2, 2017 at 5:10 AM, Sophonet
>>> <vtk12af6bc42 at kant.sophonet.de> wrote:
>>> Dear list,
>>>
>>> for displaying images, I am using vtkImageResliceMapper. For
>>> changing the colormap, I set a dedicated color map to the
>>> imageSlice's property (which is a vtkLookupTable) and tell to use
>>> its scalar range:
>>>
>>> colorMap_->SetNumberOfTableValues(256);
>>> colorMap_->SetRange(0, 1);
>>>
>>> imageProperty_->SetLookupTable(colorMap_);
>>> imageProperty_->UseLookupTableScalarRangeOn();
>>>
>>> Now, when changing level/window interactively with the mouse, I am
>>> setting the range in the colorMap via
>>>
>>> double minmax[2];
>>> // set values of minmax correctly
>>> colorMap_->SetRange(minmax);
>>>
>>> The changes are displayed correctly - however, areas in which
>>> original scalars of the image are clipped, the resulting color is
>>> displayed as transparent. However, I would like to display the
>>> maximum / minimum value in the color table.
>>>
>>> I have tried using colorMap_->SetAboveRangeColor() and
>>> colorMap_->SetAboveRangeColorOn() (likewise for ...BelowRange...),
>>> with no apparent effect.
>>>
>>> Any advice?
>>>
>>> I am using VTK 7.1.0.
>>>
>>> Thanks,
>>>
>>>      Sophonet
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20170202/e774b148/attachment.html>


More information about the vtkusers mailing list