public ColorModel getColorModel() { if (colorModel != null) return colorModel; // Attempt to get the ColorModel from the JP2 boxes. colorModel = ff.getColorModel(); if (colorModel != null) return colorModel; if (hi.siz.csiz <= 4) { // XXX: Code essentially duplicated from FileFormatReader.getColorModel(). // Create the ColorModel from the SIZ marker segment parameters. ColorSpace cs; if (hi.siz.csiz > 2) { cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); } else { cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); } int[] bitsPerComponent = new int[hi.siz.csiz]; boolean isSigned = false; int maxBitDepth = -1; for (int i = 0; i < hi.siz.csiz; i++) { bitsPerComponent[i] = hi.siz.getOrigBitDepth(i); if (maxBitDepth < bitsPerComponent[i]) { maxBitDepth = bitsPerComponent[i]; } isSigned |= hi.siz.isOrigSigned(i); } boolean hasAlpha = hi.siz.csiz % 2 == 0; 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) { if (hi.siz.csiz == 1 && (maxBitDepth == 1 || maxBitDepth == 2 || maxBitDepth == 4)) { colorModel = ImageUtil.createColorModel(getSampleModel()); } else { colorModel = new ComponentColorModel( cs, bitsPerComponent, hasAlpha, false, hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, type); } return colorModel; } } if (sampleModel == null) { sampleModel = getSampleModel(); } if (sampleModel == null) return null; return ImageUtil.createColorModel(null, sampleModel); }
private void initializeRead(int imageIndex, J2KImageReadParamJava param, J2KMetadata metadata) { try { iis.mark(); in = new IISRandomAccessIO(iis); // **** File Format **** // If the codestream is wrapped in the jp2 fileformat, Read the // file format wrapper ff = new FileFormatReader(in, metadata); ff.readFileFormat(); in.seek(ff.getFirstCodeStreamPos()); hi = new HeaderInfo(); try { hd = new HeaderDecoder(in, j2krparam, hi); } catch (EOFException e) { throw new RuntimeException(I18N.getString("J2KReadState2")); } catch (IOException ioe) { throw new RuntimeException(ioe); } this.width = hd.getImgWidth(); this.height = hd.getImgHeight(); Rectangle sourceRegion = param.getSourceRegion(); sourceOrigin = new Point(); sourceRegion = new Rectangle(hd.getImgULX(), hd.getImgULY(), this.width, this.height); // if the subsample rate for components are not consistent boolean compConsistent = true; stepX = hd.getCompSubsX(0); stepY = hd.getCompSubsY(0); for (int i = 1; i < nComp; i++) { if (stepX != hd.getCompSubsX(i) || stepY != hd.getCompSubsY(i)) throw new RuntimeException(I18N.getString("J2KReadState12")); } // Get minimum number of resolution levels available across // all tile-components. int minResLevels = hd.getDecoderSpecs().dls.getMin(); // Set current resolution level. this.resolution = param != null ? param.getResolution() : minResLevels; if (resolution < 0 || resolution > minResLevels) { resolution = minResLevels; } // Convert source region to lower resolution level. if (resolution != minResLevels || stepX != 1 || stepY != 1) { sourceRegion = J2KImageReader.getReducedRect(sourceRegion, minResLevels, resolution, stepX, stepY); } destinationRegion = (Rectangle) sourceRegion.clone(); J2KImageReader.computeRegionsWrapper( param, false, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); sourceOrigin = new Point(sourceRegion.x, sourceRegion.y); scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); this.width = destinationRegion.width; this.height = destinationRegion.height; Point tileOffset = hd.getTilingOrigin(null); this.tileWidth = hd.getNomTileWidth(); this.tileHeight = hd.getNomTileHeight(); // Convert tile 0 to lower resolution level. if (resolution != minResLevels || stepX != 1 || stepY != 1) { Rectangle tileRect = new Rectangle(tileOffset); tileRect.width = tileWidth; tileRect.height = tileHeight; tileRect = J2KImageReader.getReducedRect(tileRect, minResLevels, resolution, stepX, stepY); tileOffset = tileRect.getLocation(); tileWidth = tileRect.width; tileHeight = tileRect.height; } tileXOffset = tileOffset.x; tileYOffset = tileOffset.y; // Set the tile step sizes. These values are used because it // is possible that tiles will be empty. In particular at lower // resolution levels when subsampling is used this may be the // case. This method of calculation will work at least for // Profile-0 images. if (tileWidth * (1 << (minResLevels - resolution)) * stepX > hd.getNomTileWidth()) { tileStepX = (tileWidth * (1 << (minResLevels - resolution)) * stepX + hd.getNomTileWidth() - 1) / hd.getNomTileWidth(); } else { tileStepX = 1; } if (tileHeight * (1 << (minResLevels - resolution)) * stepY > hd.getNomTileHeight()) { tileStepY = (tileHeight * (1 << (minResLevels - resolution)) * stepY + hd.getNomTileHeight() - 1) / hd.getNomTileHeight(); } else { tileStepY = 1; } if (!destinationRegion.equals(sourceRegion)) noTransform = false; // **** Header decoder **** // Instantiate header decoder and read main header decSpec = hd.getDecoderSpecs(); // **** Instantiate decoding chain **** // Get demixed bitdepths nComp = hd.getNumComps(); int[] depth = new int[nComp]; for (int i = 0; i < nComp; i++) depth[i] = hd.getOriginalBitDepth(i); // Get channel mapping ChannelDefinitionBox cdb = null; if (metadata != null) cdb = (ChannelDefinitionBox) metadata.getElement("JPEG2000ChannelDefinitionBox"); channelMap = new int[nComp]; if (cdb != null && metadata.getElement("JPEG2000PaletteBox") == null) { short[] assoc = cdb.getAssociation(); short[] types = cdb.getTypes(); short[] channels = cdb.getChannel(); for (int i = 0; i < types.length; i++) if (types[i] == 0) channelMap[channels[i]] = assoc[i] - 1; else if (types[i] == 1 || types[i] == 2) channelMap[channels[i]] = channels[i]; } else { for (int i = 0; i < nComp; i++) channelMap[i] = i; } // **** Bitstream reader **** try { boolean logJJ2000Messages = Boolean.getBoolean("jj2000.j2k.decoder.log"); breader = BitstreamReaderAgent.createInstance(in, hd, j2krparam, decSpec, logJJ2000Messages, hi); } catch (IOException e) { throw new RuntimeException( I18N.getString("J2KReadState3") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } catch (IllegalArgumentException e) { throw new RuntimeException( I18N.getString("J2KReadState4") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } // **** Entropy decoder **** try { entdec = hd.createEntropyDecoder(breader, j2krparam); } catch (IllegalArgumentException e) { throw new RuntimeException( I18N.getString("J2KReadState5") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } // **** ROI de-scaler **** try { roids = hd.createROIDeScaler(entdec, j2krparam, decSpec); } catch (IllegalArgumentException e) { throw new RuntimeException( I18N.getString("J2KReadState6") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } // **** Dequantizer **** try { deq = hd.createDequantizer(roids, depth, decSpec); } catch (IllegalArgumentException e) { throw new RuntimeException( I18N.getString("J2KReadState7") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } // **** Inverse wavelet transform *** try { // full page inverse wavelet transform invWT = InverseWT.createInstance(deq, decSpec); } catch (IllegalArgumentException e) { throw new RuntimeException( I18N.getString("J2KReadState8") + " " + ((e.getMessage() != null) ? (":\n" + e.getMessage()) : "")); } int res = breader.getImgRes(); int mrl = decSpec.dls.getMin(); invWT.setImgResLevel(res); // **** Data converter **** (after inverse transform module) converter = new ImgDataConverter(invWT, 0); // **** Inverse component transformation **** ictransf = new InvCompTransf(converter, decSpec, depth); // If the destination band is set used it sourceBands = j2krparam.getSourceBands(); if (sourceBands == null) { sourceBands = new int[nComp]; for (int i = 0; i < nComp; i++) sourceBands[i] = i; } nComp = sourceBands.length; destinationBands = j2krparam.getDestinationBands(); if (destinationBands == null) { destinationBands = new int[nComp]; for (int i = 0; i < nComp; i++) destinationBands[i] = i; } J2KImageReader.checkReadParamBandSettingsWrapper( param, hd.getNumComps(), destinationBands.length); levelShift = new int[nComp]; minValues = new int[nComp]; maxValues = new int[nComp]; fracBits = new int[nComp]; dataBlocks = new DataBlkInt[nComp]; depth = new int[nComp]; bandOffsets = new int[nComp]; maxDepth = 0; isSigned = false; for (int i = 0; i < nComp; i++) { depth[i] = hd.getOriginalBitDepth(sourceBands[i]); if (depth[i] > maxDepth) maxDepth = depth[i]; dataBlocks[i] = new DataBlkInt(); // XXX: may need to change if ChannelDefinition is used to // define the color channels, such as BGR order bandOffsets[i] = i; if (hd.isOriginalSigned(sourceBands[i])) isSigned = true; else { levelShift[i] = 1 << (ictransf.getNomRangeBits(sourceBands[i]) - 1); } // Get the number of bits in the image, and decide what the max // value should be, depending on whether it is signed or not int nomRangeBits = ictransf.getNomRangeBits(sourceBands[i]); maxValues[i] = (1 << (isSigned == true ? (nomRangeBits - 1) : nomRangeBits)) - 1; minValues[i] = isSigned ? -(maxValues[i] + 1) : 0; fracBits[i] = ictransf.getFixedPoint(sourceBands[i]); } iis.reset(); } catch (IllegalArgumentException e) { throw new RuntimeException(e.getMessage(), e); } catch (Error e) { if (e.getMessage() != null) throw new RuntimeException(e.getMessage(), e); else { throw new RuntimeException(I18N.getString("J2KReadState9"), e); } } catch (RuntimeException e) { if (e.getMessage() != null) throw new RuntimeException(I18N.getString("J2KReadState10") + " " + e.getMessage(), e); else { throw new RuntimeException(I18N.getString("J2KReadState10"), e); } } catch (Throwable e) { throw new RuntimeException(I18N.getString("J2KReadState10"), e); } }