0001: /*
0002: * $RCSfile: MediaLibAccessor.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.2 $
0009: * $Date: 2005/11/23 21:08:28 $
0010: * $State: Exp $
0011: */
0012: package com.sun.media.jai.mlib;
0013:
0014: import java.awt.Rectangle;
0015: import java.awt.image.ColorModel;
0016: import java.awt.image.ComponentSampleModel;
0017: import java.awt.image.ComponentColorModel;
0018: import java.awt.image.DataBuffer;
0019: import java.awt.image.DataBufferByte;
0020: import java.awt.image.DataBufferShort;
0021: import java.awt.image.DataBufferInt;
0022: import java.awt.image.DataBufferUShort;
0023: import java.awt.image.Raster;
0024: import java.awt.image.SampleModel;
0025: import java.awt.image.WritableRaster;
0026: import java.awt.image.RenderedImage;
0027: import java.awt.image.renderable.ParameterBlock;
0028: import java.io.FileNotFoundException;
0029: import java.io.FilePermission;
0030: import java.io.InputStream;
0031: import java.io.IOException;
0032: import java.lang.NoClassDefFoundError;
0033: import java.security.AccessControlException;
0034: import java.security.AccessController;
0035: import java.security.PrivilegedAction;
0036: import javax.media.jai.ImageLayout;
0037: import javax.media.jai.JAI;
0038: import javax.media.jai.RasterAccessor;
0039: import javax.media.jai.util.ImagingListener;
0040: import com.sun.media.jai.util.DataBufferUtils;
0041: import com.sun.media.jai.util.ImageUtil;
0042: import com.sun.media.jai.util.PropertyUtil;
0043: import com.sun.medialib.mlib.*;
0044:
0045: /**
0046: * An adapter class for presenting image data in a mediaLibImage
0047: * format, even if the data isn't stored that way. MediaLibAccessor
0048: * is meant to make the common case (ComponentRasters) and allow
0049: * them to be accelerated via medialib. Note that unlike RasterAccessor,
0050: * MediaLibAccessor does not work with all cases. In the event that
0051: * MediaLibAccessor can not deal with a give collection of Rasters,
0052: * findCompatibleTag will return the value MediaLibAccessor.TAG_INCOMPATIBLE.
0053: * OpImages that use MediaLibAccessor should be paired with RIF's
0054: * which check that findCompatibleTag returns a valid tag before
0055: * actually constructing the Mlib OpImage.
0056: *
0057: */
0058:
0059: public class MediaLibAccessor {
0060: /**
0061: * Value indicating how far COPY_MASK info is shifted to avoid
0062: * interfering with the data type info
0063: */
0064: private static final int COPY_MASK_SHIFT = 7;
0065:
0066: /* Value indicating how many bits the COPY_MASK is */
0067: private static final int COPY_MASK_SIZE = 1;
0068:
0069: /** The bits of a FormatTag associated with how dataArrays are obtained. */
0070: public static final int COPY_MASK = 0x1 << COPY_MASK_SHIFT;
0071:
0072: /** Flag indicating data is raster's data. */
0073: public static final int UNCOPIED = 0x0 << COPY_MASK_SHIFT;
0074:
0075: /** Flag indicating data is a copy of the raster's data. */
0076: public static final int COPIED = 0x01 << COPY_MASK_SHIFT;
0077:
0078: /** The bits of a FormatTag associated with pixel datatype. */
0079: public static final int DATATYPE_MASK = (0x1 << COPY_MASK_SHIFT) - 1;
0080:
0081: /**
0082: * Value indicating how far BINARY_MASK info is shifted to avoid
0083: * interfering with the data type and copying info.
0084: */
0085: private static final int BINARY_MASK_SHIFT = COPY_MASK_SHIFT
0086: + COPY_MASK_SIZE;
0087:
0088: /** Value indicating how many bits the BINARY_MASK is */
0089: private static final int BINARY_MASK_SIZE = 1;
0090:
0091: /** The bits of a FormatTag associated with binary data. */
0092: public static final int BINARY_MASK = ((1 << BINARY_MASK_SIZE) - 1) << BINARY_MASK_SHIFT;
0093:
0094: /** Flag indicating data are not binary. */
0095: public static final int NONBINARY = 0x0 << BINARY_MASK_SHIFT;
0096:
0097: /** Flag indicating data are binary. */
0098: public static final int BINARY = 0x1 << BINARY_MASK_SHIFT;
0099:
0100: /** FormatTag indicating data in byte arrays and uncopied. */
0101: public static final int TAG_BYTE_UNCOPIED = DataBuffer.TYPE_BYTE
0102: | UNCOPIED;
0103:
0104: /** FormatTag indicating data in unsigned short arrays and uncopied. */
0105: public static final int TAG_USHORT_UNCOPIED = DataBuffer.TYPE_USHORT
0106: | UNCOPIED;
0107:
0108: /** FormatTag indicating data in short arrays and uncopied. */
0109: public static final int TAG_SHORT_UNCOPIED = DataBuffer.TYPE_SHORT
0110: | UNCOPIED;
0111:
0112: /** FormatTag indicating data in integer arrays and uncopied. */
0113: public static final int TAG_INT_UNCOPIED = DataBuffer.TYPE_INT
0114: | UNCOPIED;
0115:
0116: /** FormatTag indicating data in float arrays and uncopied. */
0117: public static final int TAG_FLOAT_UNCOPIED = DataBuffer.TYPE_FLOAT
0118: | UNCOPIED;
0119:
0120: /** FormatTag indicating data in double arrays and uncopied. */
0121: public static final int TAG_DOUBLE_UNCOPIED = DataBuffer.TYPE_DOUBLE
0122: | UNCOPIED;
0123:
0124: /** FormatTag indicating data in byte arrays and uncopied. */
0125: public static final int TAG_BYTE_COPIED = DataBuffer.TYPE_BYTE
0126: | COPIED;
0127:
0128: /** FormatTag indicating data in unsigned short arrays and copied. */
0129: public static final int TAG_USHORT_COPIED = DataBuffer.TYPE_USHORT
0130: | COPIED;
0131:
0132: /** FormatTag indicating data in short arrays and copied. */
0133: public static final int TAG_SHORT_COPIED = DataBuffer.TYPE_SHORT
0134: | COPIED;
0135:
0136: /** FormatTag indicating data in short arrays and copied. */
0137: public static final int TAG_INT_COPIED = DataBuffer.TYPE_INT
0138: | COPIED;
0139:
0140: /** FormatTag indicating data in float arrays and copied. */
0141: public static final int TAG_FLOAT_COPIED = DataBuffer.TYPE_FLOAT
0142: | COPIED;
0143:
0144: /** FormatTag indicating data in double arrays and copied. */
0145: public static final int TAG_DOUBLE_COPIED = DataBuffer.TYPE_DOUBLE
0146: | COPIED;
0147:
0148: /** The raster that is the source of pixel data. */
0149: protected Raster raster;
0150:
0151: /** The rectangle of the raster that MediaLibAccessor addresses. */
0152: protected Rectangle rect;
0153:
0154: /** The number of bands per pixel in the data array. */
0155: protected int numBands;
0156:
0157: /** The offsets of each band in the src image */
0158: protected int bandOffsets[];
0159:
0160: /** Tag indicating the data type of the data and whether its copied */
0161: protected int formatTag;
0162:
0163: /** Area of mediaLib images that represent image data */
0164: protected mediaLibImage mlimages[] = null;
0165:
0166: /**
0167: * Whether packed data are preferred when processing binary images.
0168: * This tag is ignored if the data are not binary.
0169: */
0170: private boolean areBinaryDataPacked = false;
0171:
0172: private static boolean useMlibVar = false;
0173: private static boolean useMlibVarSet = false;
0174:
0175: private static synchronized boolean useMlib() {
0176: if (!useMlibVarSet) {
0177: setUseMlib();
0178: useMlibVarSet = true;
0179: }
0180:
0181: return useMlibVar;
0182: }
0183:
0184: private static void setUseMlib() {
0185:
0186: // Fix of 4726600: Disable medialib before the searching of
0187: // medialib library if the property is set.
0188: boolean disableMediaLib = false;
0189: try {
0190: disableMediaLib = Boolean
0191: .getBoolean("com.sun.media.jai.disableMediaLib");
0192: } catch (java.security.AccessControlException e) {
0193: // Because the property com.sun.media.jai.disableMediaLib isn't
0194: // defined as public, the users shouldn't know it. In most of
0195: // the cases, it isn't defined, and thus no access permission
0196: // is granted to it in the policy file. When JAI is utilized in
0197: // a security environment, AccessControlException will be thrown.
0198: // In this case, we suppose that the users would like to use
0199: // medialib accelaration. So, the medialib won't be disabled.
0200:
0201: // The fix of 4531501
0202: }
0203:
0204: // If mediaLib usage has been explicity disabled.
0205: if (disableMediaLib) {
0206: useMlibVar = false;
0207: return;
0208: }
0209:
0210: try {
0211:
0212: SecurityManager securityManager = System
0213: .getSecurityManager();
0214:
0215: if (securityManager != null
0216: && MediaLibAccessor.class.getClassLoader() != null) {
0217:
0218: // a non-null security manager means we're in an applet
0219: // if this.classLoader == null, we're an installed extension
0220: // and the doPrivleged block should be ok.
0221:
0222: // native code doesn't currently load on Wintel regardless
0223: // of where the dll's are even if this code is removed.
0224: // At some point we'll need to come up with a better
0225: // solution. For now this is a good work around because
0226: // on Sparc it will cause
0227: // a SecurityException to be thrown instead of an
0228: // ExceptionInInitializerError in the doPriviliged block
0229: // which can't be caught.
0230: // If MediaLib is rewritten so that the Exception is thrown
0231: // after the class is loaded this chunk of code can be
0232: // removed.
0233: String osName = System.getProperty("os.name");
0234: String osArch = System.getProperty("os.arch");
0235:
0236: // The fix of 4531469
0237: if ((osName.equals("Solaris") || osName.equals("SunOS"))
0238: && osArch.equals("sparc")) {
0239: FilePermission fp = new FilePermission(
0240: "/usr/bin/uname", "execute");
0241: securityManager.checkPermission(fp);
0242: }
0243: }
0244:
0245: Boolean result = (Boolean) AccessController
0246: .doPrivileged(new PrivilegedAction() {
0247: public Object run() {
0248: return new Boolean(Image.isAvailable());
0249: }
0250: });
0251: useMlibVar = result.booleanValue();
0252: if (!useMlibVar) {
0253: forwardToListener(JaiI18N
0254: .getString("MediaLibAccessor2"),
0255: new MediaLibLoadException());
0256: }
0257: } catch (NoClassDefFoundError ncdfe) {
0258: // If mediaLib jar file is not found, fall back to Java code.
0259: useMlibVar = false;
0260: forwardToListener(JaiI18N.getString("MediaLibAccessor3"),
0261: ncdfe);
0262: } catch (ClassFormatError cfe) {
0263: // If mediaLib jar file is not found, fall back to Java code.
0264: useMlibVar = false;
0265: forwardToListener(JaiI18N.getString("MediaLibAccessor3"),
0266: cfe);
0267: } catch (SecurityException se) {
0268: // If mediaLib jar file is not found, fall back to Java code.
0269: useMlibVar = false;
0270: forwardToListener(JaiI18N.getString("MediaLibAccessor4"),
0271: se);
0272: }
0273:
0274: if (useMlibVar == false)
0275: return;
0276: }
0277:
0278: /**
0279: * Forwards the supplied message and exception to the
0280: * <code>ImagingListener</code> set on the default JAI instance.
0281: * If none is set (which should not happen) the message is simply
0282: * printed to <code>System.err</code>.
0283: */
0284: private static void forwardToListener(String message,
0285: Throwable thrown) {
0286: ImagingListener listener = JAI.getDefaultInstance()
0287: .getImagingListener();
0288:
0289: if (listener != null) {
0290: listener.errorOccurred(message, thrown,
0291: MediaLibAccessor.class, false);
0292: } else {
0293: System.err.println(message);
0294: }
0295: }
0296:
0297: /**
0298: * Returns <code>true</code> if mediaLib is able to handle the
0299: * source(s) and destination image format. Currently, all of the
0300: * following conditions must be met in order for this method to
0301: * return <code>true</code>.
0302: * <ul>
0303: * <li>MediaLib is available.</li>
0304: * <li>All sources must be <code>RenderedImage</code>.</li>
0305: * <li>All sources and destination must have
0306: * <code>ComponentSampleModel</code> and
0307: * <code>ComponentColorModel</code>.</li>
0308: * <li>All sources and destination must have less than or equal
0309: * to 4 bands of pixel data.</li>
0310: * </ul>
0311: * Additional checks for each individual <code>OpImage</code>
0312: * should be done in its corresponding <code>RIF</code>.
0313: *
0314: * @param args Input arguments that include sources.
0315: * @param layout Destination image layout; may be <code>null</code>.
0316: */
0317: public static boolean isMediaLibCompatible(ParameterBlock args,
0318: ImageLayout layout) {
0319: if (!isMediaLibCompatible(args)) {
0320: // sources not supported
0321: return false;
0322: }
0323:
0324: if (layout != null) { // validate destination
0325: SampleModel sm = layout.getSampleModel(null);
0326: if (sm != null) {
0327: if (!(sm instanceof ComponentSampleModel)
0328: || sm.getNumBands() > 4) {
0329: return false;
0330: }
0331: }
0332:
0333: ColorModel cm = layout.getColorModel(null);
0334: if (cm != null && (!(cm instanceof ComponentColorModel))) {
0335: return false;
0336: }
0337: }
0338:
0339: return true;
0340: }
0341:
0342: /**
0343: * Returns <code>true</code> if mediaLib is able to handle the
0344: * source(s) image format. Currently, all of the following
0345: * conditions must be met in order for this method to return
0346: * <code>true</code>.
0347: * <ul>
0348: * <li>MediaLib is available.</li>
0349: * <li>All sources must be <code>RenderedImage</code>.</li>
0350: * <li>All sources must have <code>ComponentSampleModel</code> and
0351: * <code>ComponentColorModel</code>.</li>
0352: * <li>All sources must have less than or equal to 4 bands of pixel
0353: * data.</li>
0354: * </ul>
0355: * Additional checks for each individual <code>OpImage</code>
0356: * should be done in its corresponding <code>RIF</code>.
0357: *
0358: * @param args Input arguments that include sources.
0359: */
0360: public static boolean isMediaLibCompatible(ParameterBlock args) {
0361: if (!useMlib()) { // mediaLib is not available
0362: return false;
0363: }
0364:
0365: int numSrcs = args.getNumSources();
0366: for (int i = 0; i < numSrcs; i++) {
0367: Object src = args.getSource(i);
0368: if (!(src instanceof RenderedImage)
0369: || !isMediaLibCompatible((RenderedImage) src)) {
0370: return false;
0371: }
0372: }
0373:
0374: return true;
0375: }
0376:
0377: /**
0378: * Returns <code>true</code> if mediaLib is able to handle the
0379: * image. Currently, all of the following conditions must be
0380: * met in order for this method to return <code>true</code>.
0381: * <ul>
0382: * <li>MediaLib is available.</li>
0383: * <li>The image must have <code>ComponentSampleModel</code> and
0384: * <code>ComponentColorModel</code>.</li>
0385: * <li>The image must have less than or equal to 4 bands of pixel
0386: * data.</li>
0387: * </ul>
0388: * Additional checks for each individual <code>OpImage</code>
0389: * should be done in its corresponding <code>RIF</code>.
0390: *
0391: * @param image The image the compatibility of which is to be checked.
0392: */
0393: public static boolean isMediaLibCompatible(RenderedImage image) {
0394: if (!useMlib()) { // mediaLib is not available
0395: return false;
0396: }
0397:
0398: SampleModel sm = image.getSampleModel();
0399: ColorModel cm = image.getColorModel();
0400:
0401: return (sm instanceof ComponentSampleModel
0402: && sm.getNumBands() <= 4 && (cm == null || cm instanceof ComponentColorModel));
0403: }
0404:
0405: /**
0406: * Returns <code>true</code> if mediaLib is able to handle
0407: * an image having the supplied <code>SampleModel</code> and
0408: * <code>ColorModel</code>. Currently, all of the following conditions
0409: * must be met in order for this method to return <code>true</code>:
0410: * <ul>
0411: * <li>mediaLib is available.</li>
0412: * <li>The <code>SampleModel</code> is an instance of
0413: * <code>ComponentSampleModel</code> or one of its subclasses.</li>
0414: * <li>The <code>ColorModel</code> is <code>null</code> or an
0415: * instance of <code>ComponentColorModel</code> or a subclass thereof.</li>
0416: * <li>The image must have no more than 4 bands of pixel data.</li>
0417: * </ul>
0418: *
0419: * @param sm The image <code>SampleModel</code>.
0420: * @param cm The image <code>ColorModel</code>.
0421: *
0422: * @throws NullPointerException if <code>sm</code> is <code>null</code>.
0423: */
0424: public static boolean isMediaLibCompatible(SampleModel sm,
0425: ColorModel cm) {
0426: if (!useMlib()) { // mediaLib is not available
0427: return false;
0428: }
0429:
0430: return (sm instanceof ComponentSampleModel
0431: && sm.getNumBands() <= 4 && (cm == null || cm instanceof ComponentColorModel));
0432: }
0433:
0434: /**
0435: * Returns <code>true</code> if mediaLib is able to handle the
0436: * source(s) and destination image format as binary (also known
0437: * as bit or bilevel) image data. Currently, all of the
0438: * following conditions must be met in order for this method to
0439: * return <code>true</code>.
0440: * <ul>
0441: * <li>MediaLib is available.</li>
0442: * <li>All sources must be <code>RenderedImage</code>s.</li>
0443: * <li>All sources and destination must have a
0444: * <code>MultiPixelPackedSampleModel</code>.</li>
0445: * <li>All sources and destination must have represent
0446: * single-bit data.</li>
0447: * <li>All sources and destination must have
0448: * a single band of pixel data.</li>
0449: * </ul>
0450: * Additional checks for each individual <code>OpImage</code>
0451: * should be done in its corresponding <code>RIF</code>.
0452: *
0453: * @param args Input arguments that include sources.
0454: * @param layout Destination image layout; may be <code>null</code>.
0455: */
0456: public static boolean isMediaLibBinaryCompatible(
0457: ParameterBlock args, ImageLayout layout) {
0458: if (!useMlib()) { // mediaLib is not available
0459: return false;
0460: }
0461:
0462: SampleModel sm = null;
0463:
0464: int numSrcs = args.getNumSources();
0465: for (int i = 0; i < numSrcs; i++) { // sources not supported
0466: Object src = args.getSource(i);
0467: if (!(src instanceof RenderedImage)
0468: || (sm = ((RenderedImage) src).getSampleModel()) == null
0469: || !ImageUtil.isBinary(sm)) {
0470: return false;
0471: }
0472: }
0473:
0474: if (layout != null) { // validate destination
0475: if ((sm = layout.getSampleModel(null)) != null
0476: && !ImageUtil.isBinary(sm)) {
0477: return false;
0478: }
0479: }
0480:
0481: return true;
0482: }
0483:
0484: /**
0485: * Returns <code>true</code> if the number of bands of all the
0486: * <code>RenderedImage</code> sources and destination are the same.
0487: *
0488: * @throws ClassCastException if any source is not
0489: * <code>RenderedImage</code>.
0490: */
0491: public static boolean hasSameNumBands(ParameterBlock args,
0492: ImageLayout layout) {
0493: int numSrcs = args.getNumSources();
0494:
0495: if (numSrcs > 0) {
0496: RenderedImage src = args.getRenderedSource(0);
0497: int numBands = src.getSampleModel().getNumBands();
0498:
0499: for (int i = 1; i < numSrcs; i++) {
0500: src = args.getRenderedSource(i);
0501: if (src.getSampleModel().getNumBands() != numBands) {
0502: return false;
0503: }
0504: }
0505:
0506: if (layout != null) {
0507: SampleModel sm = layout.getSampleModel(null);
0508: if (sm != null && sm.getNumBands() != numBands) {
0509: return false;
0510: }
0511: }
0512: }
0513:
0514: return true;
0515: }
0516:
0517: /**
0518: * Returns the most efficient FormatTag that is compatible with
0519: * the destination raster and all source rasters.
0520: *
0521: * @param srcs the source <code>Raster</code>; may be <code>null</code>.
0522: * @param dst the destination <code>Raster</code>.
0523: */
0524: public static int findCompatibleTag(Raster srcs[], Raster dst) {
0525: SampleModel dstSM = dst.getSampleModel();
0526: int dstDT = dstSM.getDataType();
0527:
0528: int defaultDataType = dstSM.getDataType();
0529:
0530: boolean allComponentSampleModel = dstSM instanceof ComponentSampleModel;
0531: boolean allBinary = ImageUtil.isBinary(dstSM);
0532:
0533: // use highest precision datatype of all srcs & dst
0534: if (srcs != null) {
0535: int numSources = srcs.length;
0536: int i;
0537: for (i = 0; i < numSources; i++) {
0538: SampleModel srcSampleModel = srcs[i].getSampleModel();
0539: if (!(srcSampleModel instanceof ComponentSampleModel)) {
0540: allComponentSampleModel = false;
0541: }
0542: if (!ImageUtil.isBinary(srcSampleModel)) {
0543: allBinary = false;
0544: }
0545: int srcDataType = srcSampleModel.getTransferType();
0546: if (srcDataType > defaultDataType) {
0547: defaultDataType = srcDataType;
0548: }
0549: }
0550: }
0551:
0552: if (allBinary) {
0553: // The copy flag is not set until the mediaLibImage is
0554: // created as knowing this information requires too much
0555: // processing to determine here.
0556: return DataBuffer.TYPE_BYTE | BINARY;
0557: }
0558:
0559: if (!allComponentSampleModel) {
0560: if ((defaultDataType == DataBuffer.TYPE_BYTE)
0561: || (defaultDataType == DataBuffer.TYPE_USHORT)
0562: || (defaultDataType == DataBuffer.TYPE_SHORT)) {
0563: defaultDataType = DataBuffer.TYPE_INT;
0564: }
0565: }
0566:
0567: int tag = defaultDataType | COPIED;
0568:
0569: if (!allComponentSampleModel) {
0570: return tag;
0571: }
0572:
0573: // see if they all have same DT and are pixelSequential
0574:
0575: SampleModel srcSM[];
0576: if (srcs == null) {
0577: srcSM = new SampleModel[0];
0578: } else {
0579: srcSM = new SampleModel[srcs.length];
0580: }
0581: for (int i = 0; i < srcSM.length; i++) {
0582: srcSM[i] = srcs[i].getSampleModel();
0583: if (dstDT != srcSM[i].getDataType()) {
0584: return tag;
0585: }
0586: }
0587: if (isPixelSequential(dstSM)) {
0588: for (int i = 0; i < srcSM.length; i++) {
0589: if (!isPixelSequential(srcSM[i])) {
0590: return tag;
0591: }
0592: }
0593: for (int i = 0; i < srcSM.length; i++) {
0594: if (!hasMatchingBandOffsets(
0595: (ComponentSampleModel) dstSM,
0596: (ComponentSampleModel) srcSM[i])) {
0597: return tag;
0598: }
0599: }
0600: return dstDT | UNCOPIED;
0601: }
0602: return tag;
0603: }
0604:
0605: /**
0606: * Determines if the SampleModel stores data in a way that can
0607: * be represented by a mediaLibImage without copying
0608: */
0609: public static boolean isPixelSequential(SampleModel sm) {
0610: ComponentSampleModel csm = null;
0611: if (sm instanceof ComponentSampleModel) {
0612: csm = (ComponentSampleModel) sm;
0613: } else {
0614: return false;
0615: }
0616: int pixelStride = csm.getPixelStride();
0617: int bandOffsets[] = csm.getBandOffsets();
0618: int bankIndices[] = csm.getBankIndices();
0619: if (pixelStride != bandOffsets.length) {
0620: return false;
0621: }
0622: for (int i = 0; i < bandOffsets.length; i++) {
0623: if (bandOffsets[i] >= pixelStride
0624: || bankIndices[i] != bankIndices[0]) {
0625: return false;
0626: }
0627: for (int j = i + 1; j < bandOffsets.length; j++) {
0628: if (bandOffsets[i] == bandOffsets[j]) {
0629: return false;
0630: }
0631: }
0632: }
0633: return true;
0634: }
0635:
0636: /**
0637: * Determines if the src ComponentSampleModel and dst
0638: * ComponentSampleModel have matching band offsets. If they
0639: * don't mediaLib can't deal with the image without a copy.
0640: */
0641: public static boolean hasMatchingBandOffsets(
0642: ComponentSampleModel dst, ComponentSampleModel src) {
0643: int srcBandOffsets[] = dst.getBandOffsets();
0644: int dstBandOffsets[] = src.getBandOffsets();
0645: if (srcBandOffsets.length != dstBandOffsets.length) {
0646: return false;
0647: }
0648: for (int i = 0; i < srcBandOffsets.length; i++) {
0649: if (srcBandOffsets[i] != dstBandOffsets[i]) {
0650: return false;
0651: }
0652: }
0653: return true;
0654: }
0655:
0656: public static int getMediaLibDataType(int formatTag) {
0657: int dataType = formatTag & DATATYPE_MASK;
0658: switch (dataType) {
0659: case DataBuffer.TYPE_BYTE:
0660: return Constants.MLIB_BYTE;
0661: case DataBuffer.TYPE_USHORT:
0662: return Constants.MLIB_USHORT;
0663: case DataBuffer.TYPE_SHORT:
0664: return Constants.MLIB_SHORT;
0665: case DataBuffer.TYPE_INT:
0666: return Constants.MLIB_INT;
0667: case DataBuffer.TYPE_DOUBLE:
0668: return Constants.MLIB_DOUBLE;
0669: case DataBuffer.TYPE_FLOAT:
0670: return Constants.MLIB_FLOAT;
0671: }
0672: return -1;
0673: }
0674:
0675: /**
0676: * Constructs a MediaLibAccessor object out of a Raster, Rectangle
0677: * and formatTag returned from MediaLibAccessor.findCompatibleTag().
0678: *
0679: * In the case of binary data the copy mask bits of the formatTag
0680: * will be reset within the constructor according to whether the
0681: * data are in fact copied. This cannot be easily determined before
0682: * the data are actually copied.
0683: */
0684: public MediaLibAccessor(Raster raster, Rectangle rect,
0685: int formatTag, boolean preferPacked) {
0686: areBinaryDataPacked = preferPacked;
0687:
0688: this .raster = raster;
0689: this .rect = new Rectangle(rect);
0690: this .formatTag = formatTag;
0691:
0692: if (isBinary()) {
0693: // Set binary-specific fields and return.
0694: numBands = 1;
0695: bandOffsets = new int[] { 0 };
0696:
0697: int mlibType;
0698: int scanlineStride;
0699: byte[] bdata;
0700: mlimages = new mediaLibImage[1];
0701:
0702: if (areBinaryDataPacked) {
0703: mlibType = Constants.MLIB_BIT;
0704: scanlineStride = (rect.width + 7) / 8;
0705: bdata = ImageUtil.getPackedBinaryData(raster, rect);
0706:
0707: // Update format tag depending on whether the data were copied.
0708: if (bdata == ((DataBufferByte) raster.getDataBuffer())
0709: .getData()) {
0710: this .formatTag |= UNCOPIED;
0711: } else {
0712: this .formatTag |= COPIED;
0713: }
0714: } else { // unpacked
0715: mlibType = Constants.MLIB_BYTE;
0716: scanlineStride = rect.width;
0717: bdata = ImageUtil.getUnpackedBinaryData(raster, rect);
0718: this .formatTag |= COPIED;
0719: }
0720:
0721: mlimages[0] = new mediaLibImage(mlibType, 1, rect.width,
0722: rect.height, scanlineStride, 0, bdata);
0723:
0724: return;
0725: }
0726:
0727: if ((formatTag & COPY_MASK) == UNCOPIED) {
0728: ComponentSampleModel csm = (ComponentSampleModel) raster
0729: .getSampleModel();
0730:
0731: numBands = csm.getNumBands();
0732: bandOffsets = csm.getBandOffsets();
0733: int dataOffset = raster.getDataBuffer().getOffset();
0734: dataOffset += (rect.y - raster.getSampleModelTranslateY())
0735: * csm.getScanlineStride()
0736: + (rect.x - raster.getSampleModelTranslateX())
0737: * csm.getPixelStride();
0738:
0739: // dataoffset should and is in terms of dataElements
0740:
0741: // scanline stride should be in terms of dataElements
0742: int scanlineStride = csm.getScanlineStride();
0743:
0744: switch (formatTag & DATATYPE_MASK) {
0745: case DataBuffer.TYPE_BYTE:
0746: DataBufferByte dbb = (DataBufferByte) raster
0747: .getDataBuffer();
0748: mlimages = new mediaLibImage[1];
0749: mlimages[0] = new mediaLibImage(Constants.MLIB_BYTE,
0750: numBands, rect.width, rect.height,
0751: scanlineStride, dataOffset, dbb.getData());
0752: break;
0753:
0754: case DataBuffer.TYPE_USHORT:
0755: DataBufferUShort dbus = (DataBufferUShort) raster
0756: .getDataBuffer();
0757: mlimages = new mediaLibImage[1];
0758: mlimages[0] = new mediaLibImage(Constants.MLIB_USHORT,
0759: numBands, rect.width, rect.height,
0760: scanlineStride, dataOffset, dbus.getData());
0761: break;
0762: case DataBuffer.TYPE_SHORT:
0763: DataBufferShort dbs = (DataBufferShort) raster
0764: .getDataBuffer();
0765: mlimages = new mediaLibImage[1];
0766: mlimages[0] = new mediaLibImage(Constants.MLIB_SHORT,
0767: numBands, rect.width, rect.height,
0768: scanlineStride, dataOffset, dbs.getData());
0769: break;
0770: case DataBuffer.TYPE_INT:
0771: DataBufferInt dbi = (DataBufferInt) raster
0772: .getDataBuffer();
0773: mlimages = new mediaLibImage[1];
0774: mlimages[0] = new mediaLibImage(Constants.MLIB_INT,
0775: numBands, rect.width, rect.height,
0776: scanlineStride, dataOffset, dbi.getData());
0777: break;
0778: case DataBuffer.TYPE_FLOAT:
0779: DataBuffer dbf = raster.getDataBuffer();
0780: mlimages = new mediaLibImage[1];
0781: mlimages[0] = new mediaLibImage(Constants.MLIB_FLOAT,
0782: numBands, rect.width, rect.height,
0783: scanlineStride, dataOffset, DataBufferUtils
0784: .getDataFloat(dbf));
0785: break;
0786: case DataBuffer.TYPE_DOUBLE:
0787: DataBuffer dbd = raster.getDataBuffer();
0788: mlimages = new mediaLibImage[1];
0789: mlimages[0] = new mediaLibImage(Constants.MLIB_DOUBLE,
0790: numBands, rect.width, rect.height,
0791: scanlineStride, dataOffset, DataBufferUtils
0792: .getDataDouble(dbd));
0793: break;
0794: default:
0795: throw new IllegalArgumentException(
0796: (formatTag & DATATYPE_MASK)
0797: + JaiI18N
0798: .getString("MediaLibAccessor1"));
0799: }
0800: } else {
0801: // Copying the data because we can't deal with it
0802: numBands = raster.getNumBands();
0803: bandOffsets = new int[numBands];
0804: for (int i = 0; i < numBands; i++) {
0805: bandOffsets[i] = i;
0806: }
0807: int scanlineStride = rect.width * numBands;
0808:
0809: switch (formatTag & DATATYPE_MASK) {
0810: case DataBuffer.TYPE_BYTE:
0811: byte bdata[] = new byte[rect.width * rect.height
0812: * numBands];
0813: mlimages = new mediaLibImage[1];
0814: mlimages[0] = new mediaLibImage(Constants.MLIB_BYTE,
0815: numBands, rect.width, rect.height,
0816: scanlineStride, 0, bdata);
0817: break;
0818: case DataBuffer.TYPE_USHORT:
0819: short usdata[] = new short[rect.width * rect.height
0820: * numBands];
0821: mlimages = new mediaLibImage[1];
0822: mlimages[0] = new mediaLibImage(Constants.MLIB_USHORT,
0823: numBands, rect.width, rect.height,
0824: scanlineStride, 0, usdata);
0825: break;
0826: case DataBuffer.TYPE_SHORT:
0827: short sdata[] = new short[rect.width * rect.height
0828: * numBands];
0829: mlimages = new mediaLibImage[1];
0830: mlimages[0] = new mediaLibImage(Constants.MLIB_SHORT,
0831: numBands, rect.width, rect.height,
0832: scanlineStride, 0, sdata);
0833: break;
0834: case DataBuffer.TYPE_INT:
0835: int idata[] = new int[rect.width * rect.height
0836: * numBands];
0837: mlimages = new mediaLibImage[1];
0838: mlimages[0] = new mediaLibImage(Constants.MLIB_INT,
0839: numBands, rect.width, rect.height,
0840: scanlineStride, 0, idata);
0841: break;
0842: case DataBuffer.TYPE_FLOAT:
0843: float fdata[] = new float[rect.width * rect.height
0844: * numBands];
0845: mlimages = new mediaLibImage[1];
0846: mlimages[0] = new mediaLibImage(Constants.MLIB_FLOAT,
0847: numBands, rect.width, rect.height,
0848: scanlineStride, 0, fdata);
0849: break;
0850: case DataBuffer.TYPE_DOUBLE:
0851: double ddata[] = new double[rect.width * rect.height
0852: * numBands];
0853: mlimages = new mediaLibImage[1];
0854: mlimages[0] = new mediaLibImage(Constants.MLIB_DOUBLE,
0855: numBands, rect.width, rect.height,
0856: scanlineStride, 0, ddata);
0857: break;
0858: default:
0859: throw new IllegalArgumentException(
0860: (formatTag & DATATYPE_MASK)
0861: + JaiI18N
0862: .getString("MediaLibAccessor1"));
0863: }
0864: copyDataFromRaster();
0865: }
0866: }
0867:
0868: /**
0869: * Constructs a MediaLibAccessor object out of a Raster, Rectangle
0870: * and formatTag returned from MediaLibAccessor.findCompatibleTag().
0871: */
0872: public MediaLibAccessor(Raster raster, Rectangle rect, int formatTag) {
0873: this (raster, rect, formatTag, false);
0874: }
0875:
0876: /**
0877: * Returns <code>true</code> if the <code>MediaLibAccessor</code>
0878: * represents binary data.
0879: */
0880: public boolean isBinary() {
0881: return ((formatTag & BINARY_MASK) == BINARY);
0882: }
0883:
0884: /**
0885: * Returns an array of mediaLibImages which represents the input raster.
0886: * An array is returned instead of a single mediaLibImage because
0887: * in some cases, an input Raster can't be represented by one
0888: * mediaLibImage (unless copying is done) but can be represented
0889: * by several mediaLibImages without copying.
0890: */
0891: public mediaLibImage[] getMediaLibImages() {
0892: return mlimages;
0893: }
0894:
0895: /**
0896: * Returns the data type of the RasterAccessor object. Note that
0897: * this datatype is not necessarily the same data type as the
0898: * underlying raster.
0899: */
0900: public int getDataType() {
0901: return formatTag & DATATYPE_MASK;
0902: }
0903:
0904: /**
0905: * Returns true if the MediaLibAccessors's data is copied from it's
0906: * raster.
0907: */
0908: public boolean isDataCopy() {
0909: return ((formatTag & COPY_MASK) == COPIED);
0910: }
0911:
0912: /** Returns the bandOffsets. */
0913: public int[] getBandOffsets() {
0914: return bandOffsets;
0915: }
0916:
0917: /**
0918: * Returns parameters in the appropriate order if MediaLibAccessor
0919: * has reordered the bands or is attempting to make a
0920: * BandSequential image look like multiple PixelSequentialImages
0921: */
0922: public int[] getIntParameters(int band, int params[]) {
0923: int returnParams[] = new int[numBands];
0924: for (int i = 0; i < numBands; i++) {
0925: returnParams[i] = params[bandOffsets[i + band]];
0926: }
0927: return returnParams;
0928: }
0929:
0930: /**
0931: * Returns parameters in the appropriate order if MediaLibAccessor
0932: * has reordered the bands or is attempting to make a
0933: * BandSequential image look like multiple PixelSequentialImages
0934: */
0935: public int[][] getIntArrayParameters(int band, int[][] params) {
0936: int returnParams[][] = new int[numBands][];
0937: for (int i = 0; i < numBands; i++) {
0938: returnParams[i] = params[bandOffsets[i + band]];
0939: }
0940: return returnParams;
0941: }
0942:
0943: /**
0944: * Returns parameters in the appropriate order if MediaLibAccessor
0945: * has reordered the bands or is attempting to make a
0946: * BandSequential image look like multiple PixelSequentialImages
0947: */
0948: public double[] getDoubleParameters(int band, double params[]) {
0949: double returnParams[] = new double[numBands];
0950: for (int i = 0; i < numBands; i++) {
0951: returnParams[i] = params[bandOffsets[i + band]];
0952: }
0953: return returnParams;
0954: }
0955:
0956: /**
0957: * Copy data from Raster to MediaLib image
0958: */
0959: private void copyDataFromRaster() {
0960: // Writeback should only be necessary on destRasters which
0961: // should be writable so this cast should succeed.
0962:
0963: if (raster.getSampleModel() instanceof ComponentSampleModel) {
0964: ComponentSampleModel csm = (ComponentSampleModel) raster
0965: .getSampleModel();
0966: int rasScanlineStride = csm.getScanlineStride();
0967: int rasPixelStride = csm.getPixelStride();
0968:
0969: int subRasterOffset = (rect.y - raster
0970: .getSampleModelTranslateY())
0971: * rasScanlineStride
0972: + (rect.x - raster.getSampleModelTranslateX())
0973: * rasPixelStride;
0974:
0975: int rasBankIndices[] = csm.getBankIndices();
0976: int rasBandOffsets[] = csm.getBandOffsets();
0977: int rasDataOffsets[] = raster.getDataBuffer().getOffsets();
0978:
0979: if (rasDataOffsets.length == 1) {
0980: for (int i = 0; i < numBands; i++) {
0981: rasBandOffsets[i] += rasDataOffsets[0]
0982: + subRasterOffset;
0983: }
0984: } else if (rasDataOffsets.length == rasBandOffsets.length) {
0985: for (int i = 0; i < numBands; i++) {
0986: rasBandOffsets[i] += rasDataOffsets[i]
0987: + subRasterOffset;
0988: }
0989: }
0990:
0991: Object mlibDataArray = null;
0992: switch (getDataType()) {
0993: case DataBuffer.TYPE_BYTE:
0994: byte bArray[][] = new byte[numBands][];
0995: for (int i = 0; i < numBands; i++) {
0996: bArray[i] = mlimages[0].getByteData();
0997: }
0998: mlibDataArray = bArray;
0999: break;
1000: case DataBuffer.TYPE_USHORT:
1001: short usArray[][] = new short[numBands][];
1002: for (int i = 0; i < numBands; i++) {
1003: usArray[i] = mlimages[0].getUShortData();
1004: }
1005: mlibDataArray = usArray;
1006: break;
1007: case DataBuffer.TYPE_SHORT:
1008: short sArray[][] = new short[numBands][];
1009: for (int i = 0; i < numBands; i++) {
1010: sArray[i] = mlimages[0].getShortData();
1011: }
1012: mlibDataArray = sArray;
1013: break;
1014: case DataBuffer.TYPE_INT:
1015: int iArray[][] = new int[numBands][];
1016: for (int i = 0; i < numBands; i++) {
1017: iArray[i] = mlimages[0].getIntData();
1018: }
1019: mlibDataArray = iArray;
1020: break;
1021: case DataBuffer.TYPE_FLOAT:
1022: float fArray[][] = new float[numBands][];
1023: for (int i = 0; i < numBands; i++) {
1024: fArray[i] = mlimages[0].getFloatData();
1025: }
1026: mlibDataArray = fArray;
1027: break;
1028: case DataBuffer.TYPE_DOUBLE:
1029: double dArray[][] = new double[numBands][];
1030: for (int i = 0; i < numBands; i++) {
1031: dArray[i] = mlimages[0].getDoubleData();
1032: }
1033: mlibDataArray = dArray;
1034: break;
1035: }
1036:
1037: Object rasDataArray = null;
1038: switch (csm.getDataType()) {
1039: case DataBuffer.TYPE_BYTE: {
1040: DataBufferByte dbb = (DataBufferByte) raster
1041: .getDataBuffer();
1042: byte rasByteDataArray[][] = new byte[numBands][];
1043: for (int i = 0; i < numBands; i++) {
1044: rasByteDataArray[i] = dbb
1045: .getData(rasBankIndices[i]);
1046: }
1047: rasDataArray = rasByteDataArray;
1048: }
1049: break;
1050: case DataBuffer.TYPE_USHORT: {
1051: DataBufferUShort dbus = (DataBufferUShort) raster
1052: .getDataBuffer();
1053: short rasUShortDataArray[][] = new short[numBands][];
1054: for (int i = 0; i < numBands; i++) {
1055: rasUShortDataArray[i] = dbus
1056: .getData(rasBankIndices[i]);
1057: }
1058: rasDataArray = rasUShortDataArray;
1059: }
1060: break;
1061: case DataBuffer.TYPE_SHORT: {
1062: DataBufferShort dbs = (DataBufferShort) raster
1063: .getDataBuffer();
1064: short rasShortDataArray[][] = new short[numBands][];
1065: for (int i = 0; i < numBands; i++) {
1066: rasShortDataArray[i] = dbs
1067: .getData(rasBankIndices[i]);
1068: }
1069: rasDataArray = rasShortDataArray;
1070: }
1071: break;
1072: case DataBuffer.TYPE_INT: {
1073: DataBufferInt dbi = (DataBufferInt) raster
1074: .getDataBuffer();
1075: int rasIntDataArray[][] = new int[numBands][];
1076: for (int i = 0; i < numBands; i++) {
1077: rasIntDataArray[i] = dbi.getData(rasBankIndices[i]);
1078: }
1079: rasDataArray = rasIntDataArray;
1080: }
1081: break;
1082: case DataBuffer.TYPE_FLOAT: {
1083: DataBuffer dbf = raster.getDataBuffer();
1084: float rasFloatDataArray[][] = new float[numBands][];
1085: for (int i = 0; i < numBands; i++) {
1086: rasFloatDataArray[i] = DataBufferUtils
1087: .getDataFloat(dbf, rasBankIndices[i]);
1088: }
1089: rasDataArray = rasFloatDataArray;
1090: }
1091: break;
1092: case DataBuffer.TYPE_DOUBLE: {
1093: DataBuffer dbd = raster.getDataBuffer();
1094: double rasDoubleDataArray[][] = new double[numBands][];
1095: for (int i = 0; i < numBands; i++) {
1096: rasDoubleDataArray[i] = DataBufferUtils
1097: .getDataDouble(dbd, rasBankIndices[i]);
1098: }
1099: rasDataArray = rasDoubleDataArray;
1100: }
1101: break;
1102: }
1103:
1104: // dst = mlib && src = ras
1105: Image.Reformat(mlibDataArray, rasDataArray, numBands,
1106: rect.width, rect.height, getMediaLibDataType(this
1107: .getDataType()), bandOffsets, rect.width
1108: * numBands, numBands,
1109: getMediaLibDataType(csm.getDataType()),
1110: rasBandOffsets, rasScanlineStride, rasPixelStride);
1111: } else {
1112: // If COPIED and the raster doesn't have ComponentSampleModel
1113: // data is moved with getPixel/setPixel (even byte/short)
1114: switch (getDataType()) {
1115: case DataBuffer.TYPE_INT:
1116: raster.getPixels(rect.x, rect.y, rect.width,
1117: rect.height, mlimages[0].getIntData());
1118: break;
1119: case DataBuffer.TYPE_FLOAT:
1120: raster.getPixels(rect.x, rect.y, rect.width,
1121: rect.height, mlimages[0].getFloatData());
1122: break;
1123: case DataBuffer.TYPE_DOUBLE:
1124: raster.getPixels(rect.x, rect.y, rect.width,
1125: rect.height, mlimages[0].getDoubleData());
1126: break;
1127: }
1128: }
1129: }
1130:
1131: /**
1132: * Copies data back into the MediaLibAccessor's raster. Note that
1133: * the data is casted from the intermediate data format to
1134: * the raster's format. If clamping is needed, the call
1135: * clampDataArrays() method needs to be called before
1136: * calling the copyDataToRaster() method.
1137: */
1138: public void copyDataToRaster() {
1139: if (isDataCopy()) {
1140:
1141: if (isBinary()) {
1142: if (areBinaryDataPacked) {
1143: ImageUtil.setPackedBinaryData(mlimages[0]
1144: .getBitData(), (WritableRaster) raster,
1145: rect);
1146: } else { // unpacked
1147: ImageUtil.setUnpackedBinaryData(mlimages[0]
1148: .getByteData(), (WritableRaster) raster,
1149: rect);
1150: }
1151: return;
1152: }
1153:
1154: // Writeback should only be necessary on destRasters which
1155: // should be writable so this cast should succeed.
1156: WritableRaster wr = (WritableRaster) raster;
1157:
1158: if (wr.getSampleModel() instanceof ComponentSampleModel) {
1159: ComponentSampleModel csm = (ComponentSampleModel) wr
1160: .getSampleModel();
1161: int rasScanlineStride = csm.getScanlineStride();
1162: int rasPixelStride = csm.getPixelStride();
1163:
1164: int subRasterOffset = (rect.y - raster
1165: .getSampleModelTranslateY())
1166: * rasScanlineStride
1167: + (rect.x - raster.getSampleModelTranslateX())
1168: * rasPixelStride;
1169:
1170: int rasBankIndices[] = csm.getBankIndices();
1171: int rasBandOffsets[] = csm.getBandOffsets();
1172: int rasDataOffsets[] = raster.getDataBuffer()
1173: .getOffsets();
1174:
1175: if (rasDataOffsets.length == 1) {
1176: for (int i = 0; i < numBands; i++) {
1177: rasBandOffsets[i] += rasDataOffsets[0]
1178: + subRasterOffset;
1179: }
1180: } else if (rasDataOffsets.length == rasBandOffsets.length) {
1181: for (int i = 0; i < numBands; i++) {
1182: rasBandOffsets[i] += rasDataOffsets[i]
1183: + subRasterOffset;
1184: }
1185: }
1186:
1187: Object mlibDataArray = null;
1188: switch (getDataType()) {
1189: case DataBuffer.TYPE_BYTE:
1190: byte bArray[][] = new byte[numBands][];
1191: for (int i = 0; i < numBands; i++) {
1192: bArray[i] = mlimages[0].getByteData();
1193: }
1194: mlibDataArray = bArray;
1195: break;
1196: case DataBuffer.TYPE_USHORT:
1197: short usArray[][] = new short[numBands][];
1198: for (int i = 0; i < numBands; i++) {
1199: usArray[i] = mlimages[0].getUShortData();
1200: }
1201: mlibDataArray = usArray;
1202: break;
1203: case DataBuffer.TYPE_SHORT:
1204: short sArray[][] = new short[numBands][];
1205: for (int i = 0; i < numBands; i++) {
1206: sArray[i] = mlimages[0].getShortData();
1207: }
1208: mlibDataArray = sArray;
1209: break;
1210: case DataBuffer.TYPE_INT:
1211: int iArray[][] = new int[numBands][];
1212: for (int i = 0; i < numBands; i++) {
1213: iArray[i] = mlimages[0].getIntData();
1214: }
1215: mlibDataArray = iArray;
1216: break;
1217: case DataBuffer.TYPE_FLOAT:
1218: float fArray[][] = new float[numBands][];
1219: for (int i = 0; i < numBands; i++) {
1220: fArray[i] = mlimages[0].getFloatData();
1221: }
1222: mlibDataArray = fArray;
1223: break;
1224: case DataBuffer.TYPE_DOUBLE:
1225: double dArray[][] = new double[numBands][];
1226: for (int i = 0; i < numBands; i++) {
1227: dArray[i] = mlimages[0].getDoubleData();
1228: }
1229: mlibDataArray = dArray;
1230: break;
1231: }
1232:
1233: byte tmpDataArray[] = null;
1234: Object rasDataArray = null;
1235: switch (csm.getDataType()) {
1236: case DataBuffer.TYPE_BYTE: {
1237: DataBufferByte dbb = (DataBufferByte) raster
1238: .getDataBuffer();
1239: byte rasByteDataArray[][] = new byte[numBands][];
1240: for (int i = 0; i < numBands; i++) {
1241: rasByteDataArray[i] = dbb
1242: .getData(rasBankIndices[i]);
1243: }
1244: tmpDataArray = rasByteDataArray[0];
1245: rasDataArray = rasByteDataArray;
1246: }
1247: break;
1248: case DataBuffer.TYPE_USHORT: {
1249: DataBufferUShort dbus = (DataBufferUShort) raster
1250: .getDataBuffer();
1251: short rasUShortDataArray[][] = new short[numBands][];
1252: for (int i = 0; i < numBands; i++) {
1253: rasUShortDataArray[i] = dbus
1254: .getData(rasBankIndices[i]);
1255: }
1256: rasDataArray = rasUShortDataArray;
1257: }
1258: break;
1259: case DataBuffer.TYPE_SHORT: {
1260: DataBufferShort dbs = (DataBufferShort) raster
1261: .getDataBuffer();
1262: short rasShortDataArray[][] = new short[numBands][];
1263: for (int i = 0; i < numBands; i++) {
1264: rasShortDataArray[i] = dbs
1265: .getData(rasBankIndices[i]);
1266: }
1267: rasDataArray = rasShortDataArray;
1268: }
1269: break;
1270: case DataBuffer.TYPE_INT: {
1271: DataBufferInt dbi = (DataBufferInt) raster
1272: .getDataBuffer();
1273: int rasIntDataArray[][] = new int[numBands][];
1274: for (int i = 0; i < numBands; i++) {
1275: rasIntDataArray[i] = dbi
1276: .getData(rasBankIndices[i]);
1277: }
1278: rasDataArray = rasIntDataArray;
1279: }
1280: break;
1281: case DataBuffer.TYPE_FLOAT: {
1282: DataBuffer dbf = raster.getDataBuffer();
1283: float rasFloatDataArray[][] = new float[numBands][];
1284: for (int i = 0; i < numBands; i++) {
1285: rasFloatDataArray[i] = DataBufferUtils
1286: .getDataFloat(dbf, rasBankIndices[i]);
1287: }
1288: rasDataArray = rasFloatDataArray;
1289: }
1290: break;
1291: case DataBuffer.TYPE_DOUBLE: {
1292: DataBuffer dbd = raster.getDataBuffer();
1293: double rasDoubleDataArray[][] = new double[numBands][];
1294: for (int i = 0; i < numBands; i++) {
1295: rasDoubleDataArray[i] = DataBufferUtils
1296: .getDataDouble(dbd, rasBankIndices[i]);
1297: }
1298: rasDataArray = rasDoubleDataArray;
1299: }
1300: break;
1301: }
1302:
1303: // src = mlib && dst = ras
1304: Image.Reformat(rasDataArray, mlibDataArray, numBands,
1305: rect.width, rect.height,
1306: getMediaLibDataType(csm.getDataType()),
1307: rasBandOffsets, rasScanlineStride,
1308: rasPixelStride, getMediaLibDataType(this
1309: .getDataType()), bandOffsets,
1310: rect.width * numBands, numBands);
1311: } else {
1312: // If COPIED and the raster doesn't have ComponentSampleModel
1313: // data is moved with getPixel/setPixel (even byte/short)
1314: switch (getDataType()) {
1315: case DataBuffer.TYPE_INT:
1316: wr.setPixels(rect.x, rect.y, rect.width,
1317: rect.height, mlimages[0].getIntData());
1318: break;
1319: case DataBuffer.TYPE_FLOAT:
1320: wr.setPixels(rect.x, rect.y, rect.width,
1321: rect.height, mlimages[0].getFloatData());
1322: break;
1323: case DataBuffer.TYPE_DOUBLE:
1324: wr.setPixels(rect.x, rect.y, rect.width,
1325: rect.height, mlimages[0].getDoubleData());
1326: break;
1327: }
1328: }
1329: }
1330: }
1331:
1332: /**
1333: * Clamps data array values to a range that the underlying raster
1334: * can deal with. For example, if the underlying raster stores
1335: * data as bytes, but the samples ares unpacked into integer arrays by
1336: * the RasterAccessor object for an operation, the operation will
1337: * need to call clampDataArrays() so that the data in the int
1338: * arrays is restricted to the range 0..255 before a setPixels()
1339: * call is made on the underlying raster. Note that some
1340: * operations (for example, lookup) can guarantee that their
1341: * results don't need clamping so they can call
1342: * RasterAccessor.copyDataToRaster() without first calling this
1343: * function.
1344: */
1345: public void clampDataArrays() {
1346: if (!isDataCopy()) {
1347: return;
1348: }
1349:
1350: // additonal medialib check: If it's a componentSampleModel
1351: // we get a free cast when we call medialibWrapper.Reformat
1352: // to copy the data to the source. So we don't need to cast
1353: // here.
1354: if (raster.getSampleModel() instanceof ComponentSampleModel) {
1355: return;
1356: }
1357:
1358: int bits[] = raster.getSampleModel().getSampleSize();
1359:
1360: // Do we even need a clamp? We do if there's any band
1361: // of the source image stored in that's less than 32 bits
1362: // and is stored in a byte, short or int format. (The automatic
1363: // cast's between floats/doubles and 32-bit ints in setPixel()
1364: // generall do what we want.)
1365:
1366: boolean needClamp = false;
1367: boolean uniformBitSize = true;
1368: for (int i = 0; i < bits.length; i++) {
1369: int bitSize = bits[0];
1370: if (bits[i] < 32) {
1371: needClamp = true;
1372: }
1373: if (bits[i] != bitSize) {
1374: uniformBitSize = false;
1375: }
1376: }
1377:
1378: if (!needClamp) {
1379: return;
1380: }
1381:
1382: int dataType = raster.getDataBuffer().getDataType();
1383: double hiVals[] = new double[bits.length];
1384: double loVals[] = new double[bits.length];
1385:
1386: if (dataType == DataBuffer.TYPE_USHORT && uniformBitSize
1387: && bits[0] == 16) {
1388: for (int i = 0; i < bits.length; i++) {
1389: hiVals[i] = (double) 0xFFFF;
1390: loVals[i] = (double) 0;
1391: }
1392: } else if (dataType == DataBuffer.TYPE_SHORT && uniformBitSize
1393: && bits[0] == 16) {
1394: for (int i = 0; i < bits.length; i++) {
1395: hiVals[i] = (double) Short.MAX_VALUE;
1396: loVals[i] = (double) Short.MIN_VALUE;
1397: }
1398: } else if (dataType == DataBuffer.TYPE_INT && uniformBitSize
1399: && bits[0] == 32) {
1400: for (int i = 0; i < bits.length; i++) {
1401: hiVals[i] = (double) Integer.MAX_VALUE;
1402: loVals[i] = (double) Integer.MIN_VALUE;
1403: }
1404: } else {
1405: for (int i = 0; i < bits.length; i++) {
1406: hiVals[i] = (double) ((1 << bits[i]) - 1);
1407: loVals[i] = (double) 0;
1408: }
1409: }
1410: clampDataArray(hiVals, loVals);
1411: }
1412:
1413: private void clampDataArray(double hiVals[], double loVals[]) {
1414: switch (getDataType()) {
1415: case DataBuffer.TYPE_INT:
1416: clampIntArrays(toIntArray(hiVals), toIntArray(loVals));
1417: break;
1418: case DataBuffer.TYPE_FLOAT:
1419: clampFloatArrays(toFloatArray(hiVals), toFloatArray(loVals));
1420: break;
1421: case DataBuffer.TYPE_DOUBLE:
1422: clampDoubleArrays(hiVals, loVals);
1423: break;
1424: }
1425: }
1426:
1427: private int[] toIntArray(double vals[]) {
1428: int returnVals[] = new int[vals.length];
1429: for (int i = 0; i < vals.length; i++) {
1430: returnVals[i] = (int) vals[i];
1431: }
1432: return returnVals;
1433: }
1434:
1435: private float[] toFloatArray(double vals[]) {
1436: float returnVals[] = new float[vals.length];
1437: for (int i = 0; i < vals.length; i++) {
1438: returnVals[i] = (float) vals[i];
1439: }
1440: return returnVals;
1441: }
1442:
1443: private void clampIntArrays(int hiVals[], int loVals[]) {
1444: int width = rect.width;
1445: int height = rect.height;
1446: int scanlineStride = numBands * width;
1447: for (int k = 0; k < numBands; k++) {
1448: int data[] = mlimages[0].getIntData();
1449: int scanlineOffset = k;
1450: int hiVal = hiVals[k];
1451: int loVal = loVals[k];
1452: for (int j = 0; j < height; j++) {
1453: int pixelOffset = scanlineOffset;
1454: for (int i = 0; i < width; i++) {
1455: int tmp = data[pixelOffset];
1456: if (tmp < loVal) {
1457: data[pixelOffset] = loVal;
1458: } else if (tmp > hiVal) {
1459: data[pixelOffset] = hiVal;
1460: }
1461: pixelOffset += numBands;
1462: }
1463: scanlineOffset += scanlineStride;
1464: }
1465: }
1466: }
1467:
1468: private void clampFloatArrays(float hiVals[], float loVals[]) {
1469: int width = rect.width;
1470: int height = rect.height;
1471: int scanlineStride = numBands * width;
1472: for (int k = 0; k < numBands; k++) {
1473: float data[] = mlimages[0].getFloatData();
1474: int scanlineOffset = k;
1475: float hiVal = hiVals[k];
1476: float loVal = loVals[k];
1477: for (int j = 0; j < height; j++) {
1478: int pixelOffset = scanlineOffset;
1479: for (int i = 0; i < width; i++) {
1480: float tmp = data[pixelOffset];
1481: if (tmp < loVal) {
1482: data[pixelOffset] = loVal;
1483: } else if (tmp > hiVal) {
1484: data[pixelOffset] = hiVal;
1485: }
1486: pixelOffset += numBands;
1487: }
1488: scanlineOffset += scanlineStride;
1489: }
1490: }
1491: }
1492:
1493: private void clampDoubleArrays(double hiVals[], double loVals[]) {
1494: int width = rect.width;
1495: int height = rect.height;
1496: int scanlineStride = numBands * width;
1497: for (int k = 0; k < numBands; k++) {
1498: double data[] = mlimages[0].getDoubleData();
1499: int scanlineOffset = k;
1500: double hiVal = hiVals[k];
1501: double loVal = loVals[k];
1502: for (int j = 0; j < height; j++) {
1503: int pixelOffset = scanlineOffset;
1504: for (int i = 0; i < width; i++) {
1505: double tmp = data[pixelOffset];
1506: if (tmp < loVal) {
1507: data[pixelOffset] = loVal;
1508: } else if (tmp > hiVal) {
1509: data[pixelOffset] = hiVal;
1510: }
1511: pixelOffset += numBands;
1512: }
1513: scanlineOffset += scanlineStride;
1514: }
1515: }
1516: }
1517: }
1518:
1519: class MediaLibLoadException extends Exception {
1520: MediaLibLoadException() {
1521: super ();
1522: }
1523:
1524: public synchronized Throwable fillInStackTrace() {
1525: return this;
1526: }
1527: }
|