use of it.geosolutions.imageio.plugins.jp2k.box.ComponentMappingBox in project imageio-ext by geosolutions-it.
the class JP2KKakaduImageReader method parseBoxes.
/**
* Get basic image properties by querying several JP2Boxes. Then, properly
* set the ColorModel of the input object.
*
* @param codestreamP
*/
private void parseBoxes(JP2KCodestreamProperties codestreamP) {
if (isRawSource)
return;
short numComp = 1;
byte[] bitDepths = null;
byte[] maps = null;
int bitDepth = -1;
ICC_Profile profile = null;
int colorSpaceType = -1;
// //
//
// ImageHeader Box
//
// //
final ImageHeaderBox ihBox = (ImageHeaderBox) getJp2Box(ImageHeaderBox.BOX_TYPE);
if (ihBox != null) {
numComp = ihBox.getNumComponents();
bitDepth = ihBox.getBitDepth();
}
// //
//
// ColorSpecification Box
//
// //
final ColorSpecificationBox csBox = (ColorSpecificationBox) getJp2Box(ColorSpecificationBox.BOX_TYPE);
if (csBox != null) {
profile = csBox.getICCProfile();
colorSpaceType = csBox.getEnumeratedColorSpace();
}
// //
//
// ComponentMapping Box
//
// //
final ComponentMappingBox cmBox = (ComponentMappingBox) getJp2Box(ComponentMappingBox.BOX_TYPE);
if (cmBox != null) {
maps = cmBox.getComponentAssociation();
}
// //
//
// Palette Box
//
// //
final PaletteBox palBox = (PaletteBox) getJp2Box(PaletteBox.BOX_TYPE);
if (palBox != null) {
byte[][] lookUpTable = palBox.getLUT();
if (lookUpTable != null && numComp == 1) {
int tableComps = lookUpTable.length;
int maxDepth = 1 + (bitDepth & 0x7F);
if (maps == null) {
maps = new byte[tableComps];
for (int i = 0; i < tableComps; i++) maps[i] = (byte) i;
}
if (tableComps == 3) {
codestreamP.setColorModel(new IndexColorModel(maxDepth, lookUpTable[0].length, lookUpTable[maps[0]], lookUpTable[maps[1]], lookUpTable[maps[2]]));
return;
} else if (tableComps == 4) {
codestreamP.setColorModel(new IndexColorModel(maxDepth, lookUpTable[0].length, lookUpTable[maps[0]], lookUpTable[maps[1]], lookUpTable[maps[2]], lookUpTable[maps[3]]));
return;
}
}
}
// //
//
// BitsPerComponent Box
//
// //
final BitsPerComponentBox bpcBox = (BitsPerComponentBox) getJp2Box(BitsPerComponentBox.BOX_TYPE);
if (bpcBox != null) {
bitDepths = bpcBox.getBitDepth();
}
// //
//
// ChannelDefinition Box
//
// //
final ChannelDefinitionBox chBox = (ChannelDefinitionBox) getJp2Box(ChannelDefinitionBox.BOX_TYPE);
if (chBox != null) {
final short[] channels = chBox.getChannel();
final short[] associations = chBox.getAssociation();
final int[] cType = chBox.getTypes();
boolean hasAlpha = false;
final int alphaChannel = numComp - 1;
for (int i = 0; i < channels.length; i++) {
if (cType[i] == 1 && channels[i] == alphaChannel)
hasAlpha = true;
}
boolean[] isPremultiplied = new boolean[] { false };
if (hasAlpha) {
isPremultiplied = new boolean[alphaChannel];
for (int i = 0; i < alphaChannel; i++) isPremultiplied[i] = false;
for (int i = 0; i < channels.length; i++) {
if (cType[i] == 2)
isPremultiplied[associations[i] - 1] = true;
}
for (int i = 1; i < alphaChannel; i++) isPremultiplied[0] &= isPremultiplied[i];
}
ColorSpace cs = null;
// RGBN Workaround
if (associations.length == 4) /* && associations[0]==1 && associations[1]==2 && associations[2]==3*/
{
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
hasAlpha = true;
} else if (profile != null)
cs = new ICC_ColorSpace(profile);
else if (colorSpaceType == ColorSpecificationBox.ECS_sRGB)
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
else if (colorSpaceType == ColorSpecificationBox.ECS_GRAY)
cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
else if (colorSpaceType == ColorSpecificationBox.ECS_YCC)
cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
else
LOGGER.warning("JP2 type only handle sRGB, GRAY and YCC Profiles");
// TODO: Check these settings
int[] bits = new int[numComp];
for (int i = 0; i < numComp; i++) if (bitDepths != null)
bits[i] = (bitDepths[i] & 0x7F) + 1;
else
bits[i] = (bitDepth & 0x7F) + 1;
int maxBitDepth = 1 + (bitDepth & 0x7F);
boolean isSigned = (bitDepth & 0x80) == 0x80;
if (bitDepths != null)
isSigned = (bitDepths[0] & 0x80) == 0x80;
if (bitDepths != null)
for (int i = 0; i < numComp; i++) if (bits[i] > maxBitDepth)
maxBitDepth = bits[i];
int type = -1;
if (maxBitDepth <= 8)
type = DataBuffer.TYPE_BYTE;
else if (maxBitDepth <= 16)
type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
else if (maxBitDepth <= 32)
type = DataBuffer.TYPE_INT;
if (type == -1)
return;
if (cs != null) {
codestreamP.setColorModel(new ComponentColorModel(cs, bits, hasAlpha, isPremultiplied[0], hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, type));
}
}
}
Aggregations