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.github.jaiimageio.jpeg2000.impl; 046import java.awt.Rectangle; 047import java.awt.image.ComponentSampleModel; 048import java.awt.image.DataBuffer; 049import java.awt.image.Raster; 050import java.awt.image.SampleModel; 051 052import com.github.jaiimageio.impl.common.ImageUtil; 053/** 054 * An adapter class for presenting image data in a mediaLibImage 055 * format, even if the data isn't stored that way. MediaLibAccessor 056 * is meant to make the common case (ComponentRasters) and allow 057 * them to be accelerated via medialib. Note that unlike RasterAccessor, 058 * MediaLibAccessor does not work with all cases. In the event that 059 * MediaLibAccessor can not deal with a give collection of Rasters, 060 * findCompatibleTag will return the value MediaLibAccessor.TAG_INCOMPATIBLE. 061 * OpImages that use MediaLibAccessor should be paired with RIF's 062 * which check that findCompatibleTag returns a valid tag before 063 * actually constructing the Mlib OpImage. 064 */ 065 066public class MediaLibAccessor { 067 /** 068 * Value indicating how far COPY_MASK info is shifted to avoid 069 * interfering with the data type info 070 */ 071 private static final int COPY_MASK_SHIFT = 7; 072 073 /* Value indicating how many bits the COPY_MASK is */ 074 private static final int COPY_MASK_SIZE = 1; 075 076 /** The bits of a FormatTag associated with how dataArrays are obtained. */ 077 public static final int COPY_MASK = 0x1 << COPY_MASK_SHIFT; 078 079 /** Flag indicating data is raster's data. */ 080 public static final int UNCOPIED = 0x0 << COPY_MASK_SHIFT; 081 082 /** Flag indicating data is a copy of the raster's data. */ 083 public static final int COPIED = 0x01 << COPY_MASK_SHIFT; 084 085 /** The bits of a FormatTag associated with pixel datatype. */ 086 public static final int DATATYPE_MASK = (0x1 << COPY_MASK_SHIFT) - 1; 087 088 /** 089 * Value indicating how far BINARY_MASK info is shifted to avoid 090 * interfering with the data type and copying info. 091 */ 092 private static final int BINARY_MASK_SHIFT = 093 COPY_MASK_SHIFT+COPY_MASK_SIZE; 094 095 /** Value indicating how many bits the BINARY_MASK is */ 096 private static final int BINARY_MASK_SIZE = 1; 097 098 /** The bits of a FormatTag associated with binary data. */ 099 public static final int BINARY_MASK = 100 ((1 << BINARY_MASK_SIZE) - 1) << BINARY_MASK_SHIFT; 101 102 /** Flag indicating data are not binary. */ 103 public static final int NONBINARY = 0x0 << BINARY_MASK_SHIFT; 104 105 /** Flag indicating data are binary. */ 106 public static final int BINARY = 0x1 << BINARY_MASK_SHIFT; 107 108 /** FormatTag indicating data in byte arrays and uncopied. */ 109 public static final int 110 TAG_BYTE_UNCOPIED = DataBuffer.TYPE_BYTE | UNCOPIED; 111 112 /** FormatTag indicating data in unsigned short arrays and uncopied. */ 113 public static final int 114 TAG_USHORT_UNCOPIED = DataBuffer.TYPE_USHORT | UNCOPIED; 115 116 /** FormatTag indicating data in short arrays and uncopied. */ 117 public static final int 118 TAG_SHORT_UNCOPIED = DataBuffer.TYPE_SHORT | UNCOPIED; 119 120 /** FormatTag indicating data in integer arrays and uncopied. */ 121 public static final int 122 TAG_INT_UNCOPIED = DataBuffer.TYPE_INT | UNCOPIED; 123 124 /** FormatTag indicating data in float arrays and uncopied. */ 125 public static final int 126 TAG_FLOAT_UNCOPIED = DataBuffer.TYPE_FLOAT | UNCOPIED; 127 128 /** FormatTag indicating data in double arrays and uncopied. */ 129 public static final int 130 TAG_DOUBLE_UNCOPIED = DataBuffer.TYPE_DOUBLE | UNCOPIED; 131 132 /** FormatTag indicating data in byte arrays and uncopied. */ 133 public static final int 134 TAG_BYTE_COPIED = DataBuffer.TYPE_BYTE | COPIED; 135 136 /** FormatTag indicating data in unsigned short arrays and copied. */ 137 public static final int 138 TAG_USHORT_COPIED = DataBuffer.TYPE_USHORT | COPIED; 139 140 /** FormatTag indicating data in short arrays and copied. */ 141 public static final int 142 TAG_SHORT_COPIED = DataBuffer.TYPE_SHORT | COPIED; 143 144 /** FormatTag indicating data in short arrays and copied. */ 145 public static final int 146 TAG_INT_COPIED = DataBuffer.TYPE_INT | COPIED; 147 148 /** FormatTag indicating data in float arrays and copied. */ 149 public static final int 150 TAG_FLOAT_COPIED = DataBuffer.TYPE_FLOAT | COPIED; 151 152 /** FormatTag indicating data in double arrays and copied. */ 153 public static final int 154 TAG_DOUBLE_COPIED = DataBuffer.TYPE_DOUBLE | COPIED; 155 156 /** The raster that is the source of pixel data. */ 157 protected Raster raster; 158 159 /** The rectangle of the raster that MediaLibAccessor addresses. */ 160 protected Rectangle rect; 161 162 /** The number of bands per pixel in the data array. */ 163 protected int numBands; 164 165 /** The offsets of each band in the src image */ 166 protected int bandOffsets[]; 167 168 /** Tag indicating the data type of the data and whether its copied */ 169 protected int formatTag; 170 171 172 /** 173 * Whether packed data are preferred when processing binary images. 174 * This tag is ignored if the data are not binary. 175 */ 176 private boolean areBinaryDataPacked = false; 177 178 /** 179 * Returns the most efficient FormatTag that is compatible with 180 * the destination raster and all source rasters. 181 * 182 * @param srcs the source <code>Raster</code>; may be <code>null</code>. 183 * @param dst the destination <code>Raster</code>. 184 */ 185 public static int findCompatibleTag(Raster src) { 186 SampleModel dstSM = src.getSampleModel(); 187 int dstDT = dstSM.getDataType(); 188 189 int defaultDataType = dstSM.getDataType(); 190 191 boolean allComponentSampleModel = 192 dstSM instanceof ComponentSampleModel; 193 boolean allBinary = ImageUtil.isBinary(dstSM); 194 195 if(allBinary) { 196 // The copy flag is not set until the mediaLibImage is 197 // created as knowing this information requires too much 198 // processing to determine here. 199 return DataBuffer.TYPE_BYTE | BINARY; 200 } 201 202 if (!allComponentSampleModel) { 203 if ((defaultDataType == DataBuffer.TYPE_BYTE) || 204 (defaultDataType == DataBuffer.TYPE_USHORT) || 205 (defaultDataType == DataBuffer.TYPE_SHORT)) { 206 defaultDataType = DataBuffer.TYPE_INT; 207 } 208 } 209 210 int tag = defaultDataType | COPIED; 211 212 if (!allComponentSampleModel) { 213 return tag; 214 } 215 216 if (isPixelSequential(dstSM)) 217 return dstDT | UNCOPIED; 218 return tag; 219 } 220 221 /** 222 * Determines if the SampleModel stores data in a way that can 223 * be represented by a mediaLibImage without copying 224 */ 225 public static boolean isPixelSequential(SampleModel sm) { 226 ComponentSampleModel csm = null; 227 if (sm instanceof ComponentSampleModel) { 228 csm = (ComponentSampleModel)sm; 229 } else { 230 return false; 231 } 232 int pixelStride = csm.getPixelStride(); 233 int bandOffsets[] = csm.getBandOffsets(); 234 int bankIndices[] = csm.getBankIndices(); 235 if (pixelStride != bandOffsets.length) { 236 return false; 237 } 238 239 //XXX: for band-selection result 240 if (pixelStride != sm.getNumBands()) 241 return false; 242 243 for (int i = 0; i < bandOffsets.length; i++) { 244 if (bandOffsets[i] >= pixelStride || 245 bankIndices[i] != bankIndices[0]) { 246 return false; 247 } 248 for (int j = i+1; j < bandOffsets.length; j++) { 249 if (bandOffsets[i] == bandOffsets[j]) { 250 return false; 251 } 252 253 //XXX: for BGR images 254 if (bandOffsets[i] != i) 255 return false; 256 } 257 } 258 return true; 259 } 260 261 /** 262 * Returns <code>true</code> if the <code>MediaLibAccessor</code> 263 * represents binary data. 264 */ 265 public boolean isBinary() { 266 return ((formatTag & BINARY_MASK) == BINARY); 267 } 268 269 /** 270 * Returns the data type of the RasterAccessor object. Note that 271 * this datatype is not necessarily the same data type as the 272 * underlying raster. 273 */ 274 public int getDataType() { 275 return formatTag & DATATYPE_MASK; 276 } 277 278 /** 279 * Returns true if the MediaLibAccessors's data is copied from it's 280 * raster. 281 */ 282 public boolean isDataCopy() { 283 return ((formatTag & COPY_MASK) == COPIED); 284 } 285 286 /** Returns the bandOffsets. */ 287 public int[] getBandOffsets() { 288 return bandOffsets; 289 } 290 291 /** 292 * Returns parameters in the appropriate order if MediaLibAccessor 293 * has reordered the bands or is attempting to make a 294 * BandSequential image look like multiple PixelSequentialImages 295 */ 296 public int[] getIntParameters(int band, int params[]) { 297 int returnParams[] = new int[numBands]; 298 for (int i = 0; i < numBands; i++) { 299 returnParams[i] = params[bandOffsets[i+band]]; 300 } 301 return returnParams; 302 } 303 304 /** 305 * Returns parameters in the appropriate order if MediaLibAccessor 306 * has reordered the bands or is attempting to make a 307 * BandSequential image look like multiple PixelSequentialImages 308 */ 309 public int[][] getIntArrayParameters(int band, int[][] params) { 310 int returnParams[][] = new int[numBands][]; 311 for (int i = 0; i < numBands; i++) { 312 returnParams[i] = params[bandOffsets[i+band]]; 313 } 314 return returnParams; 315 } 316 317 /** 318 * Returns parameters in the appropriate order if MediaLibAccessor 319 * has reordered the bands or is attempting to make a 320 * BandSequential image look like multiple PixelSequentialImages 321 */ 322 public double[] getDoubleParameters(int band, double params[]) { 323 double returnParams[] = new double[numBands]; 324 for (int i = 0; i < numBands; i++) { 325 returnParams[i] = params[bandOffsets[i+band]]; 326 } 327 return returnParams; 328 } 329 330 331 332 private int[] toIntArray(double vals[]) { 333 int returnVals[] = new int[vals.length]; 334 for (int i = 0; i < vals.length; i++) { 335 returnVals[i] = (int)vals[i]; 336 } 337 return returnVals; 338 } 339 340 private float[] toFloatArray(double vals[]) { 341 float returnVals[] = new float[vals.length]; 342 for (int i = 0; i < vals.length; i++) { 343 returnVals[i] = (float)vals[i]; 344 } 345 return returnVals; 346 } 347 348} 349