srcAt = AffineTransform.getScaleInstance(scaleX, scaleY);
int radX = (int)Math.round(radiusX*scaleX);
int radY = (int)Math.round(radiusY*scaleY);
MorphologyOp op = null;
if(radX > 0 && radY > 0){
op = new MorphologyOp(radX, radY, doDilation);
}
// This is the affine transform between our intermediate
// coordinate space and the real device space.
AffineTransform resAt;
// The shear/rotation simply divides out the
// common scale factor in the matrix.
resAt = new AffineTransform(sx/scaleX, shy/scaleX,
shx/scaleY, sy/scaleY,
tx, ty);
Shape aoi = rc.getAreaOfInterest();
if(aoi == null) {
aoi = getBounds2D();
}
Rectangle2D r = aoi.getBounds2D();
r = new Rectangle2D.Double(r.getX()-radX/scaleX,
r.getY()-radY/scaleY,
r.getWidth() +2*radX/scaleX,
r.getHeight()+2*radY/scaleY);
RenderedImage ri;
ri = getSource().createRendering(new RenderContext(srcAt, r, rh));
if (ri == null)
return null;
CachableRed cr;
cr = new RenderedImageCachableRed(ri);
Shape devShape = srcAt.createTransformedShape(aoi.getBounds2D());
r = devShape.getBounds2D();
r = new Rectangle2D.Double(r.getX()-radX,
r.getY()-radY,
r.getWidth() +2*radX,
r.getHeight()+2*radY);
cr = new PadRed(cr, r.getBounds(), PadMode.ZERO_PAD, rh);
// System.out.println("Src: " + cr.getBounds(rc));
ColorModel cm = ri.getColorModel();
// OK this is a bit of a cheat. We Pull the DataBuffer out of
// The read-only raster that getData gives us. And use it to
// build a WritableRaster. This avoids a copy of the data.
Raster rr = cr.getData();
Point pt = new Point(0,0);
WritableRaster wr = Raster.createWritableRaster(rr.getSampleModel(),
rr.getDataBuffer(),
pt);
BufferedImage srcBI;
srcBI = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
BufferedImage destBI;
if(op != null){
destBI = op.filter(srcBI, null);
}
else{
destBI = srcBI;
}