imagej / imagej-common

ImageJ core data model
https://imagej.net/libs/imagej-common
BSD 2-Clause "Simplified" License
10 stars 18 forks source link

Fix ColorTable index computation #99

Closed tpietzsch closed 3 years ago

tpietzsch commented 3 years ago

The buggy version probably slipped in because it "accidentally works" if either

imagejan commented 3 years ago

@tpietzsch can you provide a short recipe how to test this (the buggy behavior as well as the fix)?

tpietzsch commented 3 years ago

Here is an example that sets up a 100x100x20x3 (X,Y,Z,C) Dataset with every plane in the first channel having a red ramp color table, every plane in the second channel green, and every plane in the third channel blue.

public static void main( final String[] args )
{
    final ImageJ ij = new ImageJ();
    ij.ui().showUI();

    final int width = 100;
    final int height = 100;
    final int depth = 20;
    final int numChannels = 3;

    final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes(
            width, height, depth, numChannels );
    img.forEach( t -> t.set( 255 ) );
    final ImgPlus< UnsignedByteType > imp = new ImgPlus<>( img, "bug",
            new AxisType[] { Axes.X, Axes.Y, Axes.Z, Axes.CHANNEL } );

    final byte[] zeros = new byte[ 256 ];
    final byte[] ramp = new byte[ 256 ];
    for ( int i = 0; i < 256; ++i )
        ramp[ i ] = ( byte ) i;
    final ColorTable8 reds = new ColorTable8( ramp, zeros, zeros );
    final ColorTable8 greens = new ColorTable8( zeros, ramp, zeros );
    final ColorTable8 blues = new ColorTable8( zeros, zeros, ramp );
    final ColorTable8[] channelColorTables = new ColorTable8[] { reds, greens, blues };

    final int numPlanes = depth * numChannels;
    imp.initializeColorTables( numPlanes );
    for ( int c = 0; c < numChannels; ++c )
        for ( int z = 0; z < depth; ++z )
            imp.setColorTable( channelColorTables[ c ], c * depth + z );

    final Dataset dataset = ij.dataset().create( imp );
    dataset.setRGBMerged( false );
    ij.ui().show( dataset );
}

Running it with the current imagej-common, third channel is displayed as green

Screenshot 2021-06-29 at 13 03 53Screenshot 2021-06-29 at 13 04 04Screenshot 2021-06-29 at 13 04 06

Running it with this PR, third channel is blue, as expected.

Screenshot 2021-06-29 at 13 02 45Screenshot 2021-06-29 at 13 02 48Screenshot 2021-06-29 at 13 02 51

Of course, the example kind of hinges on trusting me that I got the plane index math right in

imp.setColorTable( channelColorTables[ c ], c * depth + z );