예제 #1
0
  public SampleModel getSampleModel() {
    if (sampleModel != null) return sampleModel;

    int realWidth = (int) Math.min(tileWidth, width);
    int realHeight = (int) Math.min(tileHeight, height);

    if (nComp == 1 && (maxDepth == 1 || maxDepth == 2 || maxDepth == 4))
      sampleModel =
          new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, realWidth, realHeight, maxDepth);
    else if (maxDepth <= 8)
      sampleModel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_BYTE, realWidth, realHeight, nComp, realWidth * nComp, bandOffsets);
    else if (maxDepth <= 16)
      sampleModel =
          new PixelInterleavedSampleModel(
              isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT,
              realWidth,
              realHeight,
              nComp,
              realWidth * nComp,
              bandOffsets);
    else if (maxDepth <= 32)
      sampleModel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_INT, realWidth, realHeight, nComp, realWidth * nComp, bandOffsets);
    else throw new IllegalArgumentException(I18N.getString("J2KReadState11") + " " + +maxDepth);
    return sampleModel;
  }
예제 #2
0
  /**
   * Constructs <code>J2KReadState</code>.
   *
   * @param iis The input stream.
   * @param param The reading parameters.
   * @param reader The <code>J2KImageReader</code> which holds this state. It is necessary for
   *     processing abortion.
   * @throw IllegalArgumentException If the provided <code>iis</code>, or <code>param</code> is
   *     <code>null</code>.
   */
  public J2KReadState(ImageInputStream iis, J2KImageReadParamJava param, J2KImageReader reader) {
    if (iis == null || param == null)
      throw new IllegalArgumentException(I18N.getString("J2KReadState0"));

    this.iis = iis;
    this.j2krparam = param;
    this.reader = reader;
    initializeRead(0, param, null);
  }
예제 #3
0
  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);
    }
  }
예제 #4
0
  public Raster getTile(int tileX, int tileY, WritableRaster raster) throws IOException {
    Point nT = ictransf.getNumTiles(null);

    if (noTransform) {
      if (tileX >= nT.x || tileY >= nT.y)
        throw new IllegalArgumentException(I18N.getString("J2KImageReader0"));

      ictransf.setTile(tileX * tileStepX, tileY * tileStepY);

      // The offset of the active tiles is the same for all components,
      // since we don't support different component dimensions.
      int tOffx;
      int tOffy;
      int cTileWidth;
      int cTileHeight;
      if (raster != null && (this.resolution < hd.getDecoderSpecs().dls.getMin())
          || stepX != 1
          || stepY != 1) {
        tOffx = raster.getMinX();
        tOffy = raster.getMinY();
        cTileWidth = Math.min(raster.getWidth(), ictransf.getTileWidth());
        cTileHeight = Math.min(raster.getHeight(), ictransf.getTileHeight());
      } else {
        tOffx =
            ictransf.getCompULX(0)
                - (ictransf.getImgULX() + ictransf.getCompSubsX(0) - 1) / ictransf.getCompSubsX(0)
                + destinationRegion.x;
        tOffy =
            ictransf.getCompULY(0)
                - (ictransf.getImgULY() + ictransf.getCompSubsY(0) - 1) / ictransf.getCompSubsY(0)
                + destinationRegion.y;
        cTileWidth = ictransf.getTileWidth();
        cTileHeight = ictransf.getTileHeight();
      }

      if (raster == null)
        raster = Raster.createWritableRaster(sampleModel, new Point(tOffx, tOffy));

      int numBands = sampleModel.getNumBands();

      if (tOffx + cTileWidth >= destinationRegion.width + destinationRegion.x)
        cTileWidth = destinationRegion.width + destinationRegion.x - tOffx;

      if (tOffy + cTileHeight >= destinationRegion.height + destinationRegion.y)
        cTileHeight = destinationRegion.height + destinationRegion.y - tOffy;

      // create the line buffer for pixel data if it is not large enough
      // or null
      if (pixbuf == null || pixbuf.length < cTileWidth * numBands)
        pixbuf = new int[cTileWidth * numBands];
      boolean prog = false;

      // Deliver in lines to reduce memory usage
      for (int l = 0; l < cTileHeight; l++) {
        if (reader.getAbortRequest()) break;

        // Request line data
        for (int i = 0; i < numBands; i++) {
          if (reader.getAbortRequest()) break;
          DataBlkInt db = dataBlocks[i];
          db.ulx = 0;
          db.uly = l;
          db.w = cTileWidth;
          db.h = 1;
          ictransf.getInternCompData(db, channelMap[sourceBands[i]]);
          prog = prog || db.progressive;

          int[] data = db.data;
          int k1 = db.offset + cTileWidth - 1;

          int fracBit = fracBits[i];
          int lS = levelShift[i];
          int min = minValues[i];
          int max = maxValues[i];

          if (ImageUtil.isBinary(sampleModel)) {
            // Force min max to 0 and 1.
            min = 0;
            max = 1;
            if (bytebuf == null || bytebuf.length < cTileWidth * numBands)
              bytebuf = new byte[cTileWidth * numBands];
            for (int j = cTileWidth - 1; j >= 0; j--) {
              int tmp = (data[k1--] >> fracBit) + lS;
              bytebuf[j] = (byte) ((tmp < min) ? min : ((tmp > max) ? max : tmp));
            }

            ImageUtil.setUnpackedBinaryData(
                bytebuf, raster, new Rectangle(tOffx, tOffy + l, cTileWidth, 1));
          } else {

            for (int j = cTileWidth - 1; j >= 0; j--) {
              int tmp = (data[k1--] >> fracBit) + lS;
              pixbuf[j] = (tmp < min) ? min : ((tmp > max) ? max : tmp);
            }

            raster.setSamples(tOffx, tOffy + l, cTileWidth, 1, destinationBands[i], pixbuf);
          }
        }
      }
    } else {
      readSubsampledRaster(raster);
    }

    return raster;
  }