/** * Paint the image onto a Graphics object. The painting is performed tile-by-tile, and includes a * grey region covering the unused portion of image tiles as well as the general background. At * this point the image must be byte data. */ public synchronized void paintComponent(Graphics g) { Graphics2D g2D = null; if (g instanceof Graphics2D) { g2D = (Graphics2D) g; } else { return; } // if source is null, it's just a component if (source == null) { g2D.setColor(getBackground()); g2D.fillRect(0, 0, componentWidth, componentHeight); return; } int transX = -originX; int transY = -originY; // Get the clipping rectangle and translate it into image coordinates. Rectangle clipBounds = g.getClipBounds(); if (clipBounds == null) { clipBounds = new Rectangle(0, 0, componentWidth, componentHeight); } // clear the background (clip it) [minimal optimization here] if (transX > 0 || transY > 0 || transX < (componentWidth - source.getWidth()) || transY < (componentHeight - source.getHeight())) { g2D.setColor(getBackground()); g2D.fillRect(0, 0, componentWidth, componentHeight); } clipBounds.translate(-transX, -transY); // Determine the extent of the clipping region in tile coordinates. int txmin, txmax, tymin, tymax; int ti, tj; txmin = XtoTileX(clipBounds.x); txmin = Math.max(txmin, minTileX); txmin = Math.min(txmin, maxTileX); txmax = XtoTileX(clipBounds.x + clipBounds.width - 1); txmax = Math.max(txmax, minTileX); txmax = Math.min(txmax, maxTileX); tymin = YtoTileY(clipBounds.y); tymin = Math.max(tymin, minTileY); tymin = Math.min(tymin, maxTileY); tymax = YtoTileY(clipBounds.y + clipBounds.height - 1); tymax = Math.max(tymax, minTileY); tymax = Math.min(tymax, maxTileY); Insets insets = getInsets(); // Loop over tiles within the clipping region for (tj = tymin; tj <= tymax; tj++) { for (ti = txmin; ti <= txmax; ti++) { int tx = TileXtoX(ti); int ty = TileYtoY(tj); Raster tile = source.getTile(ti, tj); if (tile != null) { DataBuffer dataBuffer = tile.getDataBuffer(); WritableRaster wr = tile.createWritableRaster(sampleModel, dataBuffer, null); BufferedImage bi = new BufferedImage(colorModel, wr, colorModel.isAlphaPremultiplied(), null); // correctly handles band offsets if (brightnessEnabled == true) { SampleModel sm = sampleModel.createCompatibleSampleModel(tile.getWidth(), tile.getHeight()); WritableRaster raster = RasterFactory.createWritableRaster(sm, null); BufferedImage bimg = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null); // don't move this code ByteLookupTable lutTable = new ByteLookupTable(0, lutData); LookupOp lookup = new LookupOp(lutTable, null); lookup.filter(bi, bimg); g2D.drawImage(bimg, biop, tx + transX + insets.left, ty + transY + insets.top); } else { AffineTransform transform; transform = AffineTransform.getTranslateInstance( tx + transX + insets.left, ty + transY + insets.top); g2D.drawRenderedImage(bi, transform); } } } } }
/** * {@collect.stats} Rescales the pixel data in the source Raster. If the destination Raster is * null, a new Raster will be created. The source and destination must have the same number of * bands. Otherwise, an IllegalArgumentException is thrown. Note that the number of scaling * factors/offsets in this object must meet the restrictions stated in the class comments above. * Otherwise, an IllegalArgumentException is thrown. * * @param src the <code>Raster</code> to be filtered * @param dst the destination for the filtering operation or <code>null</code> * @return the filtered <code>WritableRaster</code>. * @throws IllegalArgumentException if <code>src</code> and <code>dst</code> do not have the same * number of bands, or if the number of scaling factors and offsets in this <code>RescaleOp * </code> do not meet the requirements stated in the class comments. */ public final WritableRaster filter(Raster src, WritableRaster dst) { int numBands = src.getNumBands(); int width = src.getWidth(); int height = src.getHeight(); int[] srcPix = null; int step = 0; int tidx = 0; // Create a new destination Raster, if needed if (dst == null) { dst = createCompatibleDestRaster(src); } else if (height != dst.getHeight() || width != dst.getWidth()) { throw new IllegalArgumentException("Width or height of Rasters do not " + "match"); } else if (numBands != dst.getNumBands()) { // Make sure that the number of bands are equal throw new IllegalArgumentException( "Number of bands in src " + numBands + " does not equal number of bands in dest " + dst.getNumBands()); } // Make sure that the arrays match // Make sure that the low/high/constant arrays match if (length != 1 && length != src.getNumBands()) { throw new IllegalArgumentException( "Number of scaling constants " + "does not equal the number of" + " of bands in the src raster"); } // // Try for a native raster rescale first // if (ImagingLib.filter(this, src, dst) != null) { return dst; } // // Native raster rescale failed. // Try to see if a lookup operation can be used // if (canUseLookup(src, dst)) { int srcNgray = (1 << srcNbits); int dstNgray = (1 << dstNbits); if (dstNgray == 256) { ByteLookupTable lut = createByteLut( scaleFactors, offsets, numBands, srcNgray); LookupOp op = new LookupOp(lut, hints); op.filter(src, dst); } else { ShortLookupTable lut = createShortLut( scaleFactors, offsets, numBands, srcNgray); LookupOp op = new LookupOp(lut, hints); op.filter(src, dst); } } else { // // Fall back to the slow code // if (length > 1) { step = 1; } int sminX = src.getMinX(); int sY = src.getMinY(); int dminX = dst.getMinX(); int dY = dst.getMinY(); int sX; int dX; // // Determine bits per band to determine maxval for clamps. // The min is assumed to be zero. // REMIND: This must change if we ever support signed data types. // int nbits; int dstMax[] = new int[numBands]; int dstMask[] = new int[numBands]; SampleModel dstSM = dst.getSampleModel(); for (int z = 0; z < numBands; z++) { nbits = dstSM.getSampleSize(z); dstMax[z] = (1 << nbits) - 1; dstMask[z] = ~(dstMax[z]); } int val; for (int y = 0; y < height; y++, sY++, dY++) { dX = dminX; sX = sminX; for (int x = 0; x < width; x++, sX++, dX++) { // Get data for all bands at this x,y position srcPix = src.getPixel(sX, sY, srcPix); tidx = 0; for (int z = 0; z < numBands; z++, tidx += step) { val = (int) (srcPix[z] * scaleFactors[tidx] + offsets[tidx]); // Clamp if ((val & dstMask[z]) != 0) { if (val < 0) { val = 0; } else { val = dstMax[z]; } } srcPix[z] = val; } // Put it back for all bands dst.setPixel(dX, dY, srcPix); } } } return dst; }