public RenderedImage createRendering(RenderContext rc) { // // Get the mask content // Filter maskSrc = getMaskNode().getGraphicsNodeRable(true); PadRable maskPad = new PadRable8Bit(maskSrc, getBounds2D(), PadMode.ZERO_PAD); maskSrc = new FilterAsAlphaRable(maskPad); RenderedImage ri = maskSrc.createRendering(rc); if (ri == null) return null; CachableRed maskCr = RenderedImageCachableRed.wrap(ri); // // Get the masked content // PadRable maskedPad = new PadRable8Bit(getSource(), getBounds2D(), PadMode.ZERO_PAD); ri = maskedPad.createRendering(rc); if (ri == null) return null; CachableRed cr; cr = GraphicsUtil.wrap(ri); cr = GraphicsUtil.convertToLsRGB(cr); // org.apache.batik.test.gvt.ImageDisplay.showImage("Src: ", cr); // org.apache.batik.test.gvt.ImageDisplay.showImage("Mask: ", maskCr); CachableRed ret = new MultiplyAlphaRed(cr, maskCr); // org.apache.batik.test.gvt.ImageDisplay.showImage("Masked: ", ret); // ret = new PadRed(ret, cr.getBounds(), PadMode.ZERO_PAD, rh); return ret; }
/** * Builds a new BufferedImage that is the difference between the two input images * * @param ref the reference bitmap * @param gen the newly generated bitmap * @return the diff bitmap */ public static BufferedImage buildDiffImage(BufferedImage ref, BufferedImage gen) { BufferedImage diff = new BufferedImage(ref.getWidth(), ref.getHeight(), BufferedImage.TYPE_INT_ARGB); WritableRaster refWR = ref.getRaster(); WritableRaster genWR = gen.getRaster(); WritableRaster dstWR = diff.getRaster(); boolean refPre = ref.isAlphaPremultiplied(); if (!refPre) { ColorModel cm = ref.getColorModel(); cm = GraphicsUtil.coerceData(refWR, cm, true); ref = new BufferedImage(cm, refWR, true, null); } boolean genPre = gen.isAlphaPremultiplied(); if (!genPre) { ColorModel cm = gen.getColorModel(); cm = GraphicsUtil.coerceData(genWR, cm, true); gen = new BufferedImage(cm, genWR, true, null); } int w = ref.getWidth(); int h = ref.getHeight(); int y, i, val; int[] refPix = null; int[] genPix = null; for (y = 0; y < h; y++) { refPix = refWR.getPixels(0, y, w, 1, refPix); genPix = genWR.getPixels(0, y, w, 1, genPix); for (i = 0; i < refPix.length; i++) { // val = ((genPix[i] - refPix[i]) * 5) + 128; val = ((refPix[i] - genPix[i]) * 10) + 128; if ((val & 0xFFFFFF00) != 0) { if ((val & 0x80000000) != 0) { val = 0; } else { val = 255; } } genPix[i] = val; } dstWR.setPixels(0, y, w, 1, genPix); } if (!genPre) { ColorModel cm = gen.getColorModel(); cm = GraphicsUtil.coerceData(genWR, cm, false); } if (!refPre) { ColorModel cm = ref.getColorModel(); cm = GraphicsUtil.coerceData(refWR, cm, false); } return diff; }
/** Superclass getRaster... */ public final Raster getRaster(int x, int y, int w, int h) { if (w == 0 || h == 0) { return null; } // // If working raster is big enough, reuse it. Otherwise, // build a large enough new one. // WritableRaster raster = saved; if (raster == null || raster.getWidth() < w || raster.getHeight() < h) { raster = getCachedRaster(dataModel, w, h); saved = raster; } // Access raster internal int array. Because we use a DirectColorModel, // we know the DataBuffer is of type DataBufferInt and the SampleModel // is SinglePixelPackedSampleModel. // Adjust for initial offset in DataBuffer and also for the scanline // stride. // DataBufferInt rasterDB = (DataBufferInt) raster.getDataBuffer(); int[] pixels = rasterDB.getBankData()[0]; int off = rasterDB.getOffset(); int scanlineStride = ((SinglePixelPackedSampleModel) raster.getSampleModel()).getScanlineStride(); int adjust = scanlineStride - w; fillRaster(pixels, off, adjust, x, y, w, h); // delegate to subclass. GraphicsUtil.coerceData(raster, dataModel, model.isAlphaPremultiplied()); return raster; }
/** * Construct a fully transparent image <tt>bounds</tt> size, will paint one tile with paint. Thus * paint should not be a pattered paint or gradient but should be a solid color. * * @param bounds the bounds of the image (in fact will respond with any request). */ public FloodRed(Rectangle bounds, Paint paint) { super(); // We _must_ call init... ColorModel cm = GraphicsUtil.sRGB_Unpre; int defSz = AbstractTiledRed.getDefaultTileSize(); int tw = bounds.width; if (tw > defSz) tw = defSz; int th = bounds.height; if (th > defSz) th = defSz; // fix my sample model so it makes sense given my size. SampleModel sm = cm.createCompatibleSampleModel(tw, th); // Finish initializing our base class... init((CachableRed) null, bounds, cm, sm, 0, 0, null); raster = Raster.createWritableRaster(sm, new Point(0, 0)); BufferedImage offScreen = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); Graphics2D g = GraphicsUtil.createGraphics(offScreen); g.setPaint(paint); g.fillRect(0, 0, bounds.width, bounds.height); g.dispose(); }
protected static ColorModel fixColorModel(CachableRed src) { ColorModel cm = src.getColorModel(); if (cm.hasAlpha()) { if (!cm.isAlphaPremultiplied()) cm = GraphicsUtil.coerceColorModel(cm, true); return cm; } ColorSpace cs = cm.getColorSpace(); int b = src.getSampleModel().getNumBands() + 1; if (b == 4) { int[] masks = new int[4]; for (int i = 0; i < b - 1; i++) masks[i] = 0xFF0000 >> (8 * i); masks[3] = 0xFF << (8 * (b - 1)); return new DirectColorModel( cs, 8 * b, masks[0], masks[1], masks[2], masks[3], true, DataBuffer.TYPE_INT); } int[] bits = new int[b]; for (int i = 0; i < b; i++) bits[i] = 8; return new ComponentColorModel( cs, bits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_INT); }
public WritableRaster copyData(WritableRaster wr) { int tx0 = getXTile(wr.getMinX()); int ty0 = getYTile(wr.getMinY()); int tx1 = getXTile(wr.getMinX() + wr.getWidth() - 1); int ty1 = getYTile(wr.getMinY() + wr.getHeight() - 1); final boolean is_INT_PACK = GraphicsUtil.is_INT_PACK_Data(getSampleModel(), false); for (int y = ty0; y <= ty1; y++) for (int x = tx0; x <= tx1; x++) { Raster r = getTile(x, y); if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(r, wr); else GraphicsUtil.copyData_FALLBACK(r, wr); } return wr; }
/** * Copies data from this images tile grid into wr. wr may extend outside the bounds of this image * in which case the data in wr outside the bounds will not be touched. * * @param wr Raster to fill with image data. */ public void copyToRaster(WritableRaster wr) { Rectangle wrR = wr.getBounds(); int tx0 = getXTile(wrR.x); int ty0 = getYTile(wrR.y); int tx1 = getXTile(wrR.x + wrR.width - 1); int ty1 = getYTile(wrR.y + wrR.height - 1); if (tx0 < minTileX) tx0 = minTileX; if (ty0 < minTileY) ty0 = minTileY; if (tx1 >= minTileX + numXTiles) tx1 = minTileX + numXTiles - 1; if (ty1 >= minTileY + numYTiles) ty1 = minTileY + numYTiles - 1; final boolean is_INT_PACK = GraphicsUtil.is_INT_PACK_Data(getSampleModel(), false); int xtiles = (tx1 - tx0 + 1); boolean[] got = new boolean[xtiles * (ty1 - ty0 + 1)]; // Run through and get the tiles that are just sitting in the // cache... for (int y = ty0; y <= ty1; y++) for (int x = tx0; x <= tx1; x++) { Raster r = tiles.getTileNoCompute(x, y); if (r == null) continue; // Not there. got[x - tx0 + (y - ty0) * xtiles] = true; if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(r, wr); else GraphicsUtil.copyData_FALLBACK(r, wr); } // Run through and pick up the ones we need to compute... for (int y = ty0; y <= ty1; y++) for (int x = tx0; x <= tx1; x++) { if (got[x - tx0 + (y - ty0) * xtiles]) continue; // already have. Raster r = getTile(x, y); if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(r, wr); else GraphicsUtil.copyData_FALLBACK(r, wr); } }
protected void drawBlockAndCopy(TileBlock[] blocks, WritableRaster wr) { if (blocks.length == 1) { TileBlock curr = blocks[0]; int xloc = curr.getXLoc() * tileWidth + tileGridXOff; int yloc = curr.getYLoc() * tileHeight + tileGridYOff; if ((xloc == wr.getMinX()) && (yloc == wr.getMinY())) { // Safe to draw in place... drawBlockInPlace(blocks, wr); return; } } int maxSz = 0; for (int i = 0; i < blocks.length; i++) { int sz = ((blocks[i].getWidth() * tileWidth) * (blocks[i].getHeight() * tileHeight)); if (sz > maxSz) maxSz = sz; } DataBufferInt dbi = new DataBufferInt(maxSz); int[] masks = {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}; boolean use_INT_PACK = GraphicsUtil.is_INT_PACK_Data(wr.getSampleModel(), false); for (int i = 0; i < blocks.length; i++) { TileBlock curr = blocks[i]; int xloc = curr.getXLoc() * tileWidth + tileGridXOff; int yloc = curr.getYLoc() * tileHeight + tileGridYOff; Rectangle tb = new Rectangle(xloc, yloc, curr.getWidth() * tileWidth, curr.getHeight() * tileHeight); tb = tb.intersection(bounds); Point loc = new Point(tb.x, tb.y); WritableRaster child = Raster.createPackedRaster(dbi, tb.width, tb.height, tb.width, masks, loc); genRect(child); if (use_INT_PACK) GraphicsUtil.copyData_INT_PACK(child, wr); else GraphicsUtil.copyData_FALLBACK(child, wr); if (Thread.currentThread().isInterrupted()) return; } }
/** * @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream, * org.apache.batik.ext.awt.image.spi.ImageWriterParams) */ public void writeImage(RenderedImage image, OutputStream out, ImageWriterParams params) throws IOException { BufferedImage bi; if (image instanceof BufferedImage) { bi = (BufferedImage) image; } else { // TODO Is this the right way? bi = GraphicsUtil.makeLinearBufferedImage(image.getWidth(), image.getHeight(), false); } JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); if (params != null) { JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); if (params.getJPEGQuality() != null) { param.setQuality( params.getJPEGQuality().floatValue(), params.getJPEGForceBaseline().booleanValue()); } encoder.encode(bi, param); } else { encoder.encode(bi); } }
/** * Constructor for superclass. Does some initialization, but leaves most of the heavy-duty math * for calculateGradient(), so the subclass may do some other manipulation beforehand if * necessary. This is not possible if this computation is done in the superclass constructor which * always gets called first. */ public MultipleGradientPaintContext( ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform t, RenderingHints hints, float[] fractions, Color[] colors, MultipleGradientPaint.CycleMethodEnum cycleMethod, MultipleGradientPaint.ColorSpaceEnum colorSpace) throws NoninvertibleTransformException { // We have to deal with the cases where the 1st gradient stop is not // equal to 0 and/or the last gradient stop is not equal to 1. // In both cases, create a new point and replicate the previous // extreme point's color. boolean fixFirst = false; boolean fixLast = false; int len = fractions.length; // if the first gradient stop is not equal to zero, fix this condition if (fractions[0] != 0f) { fixFirst = true; len++; } // if the last gradient stop is not equal to one, fix this condition if (fractions[fractions.length - 1] != 1f) { fixLast = true; len++; } for (int i = 0; i < fractions.length - 1; i++) if (fractions[i] == fractions[i + 1]) len--; this.fractions = new float[len]; Color[] loColors = new Color[len - 1]; Color[] hiColors = new Color[len - 1]; normalizedIntervals = new float[len - 1]; gradientUnderflow = colors[0].getRGB(); gradientOverflow = colors[colors.length - 1].getRGB(); int idx = 0; if (fixFirst) { this.fractions[0] = 0; loColors[0] = colors[0]; hiColors[0] = colors[0]; normalizedIntervals[0] = fractions[0]; idx++; } for (int i = 0; i < fractions.length - 1; i++) { if (fractions[i] == fractions[i + 1]) { // System.out.println("EQ Fracts"); if (!colors[i].equals(colors[i + 1])) { hasDiscontinuity = true; } continue; } this.fractions[idx] = fractions[i]; loColors[idx] = colors[i]; hiColors[idx] = colors[i + 1]; normalizedIntervals[idx] = fractions[i + 1] - fractions[i]; idx++; } this.fractions[idx] = fractions[fractions.length - 1]; if (fixLast) { loColors[idx] = hiColors[idx] = colors[colors.length - 1]; normalizedIntervals[idx] = 1 - fractions[fractions.length - 1]; idx++; this.fractions[idx] = 1; } // The inverse transform is needed to from device to user space. // Get all the components of the inverse transform matrix. AffineTransform tInv = t.createInverse(); double m[] = new double[6]; tInv.getMatrix(m); a00 = (float) m[0]; a10 = (float) m[1]; a01 = (float) m[2]; a11 = (float) m[3]; a02 = (float) m[4]; a12 = (float) m[5]; // copy some flags this.cycleMethod = cycleMethod; this.colorSpace = colorSpace; // PATCH Werner Randelshofer: ColorModel can be null! // Setup an example Model, we may refine it later. if (cm != null && cm.getColorSpace() == lrgbmodel_A.getColorSpace()) dataModel = lrgbmodel_A; else if (cm == null || cm.getColorSpace() == srgbmodel_A.getColorSpace()) dataModel = srgbmodel_A; else throw new IllegalArgumentException("Unsupported ColorSpace for interpolation"); calculateGradientFractions(loColors, hiColors); model = GraphicsUtil.coerceColorModel(dataModel, cm != null && cm.isAlphaPremultiplied()); }
public WritableRaster copyData(WritableRaster wr) { // Get my source. CachableRed src = (CachableRed) getSources().get(0); Rectangle r = wr.getBounds(); r.x -= xinset; r.y -= yinset; r.width += 2 * xinset; r.height += 2 * yinset; // System.out.println("Gaussian GenR: " + wr); // System.out.println("SrcReq: " + r); ColorModel srcCM = src.getColorModel(); WritableRaster tmpR1 = null, tmpR2 = null; tmpR1 = srcCM.createCompatibleWritableRaster(r.width, r.height); { WritableRaster fill; fill = tmpR1.createWritableTranslatedChild(r.x, r.y); src.copyData(fill); } if (srcCM.hasAlpha() && !srcCM.isAlphaPremultiplied()) GraphicsUtil.coerceData(tmpR1, srcCM, true); // For the blur box approx we can use dest as our intermediate // otherwise we let it default to null which means we create a new // one... // this lets the Vertical conv know how much is junk, so it // doesn't bother to convolve the top and bottom edges int skipX; // long t1 = System.currentTimeMillis(); if (xinset == 0) { skipX = 0; } else if (convOp[0] != null) { tmpR2 = getColorModel().createCompatibleWritableRaster(r.width, r.height); tmpR2 = convOp[0].filter(tmpR1, tmpR2); skipX = convOp[0].getKernel().getXOrigin(); // Swap them... WritableRaster tmp = tmpR1; tmpR1 = tmpR2; tmpR2 = tmp; } else { if ((dX & 0x01) == 0) { tmpR1 = boxFilterH(tmpR1, tmpR1, 0, 0, dX, dX / 2); tmpR1 = boxFilterH(tmpR1, tmpR1, dX / 2, 0, dX, dX / 2 - 1); tmpR1 = boxFilterH(tmpR1, tmpR1, dX - 1, 0, dX + 1, dX / 2); skipX = dX - 1 + dX / 2; } else { tmpR1 = boxFilterH(tmpR1, tmpR1, 0, 0, dX, dX / 2); tmpR1 = boxFilterH(tmpR1, tmpR1, dX / 2, 0, dX, dX / 2); tmpR1 = boxFilterH(tmpR1, tmpR1, dX - 2, 0, dX, dX / 2); skipX = dX - 2 + dX / 2; } } if (yinset == 0) { tmpR2 = tmpR1; } else if (convOp[1] != null) { if (tmpR2 == null) { tmpR2 = getColorModel().createCompatibleWritableRaster(r.width, r.height); } tmpR2 = convOp[1].filter(tmpR1, tmpR2); } else { if ((dY & 0x01) == 0) { tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, 0, dY, dY / 2); tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, dY / 2, dY, dY / 2 - 1); tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, dY - 1, dY + 1, dY / 2); } else { tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, 0, dY, dY / 2); tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, dY / 2, dY, dY / 2); tmpR1 = boxFilterV(tmpR1, tmpR1, skipX, dY - 2, dY, dY / 2); } tmpR2 = tmpR1; } // long t2 = System.currentTimeMillis(); // System.out.println("Time: " + (t2-t1) + // (((convOp[0] != null) || (convOp[1] != null))? // " ConvOp":"")); // System.out.println("Rasters WR :" + wr.getBounds()); // System.out.println(" tmp:" + tmpR2.getBounds()); // System.out.println(" bounds:" + getBounds()); // System.out.println(" skipX:" + skipX + // " dx:" + dX + " Dy: " + dY); tmpR2 = tmpR2.createWritableTranslatedChild(r.x, r.y); GraphicsUtil.copyData(tmpR2, wr); return wr; }
public WritableRaster copyData(WritableRaster wr) { // Get my source. CachableRed src = (CachableRed) getSources().get(0); ColorModel srcCM = src.getColorModel(); SampleModel srcSM = src.getSampleModel(); // Fast case, SRGB source, INT Pack writable raster... if (srcIssRGB && Any2sRGBRed.is_INT_PACK_COMP(wr.getSampleModel())) { src.copyData(wr); if (srcCM.hasAlpha()) GraphicsUtil.coerceData(wr, srcCM, false); Any2sRGBRed.applyLut_INT(wr, sRGBToLsRGBLut); return wr; } if (srcCM == null) { // We don't really know much about this source, let's // guess based on the number of bands... float[][] matrix = null; switch (srcSM.getNumBands()) { case 1: matrix = new float[1][3]; matrix[0][0] = 1; // Red matrix[0][1] = 1; // Grn matrix[0][2] = 1; // Blu break; case 2: matrix = new float[2][4]; matrix[0][0] = 1; // Red matrix[0][1] = 1; // Grn matrix[0][2] = 1; // Blu matrix[1][3] = 1; // Alpha break; case 3: matrix = new float[3][3]; matrix[0][0] = 1; // Red matrix[1][1] = 1; // Grn matrix[2][2] = 1; // Blu break; default: matrix = new float[srcSM.getNumBands()][4]; matrix[0][0] = 1; // Red matrix[1][1] = 1; // Grn matrix[2][2] = 1; // Blu matrix[3][3] = 1; // Alpha break; } Raster srcRas = src.getData(wr.getBounds()); BandCombineOp op = new BandCombineOp(matrix, null); op.filter(srcRas, wr); } else { ColorModel dstCM = getColorModel(); BufferedImage dstBI; if (!dstCM.hasAlpha()) { // No alpha ao we don't have to work around the bug // in the color convert op. dstBI = new BufferedImage( dstCM, wr.createWritableTranslatedChild(0, 0), dstCM.isAlphaPremultiplied(), null); } else { // All this nonsense is to work around the fact that // the Color convert op doesn't properly copy the // Alpha from src to dst. SinglePixelPackedSampleModel dstSM; dstSM = (SinglePixelPackedSampleModel) wr.getSampleModel(); int[] masks = dstSM.getBitMasks(); SampleModel dstSMNoA = new SinglePixelPackedSampleModel( dstSM.getDataType(), dstSM.getWidth(), dstSM.getHeight(), dstSM.getScanlineStride(), new int[] {masks[0], masks[1], masks[2]}); ColorModel dstCMNoA = GraphicsUtil.Linear_sRGB; WritableRaster dstWr; dstWr = Raster.createWritableRaster(dstSMNoA, wr.getDataBuffer(), new Point(0, 0)); dstWr = dstWr.createWritableChild( wr.getMinX() - wr.getSampleModelTranslateX(), wr.getMinY() - wr.getSampleModelTranslateY(), wr.getWidth(), wr.getHeight(), 0, 0, null); dstBI = new BufferedImage(dstCMNoA, dstWr, false, null); } // Divide out alpha if we have it. We need to do this since // the color convert may not be a linear operation which may // lead to out of range values. ColorModel srcBICM = srcCM; WritableRaster srcWr; if ((srcCM.hasAlpha() == true) && (srcCM.isAlphaPremultiplied() != false)) { Rectangle wrR = wr.getBounds(); SampleModel sm = srcCM.createCompatibleSampleModel(wrR.width, wrR.height); srcWr = Raster.createWritableRaster(sm, new Point(wrR.x, wrR.y)); src.copyData(srcWr); srcBICM = GraphicsUtil.coerceData(srcWr, srcCM, false); } else { Raster srcRas = src.getData(wr.getBounds()); srcWr = GraphicsUtil.makeRasterWritable(srcRas); } BufferedImage srcBI; srcBI = new BufferedImage(srcBICM, srcWr.createWritableTranslatedChild(0, 0), false, null); /* * System.out.println("src: " + srcBI.getWidth() + "x" + * srcBI.getHeight()); * System.out.println("dst: " + dstBI.getWidth() + "x" + * dstBI.getHeight()); */ ColorConvertOp op = new ColorConvertOp(null); op.filter(srcBI, dstBI); if (dstCM.hasAlpha()) copyBand( srcWr, srcSM.getNumBands() - 1, wr, getSampleModel().getNumBands() - 1); } return wr; }
public void genRect(WritableRaster wr) { if (me2src == null) return; Rectangle srcR = me2src.createTransformedShape(wr.getBounds()).getBounds(); // System.out.println("Affine wrR: " + wr.getBounds()); // System.out.println("Affine srcR: " + srcR); // Outset by two pixels so we get context for interpolation... srcR.setBounds(srcR.x - 1, srcR.y - 1, srcR.width + 2, srcR.height + 2); // Don't try and get data from src that it doesn't have... CachableRed src = (CachableRed) getSources().get(0); // Raster srcRas = src.getData(srcR); if (!srcR.intersects(src.getBounds())) return; Raster srcRas = src.getData(srcR.intersection(src.getBounds())); if (srcRas == null) return; // This works around the problem that the buffered ops // completely ignore the coords of the Rasters passed in. AffineTransform aff = (AffineTransform) src2me.clone(); // Translate what is at 0,0 (which will be what our current // minX/Y is) to our current minX,minY. aff.concatenate(AffineTransform.getTranslateInstance(srcRas.getMinX(), srcRas.getMinY())); Point2D srcPt = new Point2D.Float(wr.getMinX(), wr.getMinY()); srcPt = me2src.transform(srcPt, null); Point2D destPt = new Point2D.Double(srcPt.getX() - srcRas.getMinX(), srcPt.getY() - srcRas.getMinY()); destPt = aff.transform(destPt, null); // Translate what will be at minX,minY to zero, zero // which where java2d will think the real minX,minY is. aff.preConcatenate(AffineTransform.getTranslateInstance(-destPt.getX(), -destPt.getY())); AffineTransformOp op = new AffineTransformOp(aff, hints); BufferedImage srcBI, myBI; ColorModel srcCM = src.getColorModel(); ColorModel myCM = getColorModel(); WritableRaster srcWR = (WritableRaster) srcRas; // If the output buffer is not premultiplied in certain cases // it fails to properly divide out the Alpha (it always does // the affine on premultiplied data). We help it out by // premultiplying for it. srcCM = GraphicsUtil.coerceData(srcWR, srcCM, true); srcBI = new BufferedImage( srcCM, srcWR.createWritableTranslatedChild(0, 0), srcCM.isAlphaPremultiplied(), null); myBI = new BufferedImage( myCM, wr.createWritableTranslatedChild(0, 0), myCM.isAlphaPremultiplied(), null); op.filter(srcBI, myBI); // if ((count % 40) == 0) { // org.apache.batik.ImageDisplay.showImage("Src: " , srcBI); // org.apache.batik.ImageDisplay.showImage("Dst: " , myBI); // } // count++; }
// long lastFrame = -1; public void repaint(RectListManager devRLM) { if (devRLM == null) return; updateWorkingBuffers(); if ((rootGN == null) || (workImg == null)) return; try { // Ensure only one thread works on WorkImg at a time... synchronized (workImg) { Graphics2D g2d = GraphicsUtil.createGraphics(workImg, renderingHints); Rectangle dr; dr = new Rectangle(0, 0, offScreenWidth, offScreenHeight); if ((isDoubleBuffered) && (currImg != null) && (damagedAreas != null)) { damagedAreas.subtract(devRLM, COPY_OVERHEAD, COPY_LINE_OVERHEAD); damagedAreas.mergeRects(COPY_OVERHEAD, COPY_LINE_OVERHEAD); Iterator iter = damagedAreas.iterator(); g2d.setComposite(AlphaComposite.Src); while (iter.hasNext()) { Rectangle r = (Rectangle) iter.next(); if (!dr.intersects(r)) continue; r = dr.intersection(r); g2d.setClip(r.x, r.y, r.width, r.height); g2d.setComposite(AlphaComposite.Clear); g2d.fillRect(r.x, r.y, r.width, r.height); g2d.setComposite(AlphaComposite.SrcOver); g2d.drawImage(currImg, 0, 0, null); } } Iterator iter = devRLM.iterator(); while (iter.hasNext()) { Rectangle r = (Rectangle) iter.next(); if (!dr.intersects(r)) continue; r = dr.intersection(r); g2d.setTransform(IDENTITY); g2d.setClip(r.x, r.y, r.width, r.height); g2d.setComposite(AlphaComposite.Clear); g2d.fillRect(r.x, r.y, r.width, r.height); g2d.setComposite(AlphaComposite.SrcOver); g2d.transform(usr2dev); rootGN.paint(g2d); } g2d.dispose(); } } catch (Throwable t) { t.printStackTrace(); } if (HaltingThread.hasBeenHalted()) return; // System.out.println("Dmg: " + damagedAreas); // System.out.println("Areas: " + devRects); // Swap the buffers if the rendering completed cleanly. if (isDoubleBuffered) { BufferedImage tmpImg = workImg; workImg = currImg; currImg = tmpImg; damagedAreas = devRLM; } }
public void copyToRasterByBlocks(WritableRaster wr) { final boolean is_INT_PACK = GraphicsUtil.is_INT_PACK_Data(getSampleModel(), false); Rectangle bounds = getBounds(); Rectangle wrR = wr.getBounds(); int tx0 = getXTile(wrR.x); int ty0 = getYTile(wrR.y); int tx1 = getXTile(wrR.x + wrR.width - 1); int ty1 = getYTile(wrR.y + wrR.height - 1); if (tx0 < minTileX) tx0 = minTileX; if (ty0 < minTileY) ty0 = minTileY; if (tx1 >= minTileX + numXTiles) tx1 = minTileX + numXTiles - 1; if (ty1 >= minTileY + numYTiles) ty1 = minTileY + numYTiles - 1; if ((tx1 < tx0) || (ty1 < ty0)) return; // System.out.println("WR: " + wrR); // System.out.println("ME: " + bounds); int insideTx0 = tx0; int insideTx1 = tx1; int insideTy0 = ty0; int insideTy1 = ty1; // Now figure out what tiles lie completely inside wr... int tx, ty; tx = tx0 * tileWidth + tileGridXOff; if ((tx < wrR.x) && (bounds.x != wrR.x)) // Partial tile off the left. insideTx0++; ty = ty0 * tileHeight + tileGridYOff; if ((ty < wrR.y) && (bounds.y != wrR.y)) // Partial tile off the top. insideTy0++; tx = (tx1 + 1) * tileWidth + tileGridXOff - 1; if ((tx >= (wrR.x + wrR.width)) && ((bounds.x + bounds.width) != (wrR.x + wrR.width))) // Partial tile off right insideTx1--; ty = (ty1 + 1) * tileHeight + tileGridYOff - 1; if ((ty >= (wrR.y + wrR.height)) && ((bounds.y + bounds.height) != (wrR.y + wrR.height))) // Partial tile off bottom insideTy1--; int xtiles = insideTx1 - insideTx0 + 1; int ytiles = insideTy1 - insideTy0 + 1; boolean[] occupied = null; if ((xtiles > 0) && (ytiles > 0)) occupied = new boolean[xtiles * ytiles]; boolean[] got = new boolean[2 * (tx1 - tx0 + 1) + 2 * (ty1 - ty0 + 1)]; int idx = 0; int numFound = 0; // Collect all the tiles that we currently have in cache... for (int y = ty0; y <= ty1; y++) { for (int x = tx0; x <= tx1; x++) { Raster ras = tiles.getTileNoCompute(x, y); boolean found = (ras != null); if ((y >= insideTy0) && (y <= insideTy1) && (x >= insideTx0) && (x <= insideTx1)) occupied[(x - insideTx0) + (y - insideTy0) * xtiles] = found; else got[idx++] = found; if (!found) continue; numFound++; if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(ras, wr); else GraphicsUtil.copyData_FALLBACK(ras, wr); } } // System.out.println("Found: " + numFound + " out of " + // ((tx1-tx0+1)*(ty1-ty0+1))); // Compute the stuff from the middle in the largest possible Chunks. if ((xtiles > 0) && (ytiles > 0)) { TileBlock block = new TileBlock(insideTx0, insideTy0, xtiles, ytiles, occupied, 0, 0, xtiles, ytiles); // System.out.println("Starting Splits"); drawBlock(block, wr); // Exception e= new Exception("Foo"); // e.printStackTrace(); } idx = 0; // Fill in the ones that weren't in the cache. for (ty = ty0; ty <= ty1; ty++) { for (tx = tx0; tx <= tx1; tx++) { // At least touch the tile... Raster ras = tiles.getTileNoCompute(tx, ty); if ((ty >= insideTy0) && (ty <= insideTy1) && (tx >= insideTx0) && (tx <= insideTx1)) { if (ras != null) continue; // Fill the tile from wr (since wr is full now // at least in the middle). WritableRaster tile = makeTile(tx, ty); if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(wr, tile); else GraphicsUtil.copyData_FALLBACK(wr, tile); tiles.setTile(tx, ty, tile); } else { if (got[idx++]) continue; // System.out.println("Computing : " + x + "," + y); ras = getTile(tx, ty); // Compute the tile.. if (Thread.currentThread().isInterrupted()) return; if (is_INT_PACK) GraphicsUtil.copyData_INT_PACK(ras, wr); else GraphicsUtil.copyData_FALLBACK(ras, wr); } } } // System.out.println("Ending Computation: " + this); }
public static ZeroRecter getZeroRecter(WritableRaster wr) { if (GraphicsUtil.is_INT_PACK_Data(wr.getSampleModel(), false)) return new ZeroRecter_INT_PACK(wr); else return new ZeroRecter(wr); }