(serverMask & SERVER_JPEG_PARTIAL) != SERVER_JPEG_PARTIAL &&
(serverMask & SERVER_FPX_PARTIAL) != SERVER_FPX_PARTIAL) {
return null;
}
ImagingListener listener = ImageUtil.getImagingListener(renderContext);
// Set JPEG and full server flags.
boolean isJPEG = false;
boolean isFull = false;
if((serverMask & SERVER_JPEG_FULL) == SERVER_JPEG_FULL) {
isJPEG = isFull = true;
} else if((serverMask & SERVER_FPX_FULL) == SERVER_FPX_FULL) {
isJPEG = false;
isFull = true;
} else if((serverMask & SERVER_JPEG_PARTIAL) == SERVER_JPEG_PARTIAL) {
isJPEG = true;
isFull = false;
}
// Create a StringBuffer for the composed image command URL.
StringBuffer buf =
new StringBuffer((String)paramBlock.getObjectParameter(0));
//TODO: subImages (how?)
// Filtering.
if((opMask & MASK_FILTER) != 0) {
buf.append("&FTR="+paramBlock.getFloatParameter(2));
}
// Color-twist.
if((opMask & MASK_COLOR_TWIST) != 0) {
buf.append("&CTW=");
float[] ctw = (float[])paramBlock.getObjectParameter(3);
for(int i = 0; i < ctw.length; i++) {
buf.append(ctw[i]);
if(i != ctw.length-1) {
buf.append(",");
}
}
}
// Contrast.
if((opMask & MASK_CONTRAST) != 0) {
buf.append("&CNT="+paramBlock.getFloatParameter(4));
}
// Source rectangle of interest.
if((opMask & MASK_ROI_SOURCE) != 0) {
Rectangle2D roi =
(Rectangle2D)paramBlock.getObjectParameter(5);
buf.append("&ROI="+roi.getX()+","+ roi.getY()+","+
roi.getWidth()+","+roi.getHeight());
}
// If full support for the CVT command is available, decompose the
// AffineTransform specifying the transformation from renderable to
// rendered coordinates into a translation, a pure scale, and the
// residual transformation. The residual transformation may then be
// concatenated with the server-side affine transform (after
// inversion), the pure scale may be effected by specifying the WID
// and HEI composed image command modifiers, and the translation as
// a subsequent operation. If the WID and HEI modifiers are not
// available, i.e., the server support is partial, this becomes
// more problematic. Fortunately no such servers are known to exist.
// Initialize the post-processing transform to the identity.
AffineTransform postTransform = new AffineTransform();
// Retrieve (a clone of) the renderable-to-rendered mapping.
AffineTransform at =
(AffineTransform)renderContext.getTransform().clone();
// If the translation is non-zero set the post-transform.
if(at.getTranslateX() != 0.0 || at.getTranslateY() != 0.0) {
postTransform.setToTranslation(at.getTranslateX(),
at.getTranslateY());
double[] m = new double[6];
at.getMatrix(m);
at.setTransform(m[0], m[1], m[2], m[3], 0.0, 0.0);
}
// Determine the renderable destination region of interest.
Rectangle2D rgn = null;
if((opMask & MASK_ROI_DESTINATION) != 0) {
rgn = (Rectangle2D)paramBlock.getObjectParameter(8);
} else {
float aspectRatio = 1.0F;
if((opMask & MASK_ASPECT_RATIO) != 0) {
aspectRatio = paramBlock.getFloatParameter(7);
} else {
aspectRatio =
((Float)(lowRes.getProperty("aspect-ratio"))).floatValue();
}
rgn = new Rectangle2D.Float(0.0F, 0.0F, aspectRatio, 1.0F);
}
// Apply the renderable-to-rendered mapping to the renderable
// destination region of interest.
Rectangle dstROI = at.createTransformedShape(rgn).getBounds();
// Calculate the pure scale portion of the
// renderable-to-rendered mapping.
AffineTransform scale =
AffineTransform.getScaleInstance(dstROI.getWidth()/
rgn.getWidth(),
dstROI.getHeight()/
rgn.getHeight());
// Determine the residual mapping.
try {
at.preConcatenate(scale.createInverse());
} catch(Exception e) {
String message = JaiI18N.getString("IIPCRIF6");
listener.errorOccurred(message,
new ImagingException(message, e),
this, false);
// throw new RuntimeException(JaiI18N.getString("IIPCRIF6"));
}
// Compose the inverse residual mapping with the renderable
// transform.
AffineTransform afn =
(AffineTransform)paramBlock.getObjectParameter(6);
try {
afn.preConcatenate(at.createInverse());
} catch(Exception e) {
String message = JaiI18N.getString("IIPCRIF6");
listener.errorOccurred(message,
new ImagingException(message, e),
this, false);
// throw new RuntimeException(JaiI18N.getString("IIPCRIF6"));
}
if(isFull) {
// Append the WID and HEI composed image command modifiers using
// the dimensions of the rendered destination region of interest.
buf.append("&WID="+dstROI.width+"&HEI="+dstROI.height);
/* XXX Begin suppressed section.
} else if((opMask & MASK_TRANSFORM) != 0) {
Point2D[] dstPts =
new Point2D[] {new Point2D.Double(rgn.getMinX(),
rgn.getMinY()),
new Point2D.Double(rgn.getMaxX(),
rgn.getMinY()),
new Point2D.Double(rgn.getMinX(),
rgn.getMaxY())};
Point2D[] srcPts = new Point2D[3];
afn.transform(dstPts, 0, srcPts, 0, 3);
double LLeft = srcPts[0].distance(srcPts[2]);
double LTop = srcPts[0].distance(srcPts[1]);
int[] maxSize = (int[])lowRes.getProperty("max-size");
double H = maxSize[1]*LLeft;
double W = maxSize[1]*LTop;
double m = Math.max(H, W*(double)maxSize[1]/(double)maxSize[0]);
int Hp = (int)(m + 0.5);
int Wp = (int)(m*(double)maxSize[0]/(double)maxSize[1] + 0.5);
System.out.println("Estimated dimensions = "+Wp+" x "+Hp);
AffineTransform scl =
AffineTransform.getScaleInstance(dstROI.getWidth()/Wp,
dstROI.getHeight()/Hp);
System.out.println("scl = "+scl);
afn.preConcatenate(scl);
End suppressed section. XXX */
}
// Append the affine tranform composed image command.
double[] matrix = new double[6];
afn.getMatrix(matrix);
buf.append("&AFN="+
matrix[0]+","+matrix[2]+",0,"+matrix[4]+","+
matrix[1]+","+matrix[3]+",0,"+matrix[5]+
",0,0,1,0,0,0,0,1");
// Destination aspect ratio.
if((opMask & MASK_ASPECT_RATIO) != 0) {
buf.append("&RAR="+paramBlock.getFloatParameter(7));
}
// Destination rectangle of interest.
if((opMask & MASK_ROI_DESTINATION) != 0) {
Rectangle2D dstRGN =
(Rectangle2D)paramBlock.getObjectParameter(8);
buf.append("&RGN="+dstRGN.getX()+","+ dstRGN.getY()+","+
dstRGN.getWidth()+","+dstRGN.getHeight());
}
// Rotation and mirroring.
if(isFull) {
if((opMask & MASK_ROTATION) != 0 ||
(opMask & MASK_MIRROR_AXIS) != 0) {
buf.append("&RFM="+paramBlock.getIntParameter(9));
if((opMask & MASK_MIRROR_AXIS) != 0) {
String axis = (String)paramBlock.getObjectParameter(10);
if(axis.equalsIgnoreCase("x")) {
buf.append(",0");
} else {
buf.append(",90");
}
}
}
}
// ICC profile.
if((opMask & MASK_ICC_PROFILE) != 0) {
// According to the IIP specification this is not supported
// over HTTP connections and that is all that is available from
// the vendors right now, i.e., no socket connections are
// available (includes LivePicture and TrueSpectra).
}
// JPEG quality and compression group index.
if(isJPEG) {
if((opMask & MASK_JPEG_QUALITY) != 0) {
buf.append("&QLT="+paramBlock.getIntParameter(12));
}
if((opMask & MASK_JPEG_TABLE) != 0) {
buf.append("&CIN="+paramBlock.getIntParameter(13));
}
}
// Set the format string.
String format = isJPEG ? "JPEG" : "FPX";
// Append the CVT command.
buf.append("&CVT="+format);
// Create a URL with the CVT string, open a stream from it, and
// decode the image using the appropriate decoder.
InputStream stream = null;
RenderedImage rendering = null;
try {
URL url = new URL(buf.toString());
stream = url.openStream();
MemoryCacheSeekableStream sStream =
new MemoryCacheSeekableStream(stream);
rendering = JAI.create(format, sStream);
} catch(Exception e) {
String message =
JaiI18N.getString("IIPCRIF7") + " " + buf.toString();
listener.errorOccurred(message,
new ImagingException(message, e),
this, false);
// throw new RuntimeException(e.getClass()+" "+e.getMessage());
}