Search in sources :

Example 1 with BitsPerComponentBox

use of it.geosolutions.imageio.plugins.jp2k.box.BitsPerComponentBox 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));
        }
    }
}
Also used : ICC_ColorSpace(java.awt.color.ICC_ColorSpace) ColorSpace(java.awt.color.ColorSpace) ComponentColorModel(java.awt.image.ComponentColorModel) PaletteBox(it.geosolutions.imageio.plugins.jp2k.box.PaletteBox) ColorSpecificationBox(it.geosolutions.imageio.plugins.jp2k.box.ColorSpecificationBox) ChannelDefinitionBox(it.geosolutions.imageio.plugins.jp2k.box.ChannelDefinitionBox) BitsPerComponentBox(it.geosolutions.imageio.plugins.jp2k.box.BitsPerComponentBox) ICC_ColorSpace(java.awt.color.ICC_ColorSpace) ImageHeaderBox(it.geosolutions.imageio.plugins.jp2k.box.ImageHeaderBox) ComponentMappingBox(it.geosolutions.imageio.plugins.jp2k.box.ComponentMappingBox) ICC_Profile(java.awt.color.ICC_Profile) IndexColorModel(java.awt.image.IndexColorModel)

Aggregations

BitsPerComponentBox (it.geosolutions.imageio.plugins.jp2k.box.BitsPerComponentBox)1 ChannelDefinitionBox (it.geosolutions.imageio.plugins.jp2k.box.ChannelDefinitionBox)1 ColorSpecificationBox (it.geosolutions.imageio.plugins.jp2k.box.ColorSpecificationBox)1 ComponentMappingBox (it.geosolutions.imageio.plugins.jp2k.box.ComponentMappingBox)1 ImageHeaderBox (it.geosolutions.imageio.plugins.jp2k.box.ImageHeaderBox)1 PaletteBox (it.geosolutions.imageio.plugins.jp2k.box.PaletteBox)1 ColorSpace (java.awt.color.ColorSpace)1 ICC_ColorSpace (java.awt.color.ICC_ColorSpace)1 ICC_Profile (java.awt.color.ICC_Profile)1 ComponentColorModel (java.awt.image.ComponentColorModel)1 IndexColorModel (java.awt.image.IndexColorModel)1