From 3ecd816edd5b08c8864dac2736c6bfb1d06e6c2a Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Tue, 5 Aug 2025 15:44:04 -0500 Subject: [PATCH 1/2] Add utilities for converting LUTs to ColorTables --- .../net/imglib2/imagej/LUTToColorTable.java | 57 +++++++++++++++++++ .../imglib2/imagej/LUTToColorTableTest.java | 39 +++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/net/imglib2/imagej/LUTToColorTable.java create mode 100644 src/test/java/net/imglib2/imagej/LUTToColorTableTest.java diff --git a/src/main/java/net/imglib2/imagej/LUTToColorTable.java b/src/main/java/net/imglib2/imagej/LUTToColorTable.java new file mode 100644 index 0000000..9280a4e --- /dev/null +++ b/src/main/java/net/imglib2/imagej/LUTToColorTable.java @@ -0,0 +1,57 @@ +package net.imglib2.imagej; + +import ij.process.LUT; +import net.imglib2.util.Binning; +import net.imglib2.display.ColorTable; + +import java.awt.*; + +/** + * Provides convenience functions to wrap ImageJ {@link ij.process.LUT} objects into ImgLib2 + * {@link net.imglib2.display.ColorTable}s. + * + * + * @author Stephan Preibisch + * @author Stephan Saalfeld + * @author Matthias Arzt + * @author Gabriel Selzer + */ +public class LUTToColorTable { + + public static ColorTable wrap(final LUT lut) { + return new ColorTable() { + @Override + public int lookupARGB(double min, double max, double value) { + final int bins = getLength(); + final int bin = Binning.valueToBin( bins, min, max, value ); + return lut.getRGB( bin ); + } + + @Override + public int getComponentCount() { + return 4; + } + + @Override + public int getLength() { + return 256; + } + + @Override + public int get(int comp, int bin) { + int rgb = lut.getRGB(bin); + int shift = comp == ColorTable.RED ? 16 : + comp == ColorTable.GREEN ? 8 : + comp == ColorTable.BLUE ? 0 : + 24; + return (rgb >> shift) & 0xff; + } + + @Override + public int getResampled(int comp, int bins, int bin) { + final int newBin = ( int ) ( ( long ) getLength() * bin / bins ); + return get( comp, newBin ); + } + }; + } +} diff --git a/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java b/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java new file mode 100644 index 0000000..e062885 --- /dev/null +++ b/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java @@ -0,0 +1,39 @@ +package net.imglib2.imagej; + +import ij.process.LUT; +import net.imglib2.display.ColorTable; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.assertEquals; + +/** + * Tests utilities in {@link LUTToColorTable} + * + * @author Gabriel Selzer + */ +public class LUTToColorTableTest { + + @Test + public void testWrapLUT() { + Random r = new Random(0xdeadbeefL); + byte[] reds = new byte[256]; + r.nextBytes(reds); + byte[] blues = new byte[256]; + r.nextBytes(blues); + byte[] greens = new byte[256]; + r.nextBytes(greens); + LUT lut = new LUT(reds, greens, blues); + ColorTable actual = LUTToColorTable.wrap(lut); + assertEquals(256, actual.getLength()); + assertEquals(4, actual.getComponentCount()); + for(int i = 0; i < actual.getLength(); i++) { + // Note ColorTable.get unsigned bytes as ints + assertEquals(reds[i], (byte) actual.get(ColorTable.RED, i)); + assertEquals(greens[i], (byte) actual.get(ColorTable.GREEN, i)); + assertEquals(blues[i], (byte) actual.get(ColorTable.BLUE, i)); + assertEquals((byte) 255, (byte) actual.get(ColorTable.ALPHA, i)); + } + } +} From 08bb380d64f0fe5b218dd0072aec40223f5c0866 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Tue, 5 Aug 2025 17:39:00 -0500 Subject: [PATCH 2/2] Add utilities for converting Color Tables to LUTs --- .../net/imglib2/imagej/ColorTableToLUT.java | 30 +++++++++++++++++ .../net/imglib2/imagej/LUTToColorTable.java | 8 +++-- .../imglib2/imagej/ColorTableToLUTTest.java | 33 +++++++++++++++++++ .../imglib2/imagej/LUTToColorTableTest.java | 4 +-- 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/imglib2/imagej/ColorTableToLUT.java create mode 100644 src/test/java/net/imglib2/imagej/ColorTableToLUTTest.java diff --git a/src/main/java/net/imglib2/imagej/ColorTableToLUT.java b/src/main/java/net/imglib2/imagej/ColorTableToLUT.java new file mode 100644 index 0000000..f0dcdf3 --- /dev/null +++ b/src/main/java/net/imglib2/imagej/ColorTableToLUT.java @@ -0,0 +1,30 @@ +package net.imglib2.imagej; + +import ij.process.LUT; +import net.imglib2.display.ColorTable; +import net.imglib2.util.Binning; + +/** + * Provides convenience functions to convert ImgLib2 {@link ColorTable}s into + * ImageJ {@link LUT} objects. + * + * + * @author Gabriel Selzer + */ +public class ColorTableToLUT { + + /** + * Copies the data from {@code table} into a new {@link LUT} + * @param table the {@link ColorTable} to convert + * @return a {@link LUT} containing the same color mapping as {@code table} + */ + public static LUT convert(final ColorTable table) { + byte[][] data = new byte[3][256]; + for (int bin = 0; bin < 256; bin++) { + data[ColorTable.RED][bin] = (byte) table.get(ColorTable.RED, bin); + data[ColorTable.GREEN][bin] = (byte) table.get(ColorTable.GREEN, bin); + data[ColorTable.BLUE][bin] = (byte) table.get(ColorTable.BLUE, bin); + } + return new LUT(data[ColorTable.RED], data[ColorTable.GREEN], data[ColorTable.BLUE]); + } +} diff --git a/src/main/java/net/imglib2/imagej/LUTToColorTable.java b/src/main/java/net/imglib2/imagej/LUTToColorTable.java index 9280a4e..121cce6 100644 --- a/src/main/java/net/imglib2/imagej/LUTToColorTable.java +++ b/src/main/java/net/imglib2/imagej/LUTToColorTable.java @@ -11,13 +11,15 @@ * {@link net.imglib2.display.ColorTable}s. * * - * @author Stephan Preibisch - * @author Stephan Saalfeld - * @author Matthias Arzt * @author Gabriel Selzer */ public class LUTToColorTable { + /** + * Wraps (i.e. copyless) {@code lut} into a {@link ColorTable}. + * @param lut the {@link LUT} to convert + * @return a {@link ColorTable} enclosing {@code lut} + */ public static ColorTable wrap(final LUT lut) { return new ColorTable() { @Override diff --git a/src/test/java/net/imglib2/imagej/ColorTableToLUTTest.java b/src/test/java/net/imglib2/imagej/ColorTableToLUTTest.java new file mode 100644 index 0000000..7e5cb55 --- /dev/null +++ b/src/test/java/net/imglib2/imagej/ColorTableToLUTTest.java @@ -0,0 +1,33 @@ +package net.imglib2.imagej; + +import ij.process.LUT; +import net.imglib2.display.ColorTable; +import net.imglib2.display.ColorTable8; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.assertEquals; + +public class ColorTableToLUTTest { + + @Test + public void testConvertColorTable() { + Random r = new Random(0xdeadbeefL); + byte[] reds = new byte[256]; + r.nextBytes(reds); + byte[] greens = new byte[256]; + r.nextBytes(greens); + byte[] blues = new byte[256]; + r.nextBytes(blues); + ColorTable table = new ColorTable8(reds, greens, blues); + LUT actual = ColorTableToLUT.convert(table); + for(int i = 0; i < 256; i++) { + // Note ColorTable.get unsigned bytes as ints + assertEquals(reds[i], (byte) actual.getRed(i)); + assertEquals(greens[i], (byte) actual.getGreen(i)); + assertEquals(blues[i], (byte) actual.getBlue(i)); + assertEquals((byte) 255, (byte) actual.getAlpha(i)); + } + } +} diff --git a/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java b/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java index e062885..b7c6d60 100644 --- a/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java +++ b/src/test/java/net/imglib2/imagej/LUTToColorTableTest.java @@ -20,10 +20,10 @@ public void testWrapLUT() { Random r = new Random(0xdeadbeefL); byte[] reds = new byte[256]; r.nextBytes(reds); - byte[] blues = new byte[256]; - r.nextBytes(blues); byte[] greens = new byte[256]; r.nextBytes(greens); + byte[] blues = new byte[256]; + r.nextBytes(blues); LUT lut = new LUT(reds, greens, blues); ColorTable actual = LUTToColorTable.wrap(lut); assertEquals(256, actual.getLength());