001: /*
002: * $RCSfile: MlibAffineRIF.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:55:49 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.mlib;
013:
014: import java.awt.RenderingHints;
015: import java.awt.geom.AffineTransform;
016: import java.awt.image.DataBuffer;
017: import java.awt.image.MultiPixelPackedSampleModel;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.SampleModel;
020: import java.awt.image.renderable.ParameterBlock;
021: import java.awt.image.renderable.RenderedImageFactory;
022: import javax.media.jai.BorderExtender;
023: import javax.media.jai.ImageLayout;
024: import javax.media.jai.Interpolation;
025: import javax.media.jai.InterpolationBicubic2;
026: import javax.media.jai.InterpolationBicubic;
027: import javax.media.jai.InterpolationBilinear;
028: import javax.media.jai.InterpolationNearest;
029: import javax.media.jai.InterpolationTable;
030: import java.util.Map;
031: import com.sun.media.jai.opimage.RIFUtil;
032: import com.sun.media.jai.opimage.TranslateIntOpImage;
033:
034: /**
035: * A <code>RIF</code> supporting the "Affine" operation in the
036: * rendered image mode using MediaLib.
037: *
038: * @see javax.media.jai.operator.AffineDescriptor
039: * @see MlibAffineOpImage
040: * @see MlibScaleOpImage
041: *
042: * @since EA4
043: */
044: public class MlibAffineRIF implements RenderedImageFactory {
045:
046: private static final float TOLERANCE = 0.01F;
047:
048: /** Constructor. */
049: public MlibAffineRIF() {
050: }
051:
052: /**
053: * Creates a new instance of <code>MlibAffineOpImage</code> in
054: * the rendered image mode.
055: *
056: * @param args The source image, the <code>AffineTransform</code>,
057: * and the <code>Interpolation</code>.
058: * @param hints May contain rendering hints and destination image layout.
059: */
060: public RenderedImage create(ParameterBlock args,
061: RenderingHints hints) {
062: /* Get ImageLayout and TileCache from RenderingHints. */
063: ImageLayout layout = RIFUtil.getImageLayoutHint(hints);
064:
065: // Get operation parameters.
066: AffineTransform transform = (AffineTransform) args
067: .getObjectParameter(0);
068: Interpolation interp = (Interpolation) args
069: .getObjectParameter(1);
070: double[] backgroundValues = (double[]) args
071: .getObjectParameter(2);
072:
073: RenderedImage source = args.getRenderedSource(0);
074:
075: if (!MediaLibAccessor.isMediaLibCompatible(args, layout)
076: || !MediaLibAccessor.hasSameNumBands(args, layout)
077: ||
078: // Medialib cannot deal with source image having tiles with any
079: // dimension greater than or equal to 32768
080: source.getTileWidth() >= 32768
081: || source.getTileHeight() >= 32768) {
082: return null;
083: }
084:
085: SampleModel sm = source.getSampleModel();
086: boolean isBilevel = (sm instanceof MultiPixelPackedSampleModel)
087: && (sm.getSampleSize(0) == 1)
088: && (sm.getDataType() == DataBuffer.TYPE_BYTE
089: || sm.getDataType() == DataBuffer.TYPE_USHORT || sm
090: .getDataType() == DataBuffer.TYPE_INT);
091: if (isBilevel) {
092: // Let Java code handle it, reformatting is slower
093: return null;
094: }
095:
096: // Get BorderExtender from hints if any.
097: BorderExtender extender = RIFUtil.getBorderExtenderHint(hints);
098:
099: /* Get the affine transform. */
100: double[] tr = new double[6];
101: transform.getMatrix(tr);
102:
103: /*
104: * Check and see if the affine transform is doing a copy.
105: * If so call the copy operation.
106: */
107: if ((tr[0] == 1.0) && (tr[3] == 1.0) && (tr[2] == 0.0)
108: && (tr[1] == 0.0) && (tr[4] == 0.0) && (tr[5] == 0.0)) {
109: /* It's a copy. */
110: return new MlibCopyOpImage(source, hints, layout);
111: }
112:
113: /*
114: * Check and see if the affine transform is in fact doing
115: * a Translate operation. That is a scale by 1 and no rotation.
116: * In which case call translate. Note that only integer translate
117: * is applicable. For non-integer translate we'll have to do the
118: * affine.
119: */
120: if ((tr[0] == 1.0) && (tr[3] == 1.0) && (tr[2] == 0.0)
121: && (tr[1] == 0.0)
122: && (Math.abs(tr[4] - (int) tr[4]) < TOLERANCE)
123: && (Math.abs(tr[5] - (int) tr[5]) < TOLERANCE)
124: && layout == null) { // TranslateIntOpImage can't deal with ImageLayout hint
125: /* It's a integer translate. */
126: return new TranslateIntOpImage(source, hints, (int) tr[4],
127: (int) tr[5]);
128: }
129:
130: /*
131: * Check and see if the affine transform is in fact doing
132: * a Scale operation. In which case call Scale which is more
133: * optimized than Affine.
134: */
135: if ((tr[0] > 0.0) && (tr[2] == 0.0) && (tr[1] == 0.0)
136: && (tr[3] > 0.0)) {
137: /* It's a scale. */
138: if (interp instanceof InterpolationNearest) {
139: return new MlibScaleNearestOpImage(source, extender,
140: hints, layout, (float) tr[0], // xScale
141: (float) tr[3], // yScale
142: (float) tr[4], // xTrans
143: (float) tr[5], // yTrans
144: interp);
145: } else if (interp instanceof InterpolationBilinear) {
146: return new MlibScaleBilinearOpImage(source, extender,
147: hints, layout, (float) tr[0], // xScale
148: (float) tr[3], // yScale
149: (float) tr[4], // xTrans
150: (float) tr[5], // yTrans
151: interp);
152: } else if (interp instanceof InterpolationBicubic
153: || interp instanceof InterpolationBicubic2) {
154: return new MlibScaleBicubicOpImage(source, extender,
155: hints, layout, (float) tr[0], // xScale
156: (float) tr[3], // yScale
157: (float) tr[4], // xTrans
158: (float) tr[5], // yTrans
159: interp);
160: } else if (interp instanceof InterpolationTable) {
161: return new MlibScaleTableOpImage(source, extender,
162: hints, layout, (float) tr[0], // xScale
163: (float) tr[3], // yScale
164: (float) tr[4], // xTrans
165: (float) tr[5], // yTrans
166: interp);
167: } else {
168: return null;
169: }
170: }
171:
172: /* Have to do an Affine. */
173: if (interp instanceof InterpolationNearest) {
174: return new MlibAffineNearestOpImage(source, extender,
175: hints, layout, transform, interp, backgroundValues);
176: } else if (interp instanceof InterpolationBilinear) {
177: return new MlibAffineBilinearOpImage(source, extender,
178: hints, layout, transform, interp, backgroundValues);
179: } else if (interp instanceof InterpolationBicubic
180: || interp instanceof InterpolationBicubic2) {
181: return new MlibAffineBicubicOpImage(source, extender,
182: hints, layout, transform, interp, backgroundValues);
183: } else if (interp instanceof InterpolationTable) {
184: return new MlibAffineTableOpImage(source, extender, hints,
185: layout, transform, interp, backgroundValues);
186: } else {
187: return null;
188: }
189: }
190: }
|