This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit c9a672132b340426af8beacbf1e9d0bf96b07809 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sat Dec 14 13:10:38 2024 +0100 Move the `createPackedRGB(…)` and createBandedRGB(…)` methods in a new `ColorModelBuilder` class. In gives more flexibility for configuring the RGB color model to create. --- .../sis/coverage/privy/ColorModelBuilder.java | 302 +++++++++++++++++++++ .../sis/coverage/privy/ColorModelFactory.java | 103 +------ .../main/org/apache/sis/image/Colorizer.java | 3 +- .../sis/storage/geotiff/ImageFileDirectory.java | 7 +- .../org/apache/sis/storage/geotiff/WriterTest.java | 4 +- .../sis/storage/sql/postgis/RasterReader.java | 3 +- .../org/apache/sis/storage/esri/RasterStore.java | 13 +- .../org/apache/sis/storage/gdal/TiledResource.java | 3 +- 8 files changed, 323 insertions(+), 115 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelBuilder.java new file mode 100644 index 0000000000..6a9327bc71 --- /dev/null +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelBuilder.java @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.coverage.privy; + +import java.util.Arrays; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.BandedSampleModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.SampleModel; +import org.apache.sis.util.ArgumentChecks; +import org.apache.sis.util.ArraysExt; + + +/** + * Helper classes for creating a <abbr>RGB</abbr> color model suitable for a sample model. + * Usage: + * + * <ol> + * <li>Create a new {@link ColorModelBuilder} instance.</li> + * <li>Invoke setter methods.</li> + * <li>Invoke {@link #createPackedRGB()} or {@link #createBandedRGB()}.</li> + * <li>Discards {@code ColorModelBuilder}. Each instance shall be used only once.</li> + * </ol> + * + * @author Martin Desruisseaux (Geomatys) + * + * @see ColorModelType + */ +public final class ColorModelBuilder { + /** + * The usual position of the alpha channel. + * This channel is usually immediately after the <abbr>RGB</abbr> components. + */ + private static final int STANDARD_ALPHA_BAND = 3; + + /** + * Number of bits per sample, or {@code null} for the default values in all bands. + * The array length is the number of bands: 3 for <abbr>RGB</abbr> or 4 for <abbr>ARGB</abbr>. + * Each array element may be 0, which means to use the default for that specific band. + * If no number of bits is specified, the default is {@value Byte#SIZE}. + */ + private int[] bitsPerSample; + + /** + * Index of the alpha channel (usually the last band), or -1 if none. + */ + private int alphaBand; + + /** + * Whether the alpha value (if present) is premultiplied. + */ + private boolean isAlphaPremultiplied; + + /** + * Creates a new builder initialized with default values. + */ + public ColorModelBuilder() { + alphaBand = -1; + } + + /** + * Sets the number of bits per sample as a potentially different number for each band. + * The given array is stored without copy on the assumption that is will not be modified + * (this is okay for internal API). + * If no number of bits is specified, the default is {@value Byte#SIZE}. + * + * @param numBits number of bits per sample, or {@code null} for the default values. + * @return {@code this} for method calls chaining. + */ + public ColorModelBuilder bitsPerSample(final int[] numBits) { + bitsPerSample = numBits; + if (hasDefaultBitsPerSample()) { + bitsPerSample = null; + } + return this; + } + + /** + * Sets the number of bits per sample as a unique number for all bands. + * If no number of bits is specified, the default is {@value Byte#SIZE}. + * + * @param numBits number of bits per sample in each band. + * @return {@code this} for method calls chaining. + * @throws IllegalArgumentException if the given value is out of bounds. + */ + public ColorModelBuilder bitsPerSample(final int numBits) { + ArgumentChecks.ensureBetween("bitsPerSample", 1, Integer.SIZE, numBits); + if (numBits != Byte.SIZE) { + bitsPerSample = new int[STANDARD_ALPHA_BAND + 1]; + Arrays.fill(bitsPerSample, numBits); + } else { + bitsPerSample = null; + } + return this; + } + + /** + * Returns whether this builder currently uses the default number of bits per sample. + */ + private boolean hasDefaultBitsPerSample() { + if (bitsPerSample != null) { + for (int numBits : bitsPerSample) { + if (numBits != Byte.SIZE) { + return false; + } + } + } + return true; + } + + /** + * Returns the number of bits per sample in the given band. + * If no number of bits per sample was specified, the default value is {@link Byte#SIZE}. + * + * @param band the band index for which to get the number of bits per sample. + * @param max maximal value allowed. + * @return the number of bits per sample in the given band, guaranteed between 1 and {@code max} inclusive. + * @throws IllegalArgumentException if the number of bits per sample is out of bounds. + */ + private int getBitsPerSample(final int band, final int max) { + if (bitsPerSample != null && band < bitsPerSample.length) { + int numBits = bitsPerSample[band]; + if (numBits != 0) { + ArgumentChecks.ensureBetween("bitsPerSample", 1, max, numBits); + return numBits; + } + } + return Byte.SIZE; + } + + /** + * Sets the index of the alpha channel. It should be the band immediately after the color bands, + * but some color model allows other position. + * + * @param index of the alpha channel (usually the last band), or -1 if none. + * @return {@code this} for method calls chaining. + */ + public ColorModelBuilder alphaBand(final int index) { + if (index >= 0) { + ArgumentChecks.ensureBetween("alphaBand", 0, STANDARD_ALPHA_BAND, index); + } + alphaBand = index; + return this; + } + + /** + * Sets whether the alpha value (if present) is premultiplied. + * + * @param p whether the alpha value (if present) is premultiplied. + * @return {@code this} for method calls chaining. + */ + public ColorModelBuilder isAlphaPremultiplied(final boolean p) { + isAlphaPremultiplied = p; + return this; + } + + /** + * Returns the color space of the color model to build. + * The current implementation fixes the color space to <abbr>RGB</abbr>, + * but it may change in a future implementation if needed. + * + * <h4>Limitation</h4> + * Note that {@link #createPackedRGB()} is limited to color spaces of the <abbr>RGB</abbr> family. + * This is a restriction of {@link DirectColorModel}. + */ + private static ColorSpace colorSpace() { + return ColorSpace.getInstance(ColorSpace.CS_sRGB); + } + + /** + * Returns the data type to use for the given number of bits. + */ + private static int dataType(final int numBits) { + return (numBits <= Byte.SIZE) ? DataBuffer.TYPE_BYTE : + (numBits <= Short.SIZE) ? DataBuffer.TYPE_USHORT : DataBuffer.TYPE_INT; + } + + /** + * Creates a RGB color model for use with {@link SinglePixelPackedSampleModel}. + * Pixel values are packed in a single integer (usually 32-bits) per pixel. + * Color components are separated using a bitmask for each <abbr>RGBA</abbr> value. + * + * <h4>Limitations</h4> + * The color model is restricted to the <abbr>RGB</abbr> family. + * + * @return color model for use with {@link java.awt.image.SinglePixelPackedSampleModel}. + * @throws IllegalArgumentException if any argument specified to the builder is invalid. + */ + public ColorModel createPackedRGB() { + if (!isAlphaPremultiplied && alphaBand == STANDARD_ALPHA_BAND && hasDefaultBitsPerSample()) { + return ColorModel.getRGBdefault(); + } + // Red, Green, Blue, Alpha masks in that order. + final int[] masks = new int[STANDARD_ALPHA_BAND + 1]; + int numBits = 0; + for (int i=STANDARD_ALPHA_BAND - 1; i >= -1; i--) { + int band = i; + if (band < 0) { + band = alphaBand; + if (band < 0) break; + } + int n = getBitsPerSample(band, Math.min(Byte.SIZE, Integer.SIZE - numBits)); + masks[i] = ((1 << n) - 1) << numBits; + numBits += n; + } + return ColorModelFactory.unique(new DirectColorModel(colorSpace(), + numBits, masks[0], masks[1], masks[2], masks[3], isAlphaPremultiplied, dataType(numBits))); + } + + /** + * Creates a RGB color model for use with {@link BandedSampleModel}. + * Each color component (sample value) is stored in a separated data element. + * + * <h4>Limitations</h4> + * The current version requires the alpha channel (if present) to be the last band. + * If this condition is not met, this method returns {@code null}. + * + * @return color model for use with {@link java.awt.image.BandedSampleModel}. + * @throws IllegalArgumentException if any argument specified to the builder is invalid. + */ + public ColorModel createBandedRGB() { + final int numBands; + final int transparency; + final boolean hasAlpha = (alphaBand >= 0); + if (hasAlpha) { + if (alphaBand != STANDARD_ALPHA_BAND) { + throw new IllegalArgumentException("Alpha channel must be after the color components."); + } + numBands = 4; + transparency = Transparency.TRANSLUCENT; + } else { + numBands = 3; + transparency = Transparency.OPAQUE; + } + int[] numBits = bitsPerSample; + numBits = ArraysExt.resize(numBits != null ? numBits : ArraysExt.EMPTY_INT, numBands); + int maxSize = 0; + for (int i=0; i<numBands; i++) { + if (numBits[i] == 0) { + if (numBits == bitsPerSample) { + numBits = numBits.clone(); + } + numBits[i] = Byte.SIZE; + } else { + maxSize = Math.max(maxSize, numBits[i]); + } + } + return ColorModelFactory.unique(new ComponentColorModel(colorSpace(), + numBits, hasAlpha, isAlphaPremultiplied, transparency, dataType(maxSize))); + } + + /** + * Creates a <abbr>RGB</abbr> color model for the given sample model. + * The sample model shall use integer type and have 3 or 4 bands. + * This method may return {@code null} if the color model cannot be created. + * + * @param targetModel the sample model for which to create a color model. + * @return the color model, or {@code null} if the given sample model is not supported. + * @throws IllegalArgumentException if any argument specified to the builder is invalid. + */ + public ColorModel create(final SampleModel targetModel) { +check: if (ImageUtilities.isIntegerType(targetModel)) { + final int numBands = targetModel.getNumBands(); + switch (numBands) { + case 3: alphaBand = -1; break; + case 4: alphaBand = STANDARD_ALPHA_BAND; break; + default: break check; + } + bitsPerSample = targetModel.getSampleSize(); + if (targetModel.getNumDataElements() != 1) { + return createBandedRGB(); + } else { + for (int i=0; i<numBands; i++) { + if (bitsPerSample[i] > Byte.SIZE) { + break check; + } + } + return createPackedRGB(); + } + } + return null; + } +} diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelFactory.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelFactory.java index a17bb04d1d..c71c4b5379 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelFactory.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorModelFactory.java @@ -455,7 +455,7 @@ public final class ColorModelFactory { * @param cm the color model. * @return a unique instance of the given color model. */ - private static ColorModel unique(final ColorModel cm) { + static ColorModel unique(final ColorModel cm) { return CACHE.unique(cm); } @@ -591,107 +591,6 @@ public final class ColorModelFactory { return createGrayScale(model.getDataType(), model.getNumBands(), visibleBand, minimum, maximum); } - /** - * Creates a RGB color model for the given sample model. - * The sample model shall use integer type and have 3 or 4 bands. - * This method may return {@code null} if the color model cannot be created. - * - * @param targetModel the sample model for which to create a color model. - * @param isAlphaPremultiplied whether the alpha value (if present) is premultiplied. - * @return the color model, or null if a precondition does not hold. - */ - public static ColorModel createRGB(final SampleModel targetModel, final boolean isAlphaPremultiplied) { -check: if (ImageUtilities.isIntegerType(targetModel)) { - final int numBands = targetModel.getNumBands(); - final int alphaBand; - switch (numBands) { - case 3: alphaBand = -1; break; - case 4: alphaBand = 3; break; - default: break check; - } - int bitsPerSample = 0; - for (int i=0; i<numBands; i++) { - bitsPerSample = Math.max(bitsPerSample, targetModel.getSampleSize(i)); - } - if (targetModel.getNumDataElements() != 1) { - return createBandedRGB(bitsPerSample, alphaBand, isAlphaPremultiplied); - } else if (bitsPerSample <= Byte.SIZE) { - return createPackedRGB(bitsPerSample, alphaBand, isAlphaPremultiplied); - } - } - return null; - } - - /** - * Creates a RGB color model for use with {@code SinglePixelPackedSampleModel}. - * Pixel values are packed in a single integer (usually 32-bits) per pixel. - * Color components are separated using a bitmask for each <abbr>RGBA</abbr> value. - * - * @param bitsPerSample number of bits per sample, between 1 and 8 inclusive. - * @param alphaBand index of the alpha channel (usually the last band), or -1 if none. - * @param isAlphaPremultiplied whether the alpha value (if present) is premultiplied. - * @return color model for use with {@link java.awt.image.SinglePixelPackedSampleModel}. - */ - public static ColorModel createPackedRGB(final int bitsPerSample, final int alphaBand, final boolean isAlphaPremultiplied) { - if (bitsPerSample == Byte.SIZE && alphaBand == 3 && !isAlphaPremultiplied) { - return ColorModel.getRGBdefault(); - } - ArgumentChecks.ensureBetween("bitsPerSample", 1, Byte.SIZE, bitsPerSample); - final int[] masks = new int[4]; // Red, Green, Blue, Alpha masks in that order. - int mask = (1 << bitsPerSample) - 1; // Start with blue = 0xFF (usually). - for (int i=2; i >= 0; i--) { - masks[i] = mask; - mask <<= bitsPerSample; - } - int numBands = 3; - if (alphaBand >= 0) { - System.arraycopy(masks, alphaBand, masks, alphaBand+1, 3 - alphaBand); - masks[alphaBand] = mask; - numBands = 4; - } - int numBits = numBands * bitsPerSample; - int dataType = (numBits <= Byte.SIZE) ? DataBuffer.TYPE_BYTE : - (numBits <= Short.SIZE) ? DataBuffer.TYPE_USHORT : DataBuffer.TYPE_INT; - var cm = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), - numBits, masks[0], masks[1], masks[2], masks[3], - isAlphaPremultiplied, dataType); - return unique(cm); - } - - /** - * Creates a RGB color model for use with {@code BandedSampleModel}. - * Each color component (sample value) is stored in a separated data element. - * - * <h4>Limitations</h4> - * The current version requires the alpha channel (if present) to be the last band. - * If this condition is not met, this method returns {@code null}. - * - * @param bitsPerSample number of bits per sample, between 1 and 32 inclusive. - * @param alphaBand index of the alpha channel (usually the last band), or -1 if none. - * @param isAlphaPremultiplied whether the alpha value (if present) is premultiplied. - * @return color model for use with {@link java.awt.image.BandedSampleModel}, or {@code null}. - */ - public static ColorModel createBandedRGB(final int bitsPerSample, final int alphaBand, final boolean isAlphaPremultiplied) { - ArgumentChecks.ensureBetween("bitsPerSample", 1, Integer.SIZE, bitsPerSample); - final int[] numBits; - final int transparency; - final boolean hasAlpha = (alphaBand >= 0); - if (hasAlpha) { - if (alphaBand != 3) { - return null; // Limitation documented in method Javadoc. - } - numBits = new int[4]; - transparency = Transparency.TRANSLUCENT; - } else { - numBits = new int[3]; - transparency = Transparency.OPAQUE; - } - Arrays.fill(numBits, bitsPerSample); - var cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), - numBits, hasAlpha, isAlphaPremultiplied, transparency, DataBuffer.TYPE_BYTE); - return unique(cm); - } - /** * Creates a color model with only a subset of the bands of the given color model. The returned color model * is compatible with a {@linkplain SampleModel#createSubsetSampleModel(int[]) subset sample model} created diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java index 82ae3baa77..cc55809967 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java @@ -31,6 +31,7 @@ import java.awt.image.IndexColorModel; import java.awt.image.RenderedImage; import org.apache.sis.coverage.Category; import org.apache.sis.coverage.SampleDimension; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.coverage.privy.ColorScaleBuilder; import org.apache.sis.coverage.privy.ColorModelFactory; import org.apache.sis.measure.NumberRange; @@ -160,7 +161,7 @@ public interface Colorizer extends Function<Colorizer.Target, Optional<ColorMode * The color model is <abbr>RGB</abbr> for image having 3 bands, or <abbr>ARGB</abbr> for images having 4 bands. * In the latter case, the color components are considered <em>not</em> premultiplied by the alpha value. */ - Colorizer ARGB = (target) -> Optional.ofNullable(ColorModelFactory.createRGB(target.getSampleModel(), false)); + Colorizer ARGB = (target) -> Optional.ofNullable(new ColorModelBuilder().create(target.getSampleModel())); /** * Creates a colorizer which will interpolate the given colors in the given range of values. diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java index abe78d10dc..1e7dbed31b 100644 --- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java +++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java @@ -52,6 +52,7 @@ import org.apache.sis.io.stream.ChannelDataInput; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridExtent; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.coverage.privy.ColorModelFactory; import org.apache.sis.coverage.privy.SampleModelFactory; import org.apache.sis.util.Numbers; @@ -1760,10 +1761,12 @@ final class ImageFileDirectory extends DataCube { } case PHOTOMETRIC_INTERPRETATION_RGB: { if (alphaBand >= 0) alphaBand += 3; // Must add the number of color bands. + final var builder = new ColorModelBuilder().bitsPerSample(bitsPerSample) + .alphaBand(alphaBand).isAlphaPremultiplied(isAlphaPremultiplied); if (getSampleModel(null) instanceof SinglePixelPackedSampleModel) { - colorModel = ColorModelFactory.createPackedRGB(bitsPerSample, alphaBand, isAlphaPremultiplied); + colorModel = builder.createPackedRGB(); } else { - colorModel = ColorModelFactory.createBandedRGB(bitsPerSample, alphaBand, isAlphaPremultiplied); + colorModel = builder.createBandedRGB(); } break; } diff --git a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java index 5577acd807..16971a8f4e 100644 --- a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java +++ b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java @@ -41,7 +41,7 @@ import org.apache.sis.storage.geotiff.base.Tags; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridOrientation; -import org.apache.sis.coverage.privy.ColorModelFactory; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.geometry.Envelope2D; import org.apache.sis.image.DataType; @@ -237,7 +237,7 @@ public final class WriterTest extends TestCase { @Test public void testUntiledRGB() throws IOException, DataStoreException { initialize(DataType.BYTE, ByteOrder.LITTLE_ENDIAN, false, 3, 1, 1); - image.setColorModel(ColorModelFactory.createRGB(image.getSampleModel(), false)); + image.setColorModel(new ColorModelBuilder().create(image.getSampleModel())); writeImage(); verifyHeader(false, IOBase.LITTLE_ENDIAN); verifyImageFileDirectory(Writer.COMMON_NUMBER_OF_TAGS - 1, // One less tag because stripped layout. diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java index 0827136e77..1d7a0a3ecf 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java @@ -44,6 +44,7 @@ import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridCoverage2D; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.coverage.privy.ColorModelFactory; import org.apache.sis.coverage.privy.ObservableImage; import org.apache.sis.referencing.CRS; @@ -316,7 +317,7 @@ public final class RasterReader extends RasterFormat { final int dataType = sm.getDataType(); final int numBands = sm.getNumBands(); if ((numBands == 3) && (dataType == DataBuffer.TYPE_BYTE)) { - cm = ColorModelFactory.createBandedRGB(Byte.SIZE, -1, false); + cm = new ColorModelBuilder().createBandedRGB(); } else { final int visibleBand = 0; // Arbitrary value (could be configurable). final double minimum, maximum; diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java index 5fea017665..e222f4711c 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java @@ -43,6 +43,7 @@ import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.base.PRJDataStore; import org.apache.sis.storage.base.MetadataBuilder; import org.apache.sis.coverage.privy.ColorModelFactory; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.coverage.privy.ImageUtilities; import org.apache.sis.coverage.privy.ObservableImage; import org.apache.sis.coverage.privy.RangeArgument; @@ -395,14 +396,14 @@ abstract class RasterStore extends PRJDataStore implements GridCoverageResource * The color file is optional and will be used if present. */ if (band == VISIBLE_BAND) { - if (isRGB) { - colorModel = ColorModelFactory.createRGB(sm, false); // Should never be null. - } else { - try { + try { + if (isRGB) { + colorModel = new ColorModelBuilder().create(sm); + } else { colorModel = readColorMap(dataType, (int) (maximum + 1), bands.length); - } catch (URISyntaxException | IOException | NumberFormatException e) { - cannotReadAuxiliaryFile(CLR, e); } + } catch (URISyntaxException | IOException | IllegalArgumentException e) { + cannotReadAuxiliaryFile(CLR, e); } if (colorModel == null) { colorModel = ColorModelFactory.createGrayScale(dataType, bands.length, band, minimum, maximum); diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java index 7e72b37161..0bec8c97c9 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java @@ -43,6 +43,7 @@ import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.PixelInCell; import org.apache.sis.coverage.privy.ImageLayout; +import org.apache.sis.coverage.privy.ColorModelBuilder; import org.apache.sis.coverage.privy.ColorModelFactory; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreReferencingException; @@ -473,7 +474,7 @@ final class TiledResource extends TiledGridResource { */ } if ((red | green | blue) >= 0) { - colorModel = ColorModelFactory.createBandedRGB(dataType.numBits, alpha, false); + colorModel = new ColorModelBuilder().bitsPerSample(dataType.numBits).alphaBand(alpha).createBandedRGB(); // TODO: needs custom color model if too many bands, or if order is not (A)RGB. } else if (palette != null) { colorModel = ColorModelFactory.createIndexColorModel(selectedBands.length, paletteIndex, palette, true, -1);