if (!r.getBounds().equals(cr.getBounds())) {
if (edgeMode == PadMode.WRAP)
throw new IllegalArgumentException
("edgeMode=\"wrap\" is not supported by ConvolveMatrix.");
cr = new PadRed(cr, r.getBounds(), edgeMode, rh);
}
// org.apache.batik.test.gvt.ImageDisplay.printImage
// ("Padded Image", cr,
// new Rectangle(cr.getMinX()+23,cr.getMinY()+39,5,5));
if (bias != 0.0)
throw new IllegalArgumentException
("Only bias equal to zero is supported in ConvolveMatrix.");
BufferedImageOp op = new ConvolveOp(kernel,
ConvolveOp.EDGE_NO_OP,
rh);
ColorModel cm = cr.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();
WritableRaster wr = GraphicsUtil.makeRasterWritable(rr, 0, 0);
// Here we update the translate to account for the phase shift
// (if any) introduced by setting targetX, targetY in SVG.
int phaseShiftX = target.x - kernel.getXOrigin();
int phaseShiftY = target.y - kernel.getYOrigin();
int destX = (int)(r.getX() + phaseShiftX);
int destY = (int)(r.getY() + phaseShiftY);
BufferedImage destBI;
if (!preserveAlpha) {
// Force the data to be premultiplied since often the JDK
// code doesn't properly premultiply the values...
cm = GraphicsUtil.coerceData(wr, cm, true);
BufferedImage srcBI;
srcBI = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
// Easy case just apply the op...
destBI = op.filter(srcBI, null);
if (kernelHasNegValues) {
// When the kernel has negative values it's possible
// for the resultant image to have alpha values less
// than the associated color values this will lead to
// problems later when we try to display the image so
// we fix this here.
fixAlpha(destBI);
}
} else {
BufferedImage srcBI;
srcBI = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
// Construct a linear sRGB cm without alpha...
cm = new DirectColorModel(ColorSpace.getInstance
(ColorSpace.CS_LINEAR_RGB), 24,
0x00FF0000, 0x0000FF00,
0x000000FF, 0x0, false,
DataBuffer.TYPE_INT);
// Create an image with that color model
BufferedImage tmpSrcBI = new BufferedImage
(cm, cm.createCompatibleWritableRaster(wr.getWidth(),
wr.getHeight()),
cm.isAlphaPremultiplied(), null);
// Copy the color data (no alpha) to that image
// (dividing out alpha if needed).
GraphicsUtil.copyData(srcBI, tmpSrcBI);
// org.apache.batik.test.gvt.ImageDisplay.showImage
// ("tmpSrcBI: ", tmpSrcBI);
// Get a linear sRGB Premult ColorModel
ColorModel dstCM = GraphicsUtil.Linear_sRGB_Unpre;
// Construct out output image around that ColorModel
destBI = new BufferedImage
(dstCM, dstCM.createCompatibleWritableRaster(wr.getWidth(),
wr.getHeight()),
dstCM.isAlphaPremultiplied(), null);
// Construct another image on the same data buffer but without
// an alpha channel.
// Create the Raster (note we are using 'cm' again).
WritableRaster dstWR =
Raster.createWritableRaster
(cm.createCompatibleSampleModel(wr.getWidth(), wr.getHeight()),
destBI.getRaster().getDataBuffer(),
new Point(0,0));
// Create the BufferedImage.
BufferedImage tmpDstBI = new BufferedImage
(cm, dstWR, cm.isAlphaPremultiplied(), null);
// Filter between the two image without alpha.
tmpDstBI = op.filter(tmpSrcBI, tmpDstBI);
// org.apache.batik.test.gvt.ImageDisplay.showImage
// ("tmpDstBI: ", tmpDstBI);
// Copy the alpha channel into the result (note the color
// channels are still unpremult.
Rectangle srcRect = wr.getBounds();
Rectangle dstRect = new Rectangle(srcRect.x-phaseShiftX,
srcRect.y-phaseShiftY,
srcRect.width, srcRect.height);
GraphicsUtil.copyBand(wr, srcRect, wr.getNumBands()-1,
destBI.getRaster(), dstRect,
destBI.getRaster().getNumBands()-1);
}
// Wrap it as a CachableRed
cr = new BufferedImageCachableRed(destBI, destX, destY);
// org.apache.batik.test.gvt.ImageDisplay.printImage
// ("Cropped Image", cr,
// new Rectangle(cr.getMinX()+22,cr.getMinY()+38,5,5));
// org.apache.batik.test.gvt.ImageDisplay.printImage
// ("Cropped sRGB", GraphicsUtil.convertTosRGB(cr),
// new Rectangle(cr.getMinX()+22,cr.getMinY()+38,5,5));
// Make sure to crop junk from edges.
cr = new PadRed(cr, devRect.getBounds(), PadMode.ZERO_PAD, rh);
// If we need to scale/rotate/translate the result do so now...
if (!resAt.isIdentity())
cr = new AffineRed(cr, resAt, null);