IntensityWindowingImageFilter not working as expected with multiframe instances (JAVA)

i have recorded my problem:

As you can see, weasis is clearly displaying the image with [128, 256] and my software shows everything in white with same configuration.

This is the function that applys the filter:

public static Image applyWCWW (Image image, double wc, double ww) {
        IntensityWindowingImageFilter filter = new IntensityWindowingImageFilter();
        filter.setWindowMinimum(wc - (ww/2));
        filter.setWindowMaximum(wc + (ww/2));
        return filter.execute(image);

This function is working normally for singleframe instances. The only difference between the two types of image is the extraction.

//for singleframe instances
    public static Image axisSlice (Image pixeldata, long[] sliceSize, int[] sliceIndex) {
        VectorUInt32 vectorSize = new VectorUInt32(sliceSize);
        VectorInt32 vectorIndex = new VectorInt32(sliceIndex);
        return SimpleITK.extract(pixeldata, vectorSize, vectorIndex);

    //for multiframe instances
    public static Image axisSlice (Image pixeldata, int index) {
        ExtractImageFilter filter = new ExtractImageFilter();
        filter.setSize(new VectorUInt32(new long[]{pixeldata.getSize().get(0), pixeldata.getSize().get(1), 0, 0}));
        filter.setIndex(new VectorInt32(new int[]{0, 0, index, 0}));
        return filter.execute(pixeldata);

Hello @Salu_Ramos,

If you suspect the issue is with the slice extraction, then save the slice to file (i.e. WriteImage(axis_slice, "slice.nrrd")) and open it with ITK-SNAP. If the image looks like what you expect then the problem is with the display code, if it doesn’t then the problem is with the extraction.


After removing post processing (intensitywindowing), this is the result:

apparently the extraction already has intensitywindowing and I’m applying for the second time?

Hello @Salu_Ramos,

Extraction just does extraction and does not change the image content. If you used ITK-SNAP to view the image, it is doing the window/level operation. This just indicates that the problem is with your intensity-windowing code.

1 Like

itk-snap isn’t opening any multiframe instance:

my extraction image (with no defaultwindowing) is identical to that displayed in other software such as radiant and weasis with default windowing.

When I don’t apply defaultwindowing the extraction appears as expected, and when i apply defaultwindowing it becomes white.

I’ve already made sure it’s not a problem with the display code.

Hi @zivy ,

i implemented a Pixel Value and HU annotation to help me solve this problem.

as you can see:

WindowWidth = 256
WindowCenter/WindowLength = 128
WindowMax = -45.5
WindowMin = 85
Mouse Position HU = 78
Mouse Position Pixel Value = 255

So if HU is 78 and viewing range is between -45 and 85, why is everything white?

I discovered that when: wc*2+ww > 2^bitsAllocated
image becomes full white. Look the video.

the code that applies the filter is this below:

public static Image applyWCWW (Image image, double wc, double ww) {
        IntensityWindowingImageFilter filter = new IntensityWindowingImageFilter();
        ww = Math.max(ww, 0);
        double windowMin = wc - (ww/2);
        double windowMax = wc + (ww/2);
        System.out.println("viewing range (HU): from " + windowMin + " to " + windowMax);
        return filter.execute(image);

Does this give you any idea what could be going on?

Hello @Salu_Ramos,

Likely you are seeing results of overflow. See if converting the following Python code to Java solves the problem:

def applyWCWW (image, wc, ww):
    minmaxFilter = sitk.MinimumMaximumImageFilter()
    # clamp the min, max values based on the user request and image content,
    # the lowest possible value for windowMin is the minimal value in the image
    # the highest possible value for windowMax is the maximal value in the image
    windowMin = max(wc - (ww/2), minmaxFilter.GetMinimum())
    windowMax = min(wc + (ww/2), minmaxFilter.GetMaximum())

    intensityWindowingFilter = sitk.IntensityWindowingImageFilter()
    return intensityWindowingFilter.Execute(image)

Hi @zivy! It is good to see you again.

i managed to fix this today this way:

public static Image applyItkWCWW(Image image, double wc, double ww) {
        IntensityWindowingImageFilter filter = new IntensityWindowingImageFilter();
        double windowMin = wc - (ww/2);
        double windowMax = wc + (ww/2);

        long[] pixelRange = PixelIDValueEnumMap.getPixelIDByName(image.getPixelID()).getPixelRange();
        double windowRangeMin = pixelRange[0];
        double windowRangeMax = pixelRange[1];

        filter.setWindowMinimum(Math.max(windowMin, windowRangeMin));
        filter.setWindowMaximum(Math.min(windowMax, windowRangeMax));
        return filter.execute(image);
public enum PixelIDValueEnumMap {
    Unknown("sitkUnknown", new long[]{-32768, 32767}, (image, vector) -> "unknown"),
    UInt8("sitkUInt8", new long[]{0, 255}, (image, vector) -> String.valueOf(image.getPixelAsUInt8(vector))),
    Int8("sitkInt8", new long[]{-128, 127}, (image, vector) -> String.valueOf(image.getPixelAsInt8(vector))),
    UInt16("sitkUInt16", new long[]{0, 65535}, (image, vector) -> String.valueOf(image.getPixelAsUInt16(vector))),
    Int16("sitkInt16", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsInt16(vector))),
    UInt32("sitkUInt32", new long[]{0, 4_294_967_295L}, (image, vector) -> String.valueOf(image.getPixelAsUInt32(vector))),
    Int32("sitkInt32", new long[]{-2_147_483_648L, 2_147_483_647L}, (image, vector) -> String.valueOf(image.getPixelAsInt32(vector))),
    UInt64("sitkUInt64", new long[]{0, 9_223_372_036_854_775_807L}, (image, vector) -> String.valueOf(image.getPixelAsUInt64(vector))),
    Int64("sitkInt64", new long[]{-9_223_372_036_854_775_807L, 9_223_372_036_854_775_807L}, (image, vector) -> String.valueOf(image.getPixelAsInt64(vector))),
    Float32("sitkFloat32", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsComplexFloat32(vector))),
    Float64("sitkFloat64", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsComplexFloat64(vector))),
    ComplexFloat32("sitkComplexFloat32", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsComplexFloat32(vector))),
    ComplexFloat64("sitkComplexFloat64", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsComplexFloat64(vector))),
    VectorUInt8("sitkVectorUInt8", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorUInt8(vector))),
    VectorInt8("sitkVectorInt8", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorInt8(vector))),
    VectorUInt16("sitkVectorUInt16", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorUInt16(vector))),
    VectorInt16("sitkVectorInt16", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorInt16(vector))),
    VectorUInt32("sitkVectorUInt32", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorUInt32(vector))),
    VectorInt32("sitkVectorInt32", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorInt32(vector))),
    VectorUInt64("sitkVectorUInt64", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorUInt64(vector))),
    VectorInt64("sitkVectorInt64", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorInt64(vector))),
    VectorFloat32("sitkVectorFloat32", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorFloat32(vector))),
    VectorFloat64("sitkVectorFloat64", new long[]{-32768, 32767}, (image, vector) -> String.valueOf(image.getPixelAsVectorFloat64(vector))),
    LabelUInt8("sitkLabelUInt8", new long[]{-32768, 32767}, (image, vector) -> "LabelUInt8"),
    LabelUInt16("sitkLabelUInt16", new long[]{-32768, 32767}, (image, vector) -> "LabelUInt16"),
    LabelUInt32("sitkLabelUInt32", new long[]{-32768, 32767}, (image, vector) -> "LabelUInt32"),
    LabelUInt64("sitkLabelUInt64", new long[]{-32768, 32767}, (image, vector) -> "LabelUInt64");

    @Getter private final String name;
    @Getter private final long[] pixelRange;
    @Getter private final GetPixel getPixelLambda;

    PixelIDValueEnumMap(String name, long[] pixelRange, GetPixel getPixelLambda) { = name;
        this.pixelRange = pixelRange;
        this.getPixelLambda = getPixelLambda;

    public static PixelIDValueEnumMap getPixelIDByName (PixelIDValueEnum pixelID) {
        String pixelIDString = pixelID.toString();
        for (PixelIDValueEnumMap pixelIDMap : PixelIDValueEnumMap.values()) {
            if ( {
                return pixelIDMap;
        return PixelIDValueEnumMap.Unknown;


After I solved it I saw your answer, it’s basically your way but done manually lol.