pb.add(paramBlock.getObjectParameter(0)).add(res).add(subImage);
RenderedImage iipRes = JAI.create("iipresolution", pb);
Vector sources = new Vector(1);
sources.add(iipRes);
RenderableImage ri =
new MultiResolutionRenderableImage(sources, 0.0F, 0.0F,
1.0F);
// Filtering.
if((opMask & MASK_FILTER) != 0) {
float filter = paramBlock.getFloatParameter(2);
pb = (new ParameterBlock()).addSource(ri).add(filter);
ri = new RenderableImageOp(new FilterCRIF(), pb);
}
// Color-twist.
// Cache the original number of bands in case the number of bands
// changes due to addition of chroma and/or alpha channels in the
// color-twist procedure.
int nBands = iipRes.getSampleModel().getNumBands();
if((opMask & MASK_COLOR_TWIST) != 0) {
double[][] ctw = getColorTwistMatrix(iipRes.getColorModel(),
paramBlock);
pb = (new ParameterBlock()).addSource(ri).add(ctw);
ri = JAI.createRenderable("bandcombine", pb);
nBands = ctw.length;
}
// Contrast.
if((opMask & MASK_CONTRAST) != 0) {
int csType = iipRes.getColorModel().getColorSpace().getType();
boolean isPYCC =
csType != ColorSpace.TYPE_GRAY &&
csType != ColorSpace.TYPE_RGB;
if(isPYCC) {
double[][] matrix;
if(nBands == 3) { // PYCC
matrix = composeMatrices(YCC_TO_RGB, YCC_TO_RGB_CONST);
} else { // PYCC-A
matrix = composeMatrices(YCCA_TO_RGBA, YCCA_TO_RGBA_CONST);
}
pb = (new ParameterBlock()).addSource(ri).add(matrix);
ri = JAI.createRenderable("bandcombine", pb);
}
float contrast = paramBlock.getFloatParameter(4);
LookupTableJAI lut = createContrastLUT(contrast, nBands);
pb = (new ParameterBlock()).addSource(ri).add(lut);
ri = JAI.createRenderable("lookup", pb);
if(isPYCC) {
double[][] matrix;
if(nBands == 3) { // PYCC
matrix = composeMatrices(RGB_TO_YCC, RGB_TO_YCC_CONST);
} else { // PYCC-A
matrix = composeMatrices(RGBA_TO_YCCA, RGBA_TO_YCCA_CONST);
}
pb = (new ParameterBlock()).addSource(ri).add(matrix);
ri = JAI.createRenderable("bandcombine", pb);
}
}
// Source rectangle of interest.
if((opMask & MASK_ROI_SOURCE) != 0) {
// Get the source rectangle of interest.
Rectangle2D rect = (Rectangle2D)paramBlock.getObjectParameter(5);
// Check for intersection with source bounds.
if(!rect.intersects(0.0, 0.0, aspectRatioSource, 1.0)) {
throw new RuntimeException(JaiI18N.getString("IIPCRIF5"));
}
// Create the source rectangle.
Rectangle2D rectS = new Rectangle2D.Float(0.0F, 0.0F,
aspectRatioSource, 1.0F);
// Crop out the desired region.
if(!rect.equals(rectS)) {
// Clip to the source bounds.
rect = rect.createIntersection(rectS);
// Crop to the clipped rectangle of interest.
pb = (new ParameterBlock()).addSource(ri);
pb.add((float)rect.getMinX()).add((float)rect.getMinY());
pb.add((float)rect.getWidth()).add((float)rect.getHeight());
ri = JAI.createRenderable("crop", pb);
/* XXX
// Embed the cropped image in an image the size of the source.
pb = (new ParameterBlock()).addSource(ri);
pb.add((float)rectS.getMinX()).add((float)rectS.getMinY());
pb.add((float)rectS.getWidth()).add((float)rectS.getHeight());
ri = JAI.createRenderable("crop", pb);
*/
}
}
// Spatial orientation.
if((opMask & MASK_TRANSFORM) != 0) {
AffineTransform afn =
(AffineTransform)paramBlock.getObjectParameter(6);
try {
// The transform parameter is a backward mapping so invert it.
afn = afn.createInverse();
} catch(java.awt.geom.NoninvertibleTransformException e) {
// This should never happen due to descriptor check.
listener.errorOccurred(JaiI18N.getString("AffineNotInvertible"),
e, this, false);
}
pb = (new ParameterBlock()).addSource(ri).add(afn);
if(hints != null && hints.containsKey(JAI.KEY_INTERPOLATION)) {
pb.add(hints.get(JAI.KEY_INTERPOLATION));
}
ri = JAI.createRenderable("affine", pb);
}
// Destination rectangle of interest.
// Set the destination rectangle of interest.
Rectangle2D rgn = (opMask & MASK_ROI_DESTINATION) != 0 ?
(Rectangle2D)paramBlock.getObjectParameter(8) : bounds2D;
// Verify that the region is non-empty.
if(rgn.isEmpty()) {
throw new RuntimeException(JaiI18N.getString("IIPCRIF3"));
}
// Create a Rectangle2D for the current image.
Rectangle2D riRect = new Rectangle2D.Float((float)ri.getMinX(),
(float)ri.getMinY(),
(float)ri.getWidth(),
(float)ri.getHeight());
// If the current image bounds are not those of the requested
// region then crop the image.
if(!rgn.equals(riRect)) {
// Intersect rgn with source image bounds.
rgn = rgn.createIntersection(riRect);
// Crop to the rectangle of interest.
pb = (new ParameterBlock()).addSource(ri);
pb.add((float)rgn.getMinX()).add((float)rgn.getMinY());
pb.add((float)rgn.getWidth()).add((float)rgn.getHeight());
ri = JAI.createRenderable("crop", pb);
}
// Return the rendering.
return ri.createRendering(renderContext);
}