/**
   * Creates a copy of <code>param</code>. The source subsampling and and bands settings and the
   * destination bands and offset settings are copied. If <code>param</code> is a <code>
   * TIFFImageReadParam</code> then the <code>TIFFDecompressor</code> and <code>TIFFColorConverter
   * </code> settings are also copied; otherwise they are explicitly set to <code>null</code>.
   *
   * @param param the parameters to be copied.
   * @param copyTagSets whether the <code>TIFFTagSet</code> settings should be copied if set.
   * @return copied parameters.
   */
  private ImageReadParam cloneImageReadParam(ImageReadParam param, boolean copyTagSets) {
    // Create a new TIFFImageReadParam.
    TIFFImageReadParam newParam = new TIFFImageReadParam();

    // Copy the basic settings.
    newParam.setSourceSubsampling(
        param.getSourceXSubsampling(),
        param.getSourceYSubsampling(),
        param.getSubsamplingXOffset(),
        param.getSubsamplingYOffset());
    newParam.setSourceBands(param.getSourceBands());
    newParam.setDestinationBands(param.getDestinationBands());
    newParam.setDestinationOffset(param.getDestinationOffset());

    // Set the decompressor and color converter.
    if (param instanceof TIFFImageReadParam) {
      // Copy the settings from the input parameter.
      TIFFImageReadParam tparam = (TIFFImageReadParam) param;
      newParam.setTIFFDecompressor(tparam.getTIFFDecompressor());
      newParam.setColorConverter(tparam.getColorConverter());

      if (copyTagSets) {
        List tagSets = tparam.getAllowedTagSets();
        if (tagSets != null) {
          Iterator tagSetIter = tagSets.iterator();
          if (tagSetIter != null) {
            while (tagSetIter.hasNext()) {
              TIFFTagSet tagSet = (TIFFTagSet) tagSetIter.next();
              newParam.addAllowedTagSet(tagSet);
            }
          }
        }
      }
    } else {
      // Set the decompressor and color converter to null.
      newParam.setTIFFDecompressor(null);
      newParam.setColorConverter(null);
    }

    return newParam;
  }
  public RawRenderedImage(
      RawImageInputStream iis, RawImageReader reader, ImageReadParam param, int imageIndex)
      throws IOException {
    this.iis = iis;
    this.reader = reader;
    this.param = param;
    this.imageIndex = imageIndex;
    this.position = iis.getImageOffset(imageIndex);
    this.originalDimension = iis.getImageDimension(imageIndex);

    ImageTypeSpecifier type = iis.getImageType();
    sampleModel = originalSampleModel = type.getSampleModel();
    colorModel = type.getColorModel();

    // If the destination band is set used it
    sourceBands = (param == null) ? null : param.getSourceBands();

    if (sourceBands == null) {
      nComp = originalSampleModel.getNumBands();
      sourceBands = new int[nComp];
      for (int i = 0; i < nComp; i++) sourceBands[i] = i;
    } else {
      sampleModel = originalSampleModel.createSubsetSampleModel(sourceBands);
      colorModel = ImageUtil.createColorModel(null, sampleModel);
    }

    nComp = sourceBands.length;

    destinationBands = (param == null) ? null : param.getDestinationBands();
    if (destinationBands == null) {
      destinationBands = new int[nComp];
      for (int i = 0; i < nComp; i++) destinationBands[i] = i;
    }

    Dimension dim = iis.getImageDimension(imageIndex);
    this.width = dim.width;
    this.height = dim.height;

    Rectangle sourceRegion = new Rectangle(0, 0, this.width, this.height);

    originalRegion = (Rectangle) sourceRegion.clone();

    destinationRegion = (Rectangle) sourceRegion.clone();

    if (param != null) {
      RawImageReader.computeRegionsWrapper(
          param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion);
      scaleX = param.getSourceXSubsampling();
      scaleY = param.getSourceYSubsampling();
      xOffset = param.getSubsamplingXOffset();
      yOffset = param.getSubsamplingYOffset();
    }

    sourceOrigin = new Point(sourceRegion.x, sourceRegion.y);
    if (!destinationRegion.equals(sourceRegion)) noTransform = false;

    this.tileDataSize = ImageUtil.getTileSize(originalSampleModel);

    this.tileWidth = originalSampleModel.getWidth();
    this.tileHeight = originalSampleModel.getHeight();
    this.tileGridXOffset = destinationRegion.x;
    this.tileGridYOffset = destinationRegion.y;
    this.originalNumXTiles = getNumXTiles();

    this.width = destinationRegion.width;
    this.height = destinationRegion.height;
    this.minX = destinationRegion.x;
    this.minY = destinationRegion.y;

    sampleModel = sampleModel.createCompatibleSampleModel(tileWidth, tileHeight);

    maxXTile = originalDimension.width / tileWidth;
    maxYTile = originalDimension.height / tileHeight;
  }