1 /* 2 * $RCSfile: FormatDescriptor.java,v $ 3 * 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Use is subject to license terms. 7 * 8 * $Revision: 1.1 $ 9 * $Date: 2005/02/11 04:57:36 $ 10 * $State: Exp $ 11 */ 12 package com.lightcrafts.mediax.jai.operator; 13 import java.awt.RenderingHints; 14 import java.awt.image.DataBuffer; 15 import java.awt.image.RenderedImage; 16 import java.awt.image.renderable.ParameterBlock; 17 import java.awt.image.renderable.RenderableImage; 18 import com.lightcrafts.mediax.jai.JAI; 19 import com.lightcrafts.mediax.jai.OperationDescriptorImpl; 20 import com.lightcrafts.mediax.jai.ParameterBlockJAI; 21 import com.lightcrafts.mediax.jai.RenderableOp; 22 import com.lightcrafts.mediax.jai.RenderedOp; 23 import com.lightcrafts.mediax.jai.registry.RenderableRegistryMode; 24 import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode; 25 26 /** 27 * An <code>OperationDescriptor</code> describing the "Format" operation. 28 * 29 * <p> The "Format" operation performs reformatting on an image. It 30 * is capable of casting the pixel values of an image to a given data 31 * type, replacing the SampleModel and ColorModel of an image, and 32 * restructuring the image's tile grid layout. The pixel values of 33 * the destination image are defined by the pseudocode: 34 * 35 * <pre>dst[x][y][b] = cast(src[x][y][b], dataType)</pre> 36 * 37 * where "dataType" is one of the constants TYPE_BYTE, TYPE_SHORT, 38 * TYPE_USHORT, TYPE_INT, TYPE_FLOAT, or TYPE_DOUBLE from 39 * <code>java.awt.image.DataBuffer</code>. 40 * 41 * <p> The output SampleModel, ColorModel and tile grid layout are 42 * specified by passing an ImageLayout object as a RenderingHint named 43 * "ImageLayout". The output image will have a SampleModel compatible 44 * with the one specified in the layout hint wherever possible; 45 * however, for output data types of <code>float</code> and 46 * </code>double a <code>ComponentSampleModel</code> will be used 47 * regardless of the value of the hint parameter. 48 * 49 * <p> One of the common uses of the format operator is to cast the 50 * pixel values of an image to a given data type. In such a case, if 51 * the source image provided has an <code>IndexColorModel</code>, a 52 * <code>RenderingHints</code> object for 53 * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> with the value of 54 * <code>Boolean.TRUE</code> will automatically be added to the 55 * configuration <code>Map</code> for the operation. This addition 56 * will only take place if a value for the 57 * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> has not already been 58 * provided by the user. Note that the <code>configuration</code> Map 59 * is cloned before the new hint is added to it. Due to the addition 60 * of this new <code>RenderingHint</code>, using the "format" operation 61 * with source(s) that have an <code>IndexColorModel</code> will cause 62 * the destination to have an expanded non-<code>IndexColorModel</code> 63 * <code>ColorModel</code>. This expansion ensures that the conversion 64 * to a different data type, <code>ColorModel</code> or 65 * <code>SampleModel</code> happens correctly such that the indices 66 * into the color map (for <code>IndexColorModel</code> images) are 67 * not treated as pixel data. If the format operator is not being used 68 * to cast the pixel values of an image to a given data type, the 69 * expansion will not take place, the resultant image will still have 70 * an <code>IndexColorModel</code>. 71 * 72 * <p> The ImageLayout may also specify a tile grid origin and size 73 * which will be respected. 74 * 75 * <p> The typecasting performed by the <code>Format</code> function 76 * is defined by the following set of expressions, dependent on the 77 * data types of the source and destination. Casting an image to its 78 * current data type is a no-op. See <a 79 * href=http://java.sun.com/docs/books/jls/html/5.doc.html#25222> The 80 * Java Language Specification</a> for the definition of type 81 * conversions between primitive types. 82 * 83 * <p> In most cases, it is not necessary to explictly perform widening 84 * typecasts since they will be performed automatically by image 85 * operators when handed source images having different datatypes. 86 * 87 * <p><table border=1> 88 * <tr><th>Source Type</th> <th>Destination Type</th> <th>Action</th></tr> 89 * <tr><td>BYTE</td> <td>SHORT</td> <td>(short)(x & 0xff)</td></tr> 90 * <tr><td>BYTE</td> <td>USHORT</td> <td>(short)(x & 0xff)</td></tr> 91 * <tr><td>BYTE</td> <td>INT</td> <td>(int)(x & 0xff)</td></tr> 92 * <tr><td>BYTE</td> <td>FLOAT</td> <td>(float)(x & 0xff)</td></tr> 93 * <tr><td>BYTE</td> <td>DOUBLE</td> <td>(double)(x & 0xff)</td></tr> 94 * <tr><td>SHORT</td> <td>BYTE</td> <td>(byte)clamp((int)x, 0, 255)</td></tr> 95 * <tr><td>SHORT</td> <td>USHORT</td> <td>(short)clamp((int)x, 0, 32767)</td></tr> 96 * <tr><td>SHORT</td> <td>INT</td> <td>(int)x</td></tr> 97 * <tr><td>SHORT</td> <td>FLOAT</td> <td>(float)x</td></tr> 98 * <tr><td>SHORT</td> <td>DOUBLE</td> <td>(double)x</td></tr> 99 * <tr><td>USHORT</td> <td>BYTE</td> <td>(byte)clamp((int)x & 0xffff, 0, 255)</td></tr> 100 * <tr><td>USHORT</td> <td>SHORT</td> <td>(short)clamp((int)x & 0xffff, 0, 32767)</td></tr> 101 * <tr><td>USHORT</td> <td>INT</td> <td>(int)(x & 0xffff)</td></tr> 102 * <tr><td>USHORT</td> <td>FLOAT</td> <td>(float)(x & 0xffff)</td></tr> 103 * <tr><td>USHORT</td> <td>DOUBLE</td> <td>(double)(x & 0xffff)</td></tr> 104 * <tr><td>INT</td> <td>BYTE</td> <td>(byte)clamp(x, 0, 255)</td></tr> 105 * <tr><td>INT</td> <td>SHORT</td> <td>(short)clamp(x, -32768, 32767)</td></tr> 106 * <tr><td>INT</td> <td>USHORT</td> <td>(short)clamp(x, 0, 65535)</td></tr> 107 * <tr><td>INT</td> <td>FLOAT</td> <td>(float)x</td></tr> 108 * <tr><td>INT</td> <td>DOUBLE</td> <td>(double)x</td></tr> 109 * <tr><td>FLOAT</td> <td>BYTE</td> <td>(byte)clamp((int)x, 0, 255)</td></tr> 110 * <tr><td>FLOAT</td> <td>SHORT</td> <td>(short)clamp((int)x, -32768, 32767)</td></tr> 111 * <tr><td>FLOAT</td> <td>USHORT</td> <td>(short)clamp((int)x, 0, 65535)</td></tr> 112 * <tr><td>FLOAT</td> <td>INT</td> <td>(int)x</td></tr> 113 * <tr><td>FLOAT</td> <td>DOUBLE</td> <td>(double)x</td></tr> 114 * <tr><td>DOUBLE</td> <td>BYTE</td> <td>(byte)clamp((int)x, 0, 255)</td></tr> 115 * <tr><td>DOUBLE</td> <td>SHORT</td> <td>(short)clamp((int)x, -32768, 32767)</td></tr> 116 * <tr><td>DOUBLE</td> <td>USHORT</td> <td>(short)clamp((int)x, 0, 65535)</td></tr> 117 * <tr><td>DOUBLE</td> <td>INT</td> <td>(int)x</td></tr> 118 * <tr><td>DOUBLE</td> <td>FLOAT</td> <td>(float)x</td></tr> 119 * </table></p> 120 * 121 * The <code>clamp</code> function may be defined as: 122 * <pre> 123 * int clamp(int x, int low, int high) { 124 * return (x < low) ? low : ((x > high) ? high : x); 125 * } 126 * </pre> 127 * 128 * <p><table border=1> 129 * <caption>Resource List</caption> 130 * <tr><th>Name</th> <th>Value</th></tr> 131 * <tr><td>GlobalName</td> <td>Format</td></tr> 132 * <tr><td>LocalName</td> <td>Format</td></tr> 133 * <tr><td>Vendor</td> <td>com.lightcrafts.media.jai</td></tr> 134 * <tr><td>Description</td> <td>Reformats an image.</td></tr> 135 * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/FormatDescriptor.html</td></tr> 136 * <tr><td>Version</td> <td>1.0</td></tr> 137 * <tr><td>arg0Desc</td> <td>The output data type (from java.awt.image.DataBuffer).</td></tr> 138 * </table></p> 139 * 140 * <p><table border=1> 141 * <caption>Parameter List</caption> 142 * <tr><th>Name</th> <th>Class Type</th> 143 * <th>Default Value</th></tr> 144 * <tr><td>dataType</td> <td>java.lang.Integer</td> 145 * <td>DataBuffer.TYPE_BYTE</td> 146 * </table></p> 147 * 148 * @see java.awt.image.DataBuffer 149 * @see com.lightcrafts.mediax.jai.ImageLayout 150 * @see com.lightcrafts.mediax.jai.OperationDescriptor 151 */ 152 public class FormatDescriptor extends OperationDescriptorImpl { 153 154 /** 155 * The resource strings that provide the general documentation 156 * and specify the parameter list for this operation. 157 */ 158 private static final String[][] resources = { 159 {"GlobalName", "Format"}, 160 {"LocalName", "Format"}, 161 {"Vendor", "com.lightcrafts.media.jai"}, 162 {"Description", JaiI18N.getString("FormatDescriptor0")}, 163 {"DocURL", "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/FormatDescriptor.html"}, 164 {"Version", JaiI18N.getString("DescriptorVersion")}, 165 {"arg0Desc", "The output data type (from java.awt.image.DataBuffer)."} 166 }; 167 168 /** The parameter class list for this operation. */ 169 private static final Class[] paramClasses = { 170 java.lang.Integer.class 171 }; 172 173 /** The parameter name list for this operation. */ 174 private static final String[] paramNames = { 175 "dataType" 176 }; 177 178 /** The parameter default value list for this operation. */ 179 private static final Object[] paramDefaults = { 180 new Integer(DataBuffer.TYPE_BYTE) 181 }; 182 183 /** Constructor. */ FormatDescriptor()184 public FormatDescriptor() { 185 super(resources, 1, paramClasses, paramNames, paramDefaults); 186 } 187 188 /** Returns <code>true</code> since renderable operation is supported. */ isRenderableSupported()189 public boolean isRenderableSupported() { 190 return true; 191 } 192 193 /** 194 * Returns the minimum legal value of a specified numeric parameter 195 * for this operation. 196 */ getParamMinValue(int index)197 public Number getParamMinValue(int index) { 198 if (index == 0) { 199 return new Integer(DataBuffer.TYPE_BYTE); 200 } else { 201 throw new ArrayIndexOutOfBoundsException(); 202 } 203 } 204 205 /** 206 * Returns the maximum legal value of a specified numeric parameter 207 * for this operation. 208 */ getParamMaxValue(int index)209 public Number getParamMaxValue(int index) { 210 if (index == 0) { 211 return new Integer(DataBuffer.TYPE_DOUBLE); 212 } else { 213 throw new ArrayIndexOutOfBoundsException(); 214 } 215 } 216 217 218 /** 219 * Reformats an image. 220 * 221 * <p>Creates a <code>ParameterBlockJAI</code> from all 222 * supplied arguments except <code>hints</code> and invokes 223 * {@link JAI#create(String,ParameterBlock,RenderingHints)}. 224 * 225 * @see JAI 226 * @see ParameterBlockJAI 227 * @see RenderedOp 228 * 229 * @param source0 <code>RenderedImage</code> source 0. 230 * @param dataType The output data type (from java.awt.image.DataBuffer). 231 * May be <code>null</code>. 232 * @param hints The <code>RenderingHints</code> to use. 233 * May be <code>null</code>. 234 * @return The <code>RenderedOp</code> destination. 235 * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>. 236 */ create(RenderedImage source0, Integer dataType, RenderingHints hints)237 public static RenderedOp create(RenderedImage source0, 238 Integer dataType, 239 RenderingHints hints) { 240 ParameterBlockJAI pb = 241 new ParameterBlockJAI("Format", 242 RenderedRegistryMode.MODE_NAME); 243 244 pb.setSource("source0", source0); 245 246 pb.setParameter("dataType", dataType); 247 248 return JAI.create("Format", pb, hints); 249 } 250 251 /** 252 * Reformats an image. 253 * 254 * <p>Creates a <code>ParameterBlockJAI</code> from all 255 * supplied arguments except <code>hints</code> and invokes 256 * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}. 257 * 258 * @see JAI 259 * @see ParameterBlockJAI 260 * @see RenderableOp 261 * 262 * @param source0 <code>RenderableImage</code> source 0. 263 * @param dataType The output data type (from java.awt.image.DataBuffer). 264 * May be <code>null</code>. 265 * @param hints The <code>RenderingHints</code> to use. 266 * May be <code>null</code>. 267 * @return The <code>RenderableOp</code> destination. 268 * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>. 269 */ createRenderable(RenderableImage source0, Integer dataType, RenderingHints hints)270 public static RenderableOp createRenderable(RenderableImage source0, 271 Integer dataType, 272 RenderingHints hints) { 273 ParameterBlockJAI pb = 274 new ParameterBlockJAI("Format", 275 RenderableRegistryMode.MODE_NAME); 276 277 pb.setSource("source0", source0); 278 279 pb.setParameter("dataType", dataType); 280 281 return JAI.createRenderable("Format", pb, hints); 282 } 283 } 284