float origHeight = uncroppedImage.getHeight();
AffineTransform xform = org.photovault.image.ImageXform.getRotateXform(
rot, origWidth, origHeight );
ParameterBlockJAI rotParams = new ParameterBlockJAI( "affine" );
rotParams.addSource( uncroppedImage );
rotParams.setParameter( "transform", xform );
rotParams.setParameter( "interpolation",
Interpolation.getInstance( Interpolation.INTERP_NEAREST ) );
RenderingHints hints = new RenderingHints( null );
/*
In practice, JAI optimizes the pipeline so that this trasnformation is
concatenated with scaling from MultiresolutionImage to desired resolution.
This transformation obeys KYE_INTERPOLATION hint so we must set it here,
otherwise nearest neighborough interpolation will be used regardless of
the settings on parameter block.
*/
hints.put( JAI.KEY_INTERPOLATION, new InterpolationBilinear() );
rotatedImage = JAI.createRenderable( "affine", rotParams, hints );
ParameterBlockJAI cropParams = new ParameterBlockJAI( "crop" );
cropParams.addSource( rotatedImage );
float cropWidth = (float) (cropMaxX - cropMinX);
cropWidth = ( cropWidth > 0.000001 ) ? cropWidth : 0.000001f;
float cropHeight = (float) (cropMaxY - cropMinY);
cropHeight = ( cropHeight > 0.000001 ) ? cropHeight : 0.000001f;
float cropX = (float)(rotatedImage.getMinX() + cropMinX * rotatedImage.getWidth());
float cropY = (float)(rotatedImage.getMinY() + cropMinY * rotatedImage.getHeight());
float cropW = cropWidth * rotatedImage.getWidth();
float cropH = cropHeight * rotatedImage.getHeight();
Rectangle2D.Float cropRect = new Rectangle2D.Float( cropX, cropY, cropW, cropH );
Rectangle2D.Float srcRect = new Rectangle2D.Float( rotatedImage.getMinX(), rotatedImage.getMinY(),
rotatedImage.getWidth(), rotatedImage.getHeight() );
if ( !srcRect.contains( cropRect ) ) {
// Crop rectangle must fit inside source image
Rectangle2D.intersect( srcRect, cropRect, cropRect );
if ( !srcRect.contains( cropRect ) ) {
// Ups, we have a problem... this can happen due to rounding errors
// (for example, if cropY is just above zero). Disable cropping
// to avoid error.
cropX = rotatedImage.getMinX();
cropY = rotatedImage.getMinY();
cropW = rotatedImage.getWidth();
cropH = rotatedImage.getHeight();
}
}
cropParams.setParameter( "x", cropX );
cropParams.setParameter( "y", cropY );
cropParams.setParameter( "width", cropW );
cropParams.setParameter( "height", cropH );
croppedImage = JAI.createRenderable("crop", cropParams, hints );
// Translate the image so that it begins in origo
ParameterBlockJAI pbXlate = new ParameterBlockJAI( "translate" );
pbXlate.addSource( croppedImage );
pbXlate.setParameter( "xTrans", (float) (-croppedImage.getMinX() ) );
pbXlate.setParameter( "yTrans", (float) (-croppedImage.getMinY() ) );
xformCroppedImage = JAI.createRenderable( "translate", pbXlate );
return xformCroppedImage;
}