001/* 002 * $RCSfile: MediaLibAccessor.java,v $ 003 * 004 * 005 * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without 008 * modification, are permitted provided that the following conditions 009 * are met: 010 * 011 * - Redistribution of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * 014 * - Redistribution in binary form must reproduce the above copyright 015 * notice, this list of conditions and the following disclaimer in 016 * the documentation and/or other materials provided with the 017 * distribution. 018 * 019 * Neither the name of Sun Microsystems, Inc. or the names of 020 * contributors may be used to endorse or promote products derived 021 * from this software without specific prior written permission. 022 * 023 * This software is provided "AS IS," without a warranty of any 024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 035 * POSSIBILITY OF SUCH DAMAGES. 036 * 037 * You acknowledge that this software is not designed or intended for 038 * use in the design, construction, operation or maintenance of any 039 * nuclear facility. 040 * 041 * $Revision: 1.1 $ 042 * $Date: 2005/02/11 05:01:36 $ 043 * $State: Exp $ 044 */ 045package com.sun.media.imageioimpl.plugins.jpeg2000; 046import java.awt.Rectangle; 047import java.awt.image.ColorModel; 048import java.awt.image.ComponentSampleModel; 049import java.awt.image.ComponentColorModel; 050import java.awt.image.DataBuffer; 051import java.awt.image.DataBufferByte; 052import java.awt.image.DataBufferDouble; 053import java.awt.image.DataBufferFloat; 054import java.awt.image.DataBufferInt; 055import java.awt.image.DataBufferShort; 056import java.awt.image.DataBufferUShort; 057import java.awt.image.MultiPixelPackedSampleModel; 058import java.awt.image.Raster; 059import java.awt.image.SampleModel; 060import java.awt.image.WritableRaster; 061import java.awt.image.RenderedImage; 062import java.awt.image.renderable.ParameterBlock; 063import java.io.FileNotFoundException; 064import java.io.FilePermission; 065import java.io.InputStream; 066import java.io.IOException; 067import java.lang.NoClassDefFoundError; 068import java.security.AccessControlException; 069import java.security.AccessController; 070import java.security.PrivilegedAction; 071 072import com.sun.media.imageioimpl.common.ImageUtil; 073/** 074 * An adapter class for presenting image data in a mediaLibImage 075 * format, even if the data isn't stored that way. MediaLibAccessor 076 * is meant to make the common case (ComponentRasters) and allow 077 * them to be accelerated via medialib. Note that unlike RasterAccessor, 078 * MediaLibAccessor does not work with all cases. In the event that 079 * MediaLibAccessor can not deal with a give collection of Rasters, 080 * findCompatibleTag will return the value MediaLibAccessor.TAG_INCOMPATIBLE. 081 * OpImages that use MediaLibAccessor should be paired with RIF's 082 * which check that findCompatibleTag returns a valid tag before 083 * actually constructing the Mlib OpImage. 084 */ 085 086public class MediaLibAccessor { 087 /** 088 * Value indicating how far COPY_MASK info is shifted to avoid 089 * interfering with the data type info 090 */ 091 private static final int COPY_MASK_SHIFT = 7; 092 093 /* Value indicating how many bits the COPY_MASK is */ 094 private static final int COPY_MASK_SIZE = 1; 095 096 /** The bits of a FormatTag associated with how dataArrays are obtained. */ 097 public static final int COPY_MASK = 0x1 << COPY_MASK_SHIFT; 098 099 /** Flag indicating data is raster's data. */ 100 public static final int UNCOPIED = 0x0 << COPY_MASK_SHIFT; 101 102 /** Flag indicating data is a copy of the raster's data. */ 103 public static final int COPIED = 0x01 << COPY_MASK_SHIFT; 104 105 /** The bits of a FormatTag associated with pixel datatype. */ 106 public static final int DATATYPE_MASK = (0x1 << COPY_MASK_SHIFT) - 1; 107 108 /** 109 * Value indicating how far BINARY_MASK info is shifted to avoid 110 * interfering with the data type and copying info. 111 */ 112 private static final int BINARY_MASK_SHIFT = 113 COPY_MASK_SHIFT+COPY_MASK_SIZE; 114 115 /** Value indicating how many bits the BINARY_MASK is */ 116 private static final int BINARY_MASK_SIZE = 1; 117 118 /** The bits of a FormatTag associated with binary data. */ 119 public static final int BINARY_MASK = 120 ((1 << BINARY_MASK_SIZE) - 1) << BINARY_MASK_SHIFT; 121 122 /** Flag indicating data are not binary. */ 123 public static final int NONBINARY = 0x0 << BINARY_MASK_SHIFT; 124 125 /** Flag indicating data are binary. */ 126 public static final int BINARY = 0x1 << BINARY_MASK_SHIFT; 127 128 /** FormatTag indicating data in byte arrays and uncopied. */ 129 public static final int 130 TAG_BYTE_UNCOPIED = DataBuffer.TYPE_BYTE | UNCOPIED; 131 132 /** FormatTag indicating data in unsigned short arrays and uncopied. */ 133 public static final int 134 TAG_USHORT_UNCOPIED = DataBuffer.TYPE_USHORT | UNCOPIED; 135 136 /** FormatTag indicating data in short arrays and uncopied. */ 137 public static final int 138 TAG_SHORT_UNCOPIED = DataBuffer.TYPE_SHORT | UNCOPIED; 139 140 /** FormatTag indicating data in integer arrays and uncopied. */ 141 public static final int 142 TAG_INT_UNCOPIED = DataBuffer.TYPE_INT | UNCOPIED; 143 144 /** FormatTag indicating data in float arrays and uncopied. */ 145 public static final int 146 TAG_FLOAT_UNCOPIED = DataBuffer.TYPE_FLOAT | UNCOPIED; 147 148 /** FormatTag indicating data in double arrays and uncopied. */ 149 public static final int 150 TAG_DOUBLE_UNCOPIED = DataBuffer.TYPE_DOUBLE | UNCOPIED; 151 152 /** FormatTag indicating data in byte arrays and uncopied. */ 153 public static final int 154 TAG_BYTE_COPIED = DataBuffer.TYPE_BYTE | COPIED; 155 156 /** FormatTag indicating data in unsigned short arrays and copied. */ 157 public static final int 158 TAG_USHORT_COPIED = DataBuffer.TYPE_USHORT | COPIED; 159 160 /** FormatTag indicating data in short arrays and copied. */ 161 public static final int 162 TAG_SHORT_COPIED = DataBuffer.TYPE_SHORT | COPIED; 163 164 /** FormatTag indicating data in short arrays and copied. */ 165 public static final int 166 TAG_INT_COPIED = DataBuffer.TYPE_INT | COPIED; 167 168 /** FormatTag indicating data in float arrays and copied. */ 169 public static final int 170 TAG_FLOAT_COPIED = DataBuffer.TYPE_FLOAT | COPIED; 171 172 /** FormatTag indicating data in double arrays and copied. */ 173 public static final int 174 TAG_DOUBLE_COPIED = DataBuffer.TYPE_DOUBLE | COPIED; 175 176 /** The raster that is the source of pixel data. */ 177 protected Raster raster; 178 179 /** The rectangle of the raster that MediaLibAccessor addresses. */ 180 protected Rectangle rect; 181 182 /** The number of bands per pixel in the data array. */ 183 protected int numBands; 184 185 /** The offsets of each band in the src image */ 186 protected int bandOffsets[]; 187 188 /** Tag indicating the data type of the data and whether its copied */ 189 protected int formatTag; 190 191 192 /** 193 * Whether packed data are preferred when processing binary images. 194 * This tag is ignored if the data are not binary. 195 */ 196 private boolean areBinaryDataPacked = false; 197 198 /** 199 * Returns the most efficient FormatTag that is compatible with 200 * the destination raster and all source rasters. 201 * 202 * @param srcs the source <code>Raster</code>; may be <code>null</code>. 203 * @param dst the destination <code>Raster</code>. 204 */ 205 public static int findCompatibleTag(Raster src) { 206 SampleModel dstSM = src.getSampleModel(); 207 int dstDT = dstSM.getDataType(); 208 209 int defaultDataType = dstSM.getDataType(); 210 211 boolean allComponentSampleModel = 212 dstSM instanceof ComponentSampleModel; 213 boolean allBinary = ImageUtil.isBinary(dstSM); 214 215 if(allBinary) { 216 // The copy flag is not set until the mediaLibImage is 217 // created as knowing this information requires too much 218 // processing to determine here. 219 return DataBuffer.TYPE_BYTE | BINARY; 220 } 221 222 if (!allComponentSampleModel) { 223 if ((defaultDataType == DataBuffer.TYPE_BYTE) || 224 (defaultDataType == DataBuffer.TYPE_USHORT) || 225 (defaultDataType == DataBuffer.TYPE_SHORT)) { 226 defaultDataType = DataBuffer.TYPE_INT; 227 } 228 } 229 230 int tag = defaultDataType | COPIED; 231 232 if (!allComponentSampleModel) { 233 return tag; 234 } 235 236 if (isPixelSequential(dstSM)) 237 return dstDT | UNCOPIED; 238 return tag; 239 } 240 241 /** 242 * Determines if the SampleModel stores data in a way that can 243 * be represented by a mediaLibImage without copying 244 */ 245 public static boolean isPixelSequential(SampleModel sm) { 246 ComponentSampleModel csm = null; 247 if (sm instanceof ComponentSampleModel) { 248 csm = (ComponentSampleModel)sm; 249 } else { 250 return false; 251 } 252 int pixelStride = csm.getPixelStride(); 253 int bandOffsets[] = csm.getBandOffsets(); 254 int bankIndices[] = csm.getBankIndices(); 255 if (pixelStride != bandOffsets.length) { 256 return false; 257 } 258 259 //XXX: for band-selection result 260 if (pixelStride != sm.getNumBands()) 261 return false; 262 263 for (int i = 0; i < bandOffsets.length; i++) { 264 if (bandOffsets[i] >= pixelStride || 265 bankIndices[i] != bankIndices[0]) { 266 return false; 267 } 268 for (int j = i+1; j < bandOffsets.length; j++) { 269 if (bandOffsets[i] == bandOffsets[j]) { 270 return false; 271 } 272 273 //XXX: for BGR images 274 if (bandOffsets[i] != i) 275 return false; 276 } 277 } 278 return true; 279 } 280 281 /** 282 * Returns <code>true</code> if the <code>MediaLibAccessor</code> 283 * represents binary data. 284 */ 285 public boolean isBinary() { 286 return ((formatTag & BINARY_MASK) == BINARY); 287 } 288 289 /** 290 * Returns the data type of the RasterAccessor object. Note that 291 * this datatype is not necessarily the same data type as the 292 * underlying raster. 293 */ 294 public int getDataType() { 295 return formatTag & DATATYPE_MASK; 296 } 297 298 /** 299 * Returns true if the MediaLibAccessors's data is copied from it's 300 * raster. 301 */ 302 public boolean isDataCopy() { 303 return ((formatTag & COPY_MASK) == COPIED); 304 } 305 306 /** Returns the bandOffsets. */ 307 public int[] getBandOffsets() { 308 return bandOffsets; 309 } 310 311 /** 312 * Returns parameters in the appropriate order if MediaLibAccessor 313 * has reordered the bands or is attempting to make a 314 * BandSequential image look like multiple PixelSequentialImages 315 */ 316 public int[] getIntParameters(int band, int params[]) { 317 int returnParams[] = new int[numBands]; 318 for (int i = 0; i < numBands; i++) { 319 returnParams[i] = params[bandOffsets[i+band]]; 320 } 321 return returnParams; 322 } 323 324 /** 325 * Returns parameters in the appropriate order if MediaLibAccessor 326 * has reordered the bands or is attempting to make a 327 * BandSequential image look like multiple PixelSequentialImages 328 */ 329 public int[][] getIntArrayParameters(int band, int[][] params) { 330 int returnParams[][] = new int[numBands][]; 331 for (int i = 0; i < numBands; i++) { 332 returnParams[i] = params[bandOffsets[i+band]]; 333 } 334 return returnParams; 335 } 336 337 /** 338 * Returns parameters in the appropriate order if MediaLibAccessor 339 * has reordered the bands or is attempting to make a 340 * BandSequential image look like multiple PixelSequentialImages 341 */ 342 public double[] getDoubleParameters(int band, double params[]) { 343 double returnParams[] = new double[numBands]; 344 for (int i = 0; i < numBands; i++) { 345 returnParams[i] = params[bandOffsets[i+band]]; 346 } 347 return returnParams; 348 } 349 350 351 352 private int[] toIntArray(double vals[]) { 353 int returnVals[] = new int[vals.length]; 354 for (int i = 0; i < vals.length; i++) { 355 returnVals[i] = (int)vals[i]; 356 } 357 return returnVals; 358 } 359 360 private float[] toFloatArray(double vals[]) { 361 float returnVals[] = new float[vals.length]; 362 for (int i = 0; i < vals.length; i++) { 363 returnVals[i] = (float)vals[i]; 364 } 365 return returnVals; 366 } 367 368} 369