diff --git a/src/main/java/net/imglib2/display/ARGBARGBColorConverter.java b/src/main/java/net/imglib2/display/ARGBARGBColorConverter.java new file mode 100644 index 000000000..4a8f653d6 --- /dev/null +++ b/src/main/java/net/imglib2/display/ARGBARGBColorConverter.java @@ -0,0 +1,175 @@ +/*- + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package net.imglib2.display; + +import net.imglib2.converter.Converter; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.volatiles.VolatileARGBType; +import net.imglib2.util.Util; + +public abstract class ARGBARGBColorConverter implements ColorConverter, Converter< R, ARGBType > +{ + protected double min = 0; + + protected double max = 1; + + protected final ARGBType color = new ARGBType( ARGBType.rgba( 255, 255, 255, 255 ) ); + + protected int A; + + protected double scaleR; + + protected double scaleG; + + protected double scaleB; + + protected int black = 0; + + public ARGBARGBColorConverter( final double min, final double max ) + { + this.min = min; + this.max = max; + update(); + } + + @Override + public ARGBType getColor() + { + return color.copy(); + } + + @Override + public void setColor( final ARGBType c ) + { + color.set( c ); + update(); + } + + @Override + public boolean supportsColor() + { + return true; + } + + @Override + public double getMin() + { + return min; + } + + @Override + public double getMax() + { + return max; + } + + @Override + public void setMax( final double max ) + { + this.max = max; + update(); + } + + @Override + public void setMin( final double min ) + { + this.min = min; + update(); + } + + private void update() + { + final double scale = 1.0 / ( max - min ); + final int value = color.get(); + A = ARGBType.alpha( value ); + scaleR = ARGBType.red( value ) * scale; + scaleG = ARGBType.green( value ) * scale; + scaleB = ARGBType.blue( value ) * scale; + black = 0; + } + + int convertColor( final int color ) + { + final int a = ARGBType.alpha( color ); + int r = ARGBType.red( color ); + int g = ARGBType.green( color ); + int b = ARGBType.blue( color ); + + final int v = Math.min( 255, Math.max( 0, ( r + g + b ) / 3 ) ); + + final int newR = (int)Math.min( 255, Util.round( scaleR * v )); + final int newG = (int)Math.min( 255, Util.round( scaleG * v )); + final int newB = (int)Math.min( 255, Util.round( scaleB * v )); + + return ARGBType.rgba( newR, newG, newB, a ); + } + + /** + * A converter from a ARGB to ARGB that initially converts the input color to grayscale, + * then scales the resulting grayscale value with the set color. + *

+ * This can be useful if a grayscale image is imported as ARGB and one wants to change + * the hue for visualization / overlay. + * + * @author John Bogovic + * + */ + public static class ToGray extends ARGBARGBColorConverter + { + public ToGray( final double min, final double max ) + { + super( min, max ); + } + + @Override + public void convert( final ARGBType input, final ARGBType output ) + { + output.set( convertColor( input.get() )); + } + } + + public static class VolatileToGray extends ARGBARGBColorConverter + { + public VolatileToGray( final double min, final double max ) + { + super( min, max ); + } + + @Override + public void convert( final VolatileARGBType input, final ARGBType output ) + { + output.set( convertColor( input.get().get() )); + } + } +} diff --git a/src/main/java/net/imglib2/display/ColorConverter.java b/src/main/java/net/imglib2/display/ColorConverter.java new file mode 100644 index 000000000..8dc98853a --- /dev/null +++ b/src/main/java/net/imglib2/display/ColorConverter.java @@ -0,0 +1,51 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package net.imglib2.display; + +import net.imglib2.type.numeric.ARGBType; + +/** + * Allows to set a target color for a {@code Converter}, in addition to min/max + * of the source {@link LinearRange linear range}. + *

+ * (This is used in BigDataViewer to tie converter configuration into the UI.) + */ +public interface ColorConverter extends LinearRange +{ + ARGBType getColor(); + + void setColor( final ARGBType c ); + + boolean supportsColor(); +} diff --git a/src/main/java/net/imglib2/display/RealARGBColorConverter.java b/src/main/java/net/imglib2/display/RealARGBColorConverter.java new file mode 100644 index 000000000..5bbdc9d47 --- /dev/null +++ b/src/main/java/net/imglib2/display/RealARGBColorConverter.java @@ -0,0 +1,60 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package net.imglib2.display; + +import net.imglib2.converter.Converter; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.RealType; + +/** + * A converter {@code RealType} to {@code ARGBType} with configurable {@link + * LinearRange linear range} and {@link ColorConverter color}. + *

+ * Input values are passed through a linear function that maps the configured + * {@link LinearRange linear range} to {@code [0..255]}, the resulting value is + * then multiplied with R, G, B components of the configured {@link + * ColorConverter color} which are finally individually clamped to {@code + * [0..255]}. + * + * @param + * source type + */ +public interface RealARGBColorConverter< R extends RealType< ? > > extends ColorConverter, Converter< R, ARGBType > +{ + static < R extends RealType< ? > > RealARGBColorConverter< R > create( final R type, final double min, final double max ) + { + return RealARGBColorConverterFactory.create( type, min, max ); + } +} + diff --git a/src/main/java/net/imglib2/display/RealARGBColorConverterFactory.java b/src/main/java/net/imglib2/display/RealARGBColorConverterFactory.java new file mode 100644 index 000000000..c7ce98edd --- /dev/null +++ b/src/main/java/net/imglib2/display/RealARGBColorConverterFactory.java @@ -0,0 +1,160 @@ +/*- + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package net.imglib2.display; + +import net.imglib2.loops.ClassCopyProvider; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.RealType; + +class RealARGBColorConverterFactory +{ + @SuppressWarnings( "rawtypes" ) + private static ClassCopyProvider< RealARGBColorConverter > provider; + + @SuppressWarnings( "unchecked" ) + public static < R extends RealType< ? > > RealARGBColorConverter< R > create( final R type, final double min, final double max ) + { + if ( provider == null ) + { + synchronized ( RealARGBColorConverterFactory.class ) + { + if ( provider == null ) + provider = new ClassCopyProvider<>( Imp.class, RealARGBColorConverter.class, double.class, double.class ); + } + } + return provider.newInstanceForKey( type.getClass(), min, max ); + } + + public static class Imp< R extends RealType< ? > > implements RealARGBColorConverter< R > + { + private double min = 0; + + private double max = 1; + + private final ARGBType color = new ARGBType( ARGBType.rgba( 255, 255, 255, 255 ) ); + + private int A; + + private double scaleR; + + private double scaleG; + + private double scaleB; + + private int black; + + public Imp( final double min, final double max ) + { + this.min = min; + this.max = max; + update(); + } + + @Override + public ARGBType getColor() + { + return color.copy(); + } + + @Override + public void setColor( final ARGBType c ) + { + color.set( c ); + update(); + } + + @Override + public boolean supportsColor() + { + return true; + } + + @Override + public double getMin() + { + return min; + } + + @Override + public double getMax() + { + return max; + } + + @Override + public void setMax( final double max ) + { + this.max = max; + update(); + } + + @Override + public void setMin( final double min ) + { + this.min = min; + update(); + } + + private void update() + { + final double scale = 1.0 / ( max - min ); + final int value = color.get(); + A = ARGBType.alpha( value ); + scaleR = ARGBType.red( value ) * scale; + scaleG = ARGBType.green( value ) * scale; + scaleB = ARGBType.blue( value ) * scale; + black = ARGBType.rgba( 0, 0, 0, A ); + } + + @Override + public void convert( final R input, final ARGBType output ) + { + final double v = input.getRealDouble() - min; + if ( v < 0 ) + { + output.set( black ); + } + else + { + final int r0 = ( int ) ( scaleR * v + 0.5 ); + final int g0 = ( int ) ( scaleG * v + 0.5 ); + final int b0 = ( int ) ( scaleB * v + 0.5 ); + final int r = Math.min( 255, r0 ); + final int g = Math.min( 255, g0 ); + final int b = Math.min( 255, b0 ); + output.set( ARGBType.rgba( r, g, b, A ) ); + } + } + } +} diff --git a/src/main/java/net/imglib2/display/ScaledARGBConverter.java b/src/main/java/net/imglib2/display/ScaledARGBConverter.java new file mode 100644 index 000000000..b5394d4a8 --- /dev/null +++ b/src/main/java/net/imglib2/display/ScaledARGBConverter.java @@ -0,0 +1,138 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package net.imglib2.display; + +import net.imglib2.converter.Converter; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.volatiles.VolatileARGBType; + +public abstract class ScaledARGBConverter< T > implements ColorConverter, Converter< T, ARGBType > +{ + protected double min = 0; + + protected double max = 1; + + protected double scale; + + private ScaledARGBConverter( final double min, final double max ) + { + this.min = min; + this.max = max; + update(); + } + + @Override + public double getMin() + { + return min; + } + + @Override + public double getMax() + { + return max; + } + + @Override + public void setMax( final double max ) + { + this.max = max; + update(); + } + + @Override + public void setMin( final double min ) + { + this.min = min; + update(); + } + + @Override + public ARGBType getColor() + { + return new ARGBType(); + } + + @Override + public void setColor( final ARGBType c ) + {} + + @Override + public boolean supportsColor() + { + return false; + } + + private void update() + { + scale = 255.0 / ( max - min ); + } + + int getScaledColor( final int color ) + { + final int a = ARGBType.alpha( color ); + final int r = Math.min( 255, ( int ) ( scale * Math.max( 0, ARGBType.red( color ) - min ) + 0.5 ) ); + final int g = Math.min( 255, ( int ) ( scale * Math.max( 0, ARGBType.green( color ) - min ) + 0.5 ) ); + final int b = Math.min( 255, ( int ) ( scale * Math.max( 0, ARGBType.blue( color ) - min ) + 0.5 ) ); + return ARGBType.rgba( r, g, b, a ); + } + + public static class ARGB extends ScaledARGBConverter< ARGBType > + { + public ARGB( final double min, final double max ) + { + super( min, max ); + } + + @Override + public void convert( final ARGBType input, final ARGBType output ) + { + output.set( getScaledColor( input.get() ) ); + } + } + + public static class VolatileARGB extends ScaledARGBConverter< VolatileARGBType > + { + public VolatileARGB( final double min, final double max ) + { + super( min, max ); + } + + @Override + public void convert( final VolatileARGBType input, final ARGBType output ) + { + output.set( getScaledColor( input.get().get() ) ); + } + } +}