예제 #1
0
  private Raster readSubsampledRaster(WritableRaster raster) throws IOException {
    if (raster == null)
      raster =
          Raster.createWritableRaster(
              sampleModel.createCompatibleSampleModel(
                  destinationRegion.x + destinationRegion.width,
                  destinationRegion.y + destinationRegion.height),
              new Point(destinationRegion.x, destinationRegion.y));

    int pixbuf[] = null; // line buffer for pixel data
    boolean prog = false; // Flag for progressive data
    Point nT = ictransf.getNumTiles(null);
    int numBands = sourceBands.length;

    Rectangle destRect = raster.getBounds().intersection(destinationRegion);

    int offx = destinationRegion.x;
    int offy = destinationRegion.y;

    int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x;
    int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y;
    int sourceEX = (destRect.width - 1) * scaleX + sourceSX;
    int sourceEY = (destRect.height - 1) * scaleY + sourceSY;

    int startXTile = (sourceSX - tileXOffset) / tileWidth;
    int startYTile = (sourceSY - tileYOffset) / tileHeight;
    int endXTile = (sourceEX - tileXOffset) / tileWidth;
    int endYTile = (sourceEY - tileYOffset) / tileHeight;

    startXTile = clip(startXTile, 0, nT.x - 1);
    startYTile = clip(startYTile, 0, nT.y - 1);
    endXTile = clip(endXTile, 0, nT.x - 1);
    endYTile = clip(endYTile, 0, nT.y - 1);

    int totalXTiles = endXTile - startXTile + 1;
    int totalYTiles = endYTile - startYTile + 1;
    int totalTiles = totalXTiles * totalYTiles;

    // Start the data delivery to the cached consumers tile by tile
    for (int y = startYTile; y <= endYTile; y++) {
      if (reader.getAbortRequest()) break;

      // Loop on horizontal tiles
      for (int x = startXTile; x <= endXTile; x++) {
        if (reader.getAbortRequest()) break;

        float initialFraction = (x - startXTile + (y - startYTile) * totalXTiles) / totalTiles;

        ictransf.setTile(x * tileStepX, y * tileStepY);

        int sx = hd.getCompSubsX(0);
        int cTileWidth = (ictransf.getTileWidth() + sx - 1) / sx;
        int sy = hd.getCompSubsY(0);
        int cTileHeight = (ictransf.getTileHeight() + sy - 1) / sy;

        // Offsets within the tile.
        int tx = 0;
        int ty = 0;

        // The region for this tile
        int startX = tileXOffset + x * tileWidth;
        int startY = tileYOffset + y * tileHeight;

        // sourceSX is guaranteed to be >= startX
        if (sourceSX > startX) {
          if (startX >= hd.getImgULX()) {
            tx = sourceSX - startX; // Intra-tile offset.
            cTileWidth -= tx; // Reduce effective width.
          }
          startX = sourceSX; // Absolute position.
        }

        // sourceSY is guaranteed to be >= startY
        if (sourceSY > startY) {
          if (startY >= hd.getImgULY()) {
            ty = sourceSY - startY; // Intra-tile offset.
            cTileHeight -= ty; // Reduce effective width.
          }
          startY = sourceSY; // Absolute position.
        }

        // Decrement dimensions if end position is within tile.
        if (sourceEX < startX + cTileWidth - 1) {
          cTileWidth += sourceEX - startX - cTileWidth + 1;
        }
        if (sourceEY < startY + cTileHeight - 1) {
          cTileHeight += sourceEY - startY - cTileHeight + 1;
        }

        // The start X in the destination
        int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX;
        int x2 = (startX + scaleX - 1 + cTileWidth - sourceOrigin.x) / scaleX;
        int lineLength = x2 - x1;
        if (pixbuf == null || pixbuf.length < lineLength)
          pixbuf = new int[lineLength]; // line buffer for pixel data
        x2 = (x2 - 1) * scaleX + sourceOrigin.x - startX;

        int y1 = (startY + scaleY - 1 - sourceOrigin.y) / scaleY;

        x1 += offx;
        y1 += offy;

        // check to see if we have YCbCr data
        boolean ycbcr = false;

        for (int i = 0; i < numBands; i++) {
          DataBlkInt db = dataBlocks[i];
          db.ulx = tx;
          db.uly = ty + cTileHeight - 1;
          db.w = cTileWidth;
          db.h = 1;

          try {
            ictransf.getInternCompData(db, channelMap[sourceBands[i]]);
          } catch (ArrayIndexOutOfBoundsException e) {
            ycbcr = true;
            break;
          }
        }

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

          if (ycbcr) {
            DataBlkInt lum = dataBlocks[0];
            DataBlkInt cb = dataBlocks[1];
            DataBlkInt cr = dataBlocks[2];

            lum.ulx = tx;
            lum.uly = l;
            lum.w = cTileWidth;
            lum.h = 1;
            ictransf.getInternCompData(lum, channelMap[sourceBands[0]]);
            prog = prog || lum.progressive;

            cb.ulx = tx;
            cb.uly = l;
            cb.w = cTileWidth / 2;
            cb.h = 1;
            ictransf.getInternCompData(cb, channelMap[sourceBands[1]]);
            prog = prog || cb.progressive;

            cr.ulx = tx;
            cr.uly = l;
            cr.w = cTileWidth / 2;
            cr.h = 1;
            ictransf.getInternCompData(cr, channelMap[sourceBands[2]]);
            prog = prog || cr.progressive;

            int[] lumdata = lum.data;
            int[] cbdata = cb.data;
            int[] crdata = cr.data;

            int k1 = lum.offset + x2;

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

            int[][] pix = new int[3][lineLength];

            for (int j = lineLength - 1; j >= 0; j--, k1 -= scaleX) {
              int red = (lumdata[k1] >> fracBit) + lS;
              red = (red < min) ? min : ((red > max) ? max : red);

              int cIndex = k1 / 2;

              int chrom1 = cbdata[cIndex];
              int chrom2 = crdata[cIndex];
              int lumval = red;

              red = (int) (chrom2 * 1.542 + lumval);
              int blue = (int) (lumval + 1.772 * chrom1 - 0.886);
              int green = (int) (lumval - 0.34413 * chrom1 - 0.71414 * chrom2 - 0.1228785);

              if (red > 255) red = 255;
              if (green > 255) green = 255;
              if (blue > 255) blue = 255;

              if (red < 0) red = 0;
              if (green < 0) green = 0;
              if (blue < 0) blue = 0;

              pix[0][j] = red;
              pix[1][j] = green;
              pix[2][j] = blue;
            }

            raster.setSamples(x1, m, lineLength, 1, destinationBands[0], pix[0]);
            raster.setSamples(x1, m, lineLength, 1, destinationBands[1], pix[1]);
            raster.setSamples(x1, m, lineLength, 1, destinationBands[2], pix[2]);

            continue;
          }

          // Request line data
          for (int i = 0; i < numBands; i++) {
            DataBlkInt db = dataBlocks[i];
            db.ulx = tx;
            db.uly = l;
            db.w = ycbcr && i > 0 ? cTileWidth / 2 : cTileWidth;
            db.h = 1;
            ictransf.getInternCompData(db, channelMap[sourceBands[i]]);
            prog = prog || db.progressive;

            int[] data = db.data;
            int k1 = db.offset + x2;

            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 = lineLength - 1; j >= 0; j--, k1 -= scaleX) {
                int tmp = (data[k1] >> fracBit) + lS;
                bytebuf[j] = (byte) ((tmp < min) ? min : ((tmp > max) ? max : tmp));
              }

              ImageUtil.setUnpackedBinaryData(bytebuf, raster, new Rectangle(x1, m, lineLength, 1));
            } else {
              for (int j = lineLength - 1; j >= 0; j--, k1 -= scaleX) {
                int tmp = (data[k1] >> fracBit) + lS;
                pixbuf[j] = (tmp < min) ? min : ((tmp > max) ? max : tmp);
              }

              // Send the line data to the BufferedImage
              raster.setSamples(x1, m, lineLength, 1, destinationBands[i], pixbuf);
            }
          }

          if (destImage != null)
            reader.processImageUpdateWrapper(
                destImage, x1, m, cTileWidth, 1, 1, 1, destinationBands);

          float fraction = initialFraction + (l - ty + 1.0F) / cTileHeight / totalTiles;
          reader.processImageProgressWrapper(100.0f * fraction);
        }
      } // End loop on horizontal tiles
    } // End loop on vertical tiles

    return raster;
  }
예제 #2
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;
  }