Esempio n. 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;
  }