1 /* 2 * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.imageio; 27 28 import java.awt.Dimension; 29 import java.awt.image.BufferedImage; 30 31 /** 32 * A class describing how a stream is to be decoded. Instances of 33 * this class or its subclasses are used to supply prescriptive 34 * "how-to" information to instances of <code>ImageReader</code>. 35 * 36 * <p> An image encoded as part of a file or stream may be thought of 37 * extending out in multiple dimensions: the spatial dimensions of 38 * width and height, a number of bands, and a number of progressive 39 * decoding passes. This class allows a contiguous (hyper)rectangular 40 * subarea of the image in all of these dimensions to be selected for 41 * decoding. Additionally, the spatial dimensions may be subsampled 42 * discontinuously. Finally, color and format conversions may be 43 * specified by controlling the <code>ColorModel</code> and 44 * <code>SampleModel</code> of the destination image, either by 45 * providing a <code>BufferedImage</code> or by using an 46 * <code>ImageTypeSpecifier</code>. 47 * 48 * <p> An <code>ImageReadParam</code> object is used to specify how an 49 * image, or a set of images, will be converted on input from 50 * a stream in the context of the Java Image I/O framework. A plug-in for a 51 * specific image format will return instances of 52 * <code>ImageReadParam</code> from the 53 * <code>getDefaultReadParam</code> method of its 54 * <code>ImageReader</code> implementation. 55 * 56 * <p> The state maintained by an instance of 57 * <code>ImageReadParam</code> is independent of any particular image 58 * being decoded. When actual decoding takes place, the values set in 59 * the read param are combined with the actual properties of the image 60 * being decoded from the stream and the destination 61 * <code>BufferedImage</code> that will receive the decoded pixel 62 * data. For example, the source region set using 63 * <code>setSourceRegion</code> will first be intersected with the 64 * actual valid source area. The result will be translated by the 65 * value returned by <code>getDestinationOffset</code>, and the 66 * resulting rectangle intersected with the actual valid destination 67 * area to yield the destination area that will be written. 68 * 69 * <p> The parameters specified by an <code>ImageReadParam</code> are 70 * applied to an image as follows. First, if a rendering size has 71 * been set by <code>setSourceRenderSize</code>, the entire decoded 72 * image is rendered at the size given by 73 * <code>getSourceRenderSize</code>. Otherwise, the image has its 74 * natural size given by <code>ImageReader.getWidth</code> and 75 * <code>ImageReader.getHeight</code>. 76 * 77 * <p> Next, the image is clipped against the source region 78 * specified by <code>getSourceXOffset</code>, <code>getSourceYOffset</code>, 79 * <code>getSourceWidth</code>, and <code>getSourceHeight</code>. 80 * 81 * <p> The resulting region is then subsampled according to the 82 * factors given in {@link IIOParam#setSourceSubsampling 83 * <code>IIOParam.setSourceSubsampling</code>}. The first pixel, 84 * the number of pixels per row, and the number of rows all depend 85 * on the subsampling settings. 86 * Call the minimum X and Y coordinates of the resulting rectangle 87 * (<code>minX</code>, <code>minY</code>), its width <code>w</code> 88 * and its height <code>h</code>. 89 * 90 * <p> This rectangle is offset by 91 * (<code>getDestinationOffset().x</code>, 92 * <code>getDestinationOffset().y</code>) and clipped against the 93 * destination bounds. If no destination image has been set, the 94 * destination is defined to have a width of 95 * <code>getDestinationOffset().x</code> + <code>w</code>, and a 96 * height of <code>getDestinationOffset().y</code> + <code>h</code> so 97 * that all pixels of the source region may be written to the 98 * destination. 99 * 100 * <p> Pixels that land, after subsampling, within the destination 101 * image, and that are written in one of the progressive passes 102 * specified by <code>getSourceMinProgressivePass</code> and 103 * <code>getSourceNumProgressivePasses</code> are passed along to the 104 * next step. 105 * 106 * <p> Finally, the source samples of each pixel are mapped into 107 * destination bands according to the algorithm described in the 108 * comment for <code>setDestinationBands</code>. 109 * 110 * <p> Plug-in writers may extend the functionality of 111 * <code>ImageReadParam</code> by providing a subclass that implements 112 * additional, plug-in specific interfaces. It is up to the plug-in 113 * to document what interfaces are available and how they are to be 114 * used. Readers will silently ignore any extended features of an 115 * <code>ImageReadParam</code> subclass of which they are not aware. 116 * Also, they may ignore any optional features that they normally 117 * disable when creating their own <code>ImageReadParam</code> 118 * instances via <code>getDefaultReadParam</code>. 119 * 120 * <p> Note that unless a query method exists for a capability, it must 121 * be supported by all <code>ImageReader</code> implementations 122 * (<i>e.g.</i> source render size is optional, but subsampling must be 123 * supported). 124 * 125 * 126 * @see ImageReader 127 * @see ImageWriter 128 * @see ImageWriteParam 129 */ 130 public class ImageReadParam extends IIOParam { 131 132 /** 133 * <code>true</code> if this <code>ImageReadParam</code> allows 134 * the source rendering dimensions to be set. By default, the 135 * value is <code>false</code>. Subclasses must set this value 136 * manually. 137 * 138 * <p> <code>ImageReader</code>s that do not support setting of 139 * the source render size should set this value to 140 * <code>false</code>. 141 */ 142 protected boolean canSetSourceRenderSize = false; 143 144 /** 145 * The desired rendering width and height of the source, if 146 * <code>canSetSourceRenderSize</code> is <code>true</code>, or 147 * <code>null</code>. 148 * 149 * <p> <code>ImageReader</code>s that do not support setting of 150 * the source render size may ignore this value. 151 */ 152 protected Dimension sourceRenderSize = null; 153 154 /** 155 * The current destination <code>BufferedImage</code>, or 156 * <code>null</code> if none has been set. By default, the value 157 * is <code>null</code>. 158 */ 159 protected BufferedImage destination = null; 160 161 /** 162 * The set of destination bands to be used, as an array of 163 * <code>int</code>s. By default, the value is <code>null</code>, 164 * indicating all destination bands should be written in order. 165 */ 166 protected int[] destinationBands = null; 167 168 /** 169 * The minimum index of a progressive pass to read from the 170 * source. By default, the value is set to 0, which indicates 171 * that passes starting with the first available pass should be 172 * decoded. 173 * 174 * <p> Subclasses should ensure that this value is 175 * non-negative. 176 */ 177 protected int minProgressivePass = 0; 178 179 /** 180 * The maximum number of progressive passes to read from the 181 * source. By default, the value is set to 182 * <code>Integer.MAX_VALUE</code>, which indicates that passes up 183 * to and including the last available pass should be decoded. 184 * 185 * <p> Subclasses should ensure that this value is positive. 186 * Additionally, if the value is not 187 * <code>Integer.MAX_VALUE</code>, then <code>minProgressivePass + 188 * numProgressivePasses - 1</code> should not exceed 189 * <code>Integer.MAX_VALUE</code>. 190 */ 191 protected int numProgressivePasses = Integer.MAX_VALUE; 192 193 /** 194 * Constructs an <code>ImageReadParam</code>. 195 */ 196 public ImageReadParam() {} 197 198 // Comment inherited 199 public void setDestinationType(ImageTypeSpecifier destinationType) { 200 super.setDestinationType(destinationType); 201 setDestination(null); 202 } 203 204 /** 205 * Supplies a <code>BufferedImage</code> to be used as the 206 * destination for decoded pixel data. The currently set image 207 * will be written to by the <code>read</code>, 208 * <code>readAll</code>, and <code>readRaster</code> methods, and 209 * a reference to it will be returned by those methods. 210 * 211 * <p> Pixel data from the aforementioned methods will be written 212 * starting at the offset specified by 213 * <code>getDestinationOffset</code>. 214 * 215 * <p> If <code>destination</code> is <code>null</code>, a 216 * newly-created <code>BufferedImage</code> will be returned by 217 * those methods. 218 * 219 * <p> At the time of reading, the image is checked to verify that 220 * its <code>ColorModel</code> and <code>SampleModel</code> 221 * correspond to one of the <code>ImageTypeSpecifier</code>s 222 * returned from the <code>ImageReader</code>'s 223 * <code>getImageTypes</code> method. If it does not, the reader 224 * will throw an <code>IIOException</code>. 225 * 226 * @param destination the BufferedImage to be written to, or 227 * <code>null</code>. 228 * 229 * @see #getDestination 230 */ 231 public void setDestination(BufferedImage destination) { 232 this.destination = destination; 233 } 234 235 /** 236 * Returns the <code>BufferedImage</code> currently set by the 237 * <code>setDestination</code> method, or <code>null</code> 238 * if none is set. 239 * 240 * @return the BufferedImage to be written to. 241 * 242 * @see #setDestination 243 */ 244 public BufferedImage getDestination() { 245 return destination; 246 } 247 248 /** 249 * Sets the indices of the destination bands where data 250 * will be placed. Duplicate indices are not allowed. 251 * 252 * <p> A <code>null</code> value indicates that all destination 253 * bands will be used. 254 * 255 * <p> Choosing a destination band subset will not affect the 256 * number of bands in the output image of a read if no destination 257 * image is specified; the created destination image will still 258 * have the same number of bands as if this method had never been 259 * called. If a different number of bands in the destination 260 * image is desired, an image must be supplied using the 261 * <code>ImageReadParam.setDestination</code> method. 262 * 263 * <p> At the time of reading or writing, an 264 * <code>IllegalArgumentException</code> will be thrown by the 265 * reader or writer if a value larger than the largest destination 266 * band index has been specified, or if the number of source bands 267 * and destination bands to be used differ. The 268 * <code>ImageReader.checkReadParamBandSettings</code> method may 269 * be used to automate this test. 270 * 271 * @param destinationBands an array of integer band indices to be 272 * used. 273 * 274 * @exception IllegalArgumentException if <code>destinationBands</code> 275 * contains a negative or duplicate value. 276 * 277 * @see #getDestinationBands 278 * @see #getSourceBands 279 * @see ImageReader#checkReadParamBandSettings 280 */ 281 public void setDestinationBands(int[] destinationBands) { 282 if (destinationBands == null) { 283 this.destinationBands = null; 284 } else { 285 int numBands = destinationBands.length; 286 for (int i = 0; i < numBands; i++) { 287 int band = destinationBands[i]; 288 if (band < 0) { 289 throw new IllegalArgumentException("Band value < 0!"); 290 } 291 for (int j = i + 1; j < numBands; j++) { 292 if (band == destinationBands[j]) { 293 throw new IllegalArgumentException("Duplicate band value!"); 294 } 295 } 296 } 297 this.destinationBands = destinationBands.clone(); 298 } 299 } 300 301 /** 302 * Returns the set of band indices where data will be placed. 303 * If no value has been set, <code>null</code> is returned to 304 * indicate that all destination bands will be used. 305 * 306 * @return the indices of the destination bands to be used, 307 * or <code>null</code>. 308 * 309 * @see #setDestinationBands 310 */ 311 public int[] getDestinationBands() { 312 if (destinationBands == null) { 313 return null; 314 } else { 315 return destinationBands.clone(); 316 } 317 } 318 319 /** 320 * Returns <code>true</code> if this reader allows the source 321 * image to be rendered at an arbitrary size as part of the 322 * decoding process, by means of the 323 * <code>setSourceRenderSize</code> method. If this method 324 * returns <code>false</code>, calls to 325 * <code>setSourceRenderSize</code> will throw an 326 * <code>UnsupportedOperationException</code>. 327 * 328 * @return <code>true</code> if setting source rendering size is 329 * supported. 330 * 331 * @see #setSourceRenderSize 332 */ 333 public boolean canSetSourceRenderSize() { 334 return canSetSourceRenderSize; 335 } 336 337 /** 338 * If the image is able to be rendered at an arbitrary size, sets 339 * the source width and height to the supplied values. Note that 340 * the values returned from the <code>getWidth</code> and 341 * <code>getHeight</code> methods on <code>ImageReader</code> are 342 * not affected by this method; they will continue to return the 343 * default size for the image. Similarly, if the image is also 344 * tiled the tile width and height are given in terms of the default 345 * size. 346 * 347 * <p> Typically, the width and height should be chosen such that 348 * the ratio of width to height closely approximates the aspect 349 * ratio of the image, as returned from 350 * <code>ImageReader.getAspectRatio</code>. 351 * 352 * <p> If this plug-in does not allow the rendering size to be 353 * set, an <code>UnsupportedOperationException</code> will be 354 * thrown. 355 * 356 * <p> To remove the render size setting, pass in a value of 357 * <code>null</code> for <code>size</code>. 358 * 359 * @param size a <code>Dimension</code> indicating the desired 360 * width and height. 361 * 362 * @exception IllegalArgumentException if either the width or the 363 * height is negative or 0. 364 * @exception UnsupportedOperationException if image resizing 365 * is not supported by this plug-in. 366 * 367 * @see #getSourceRenderSize 368 * @see ImageReader#getWidth 369 * @see ImageReader#getHeight 370 * @see ImageReader#getAspectRatio 371 */ 372 public void setSourceRenderSize(Dimension size) 373 throws UnsupportedOperationException { 374 if (!canSetSourceRenderSize()) { 375 throw new UnsupportedOperationException 376 ("Can't set source render size!"); 377 } 378 379 if (size == null) { 380 this.sourceRenderSize = null; 381 } else { 382 if (size.width <= 0 || size.height <= 0) { 383 throw new IllegalArgumentException("width or height <= 0!"); 384 } 385 this.sourceRenderSize = (Dimension)size.clone(); 386 } 387 } 388 389 /** 390 * Returns the width and height of the source image as it 391 * will be rendered during decoding, if they have been set via the 392 * <code>setSourceRenderSize</code> method. A 393 * <code>null</code>value indicates that no setting has been made. 394 * 395 * @return the rendered width and height of the source image 396 * as a <code>Dimension</code>. 397 * 398 * @see #setSourceRenderSize 399 */ 400 public Dimension getSourceRenderSize() { 401 return (sourceRenderSize == null) ? 402 null : (Dimension)sourceRenderSize.clone(); 403 } 404 405 /** 406 * Sets the range of progressive passes that will be decoded. 407 * Passes outside of this range will be ignored. 408 * 409 * <p> A progressive pass is a re-encoding of the entire image, 410 * generally at progressively higher effective resolutions, but 411 * requiring greater transmission bandwidth. The most common use 412 * of progressive encoding is found in the JPEG format, where 413 * successive passes include more detailed representations of the 414 * high-frequency image content. 415 * 416 * <p> The actual number of passes to be decoded is determined 417 * during decoding, based on the number of actual passes available 418 * in the stream. Thus if <code>minPass + numPasses - 1</code> is 419 * larger than the index of the last available passes, decoding 420 * will end with that pass. 421 * 422 * <p> A value of <code>numPasses</code> of 423 * <code>Integer.MAX_VALUE</code> indicates that all passes from 424 * <code>minPass</code> forward should be read. Otherwise, the 425 * index of the last pass (<i>i.e.</i>, <code>minPass + numPasses 426 * - 1</code>) must not exceed <code>Integer.MAX_VALUE</code>. 427 * 428 * <p> There is no <code>unsetSourceProgressivePasses</code> 429 * method; the same effect may be obtained by calling 430 * <code>setSourceProgressivePasses(0, Integer.MAX_VALUE)</code>. 431 * 432 * @param minPass the index of the first pass to be decoded. 433 * @param numPasses the maximum number of passes to be decoded. 434 * 435 * @exception IllegalArgumentException if <code>minPass</code> is 436 * negative, <code>numPasses</code> is negative or 0, or 437 * <code>numPasses</code> is smaller than 438 * <code>Integer.MAX_VALUE</code> but <code>minPass + 439 * numPasses - 1</code> is greater than 440 * <code>INTEGER.MAX_VALUE</code>. 441 * 442 * @see #getSourceMinProgressivePass 443 * @see #getSourceMaxProgressivePass 444 */ 445 public void setSourceProgressivePasses(int minPass, int numPasses) { 446 if (minPass < 0) { 447 throw new IllegalArgumentException("minPass < 0!"); 448 } 449 if (numPasses <= 0) { 450 throw new IllegalArgumentException("numPasses <= 0!"); 451 } 452 if ((numPasses != Integer.MAX_VALUE) && 453 (((minPass + numPasses - 1) & 0x80000000) != 0)) { 454 throw new IllegalArgumentException 455 ("minPass + numPasses - 1 > INTEGER.MAX_VALUE!"); 456 } 457 458 this.minProgressivePass = minPass; 459 this.numProgressivePasses = numPasses; 460 } 461 462 /** 463 * Returns the index of the first progressive pass that will be 464 * decoded. If no value has been set, 0 will be returned (which is 465 * the correct value). 466 * 467 * @return the index of the first pass that will be decoded. 468 * 469 * @see #setSourceProgressivePasses 470 * @see #getSourceNumProgressivePasses 471 */ 472 public int getSourceMinProgressivePass() { 473 return minProgressivePass; 474 } 475 476 /** 477 * If <code>getSourceNumProgressivePasses</code> is equal to 478 * <code>Integer.MAX_VALUE</code>, returns 479 * <code>Integer.MAX_VALUE</code>. Otherwise, returns 480 * <code>getSourceMinProgressivePass() + 481 * getSourceNumProgressivePasses() - 1</code>. 482 * 483 * @return the index of the last pass to be read, or 484 * <code>Integer.MAX_VALUE</code>. 485 */ 486 public int getSourceMaxProgressivePass() { 487 if (numProgressivePasses == Integer.MAX_VALUE) { 488 return Integer.MAX_VALUE; 489 } else { 490 return minProgressivePass + numProgressivePasses - 1; 491 } 492 } 493 494 /** 495 * Returns the number of the progressive passes that will be 496 * decoded. If no value has been set, 497 * <code>Integer.MAX_VALUE</code> will be returned (which is the 498 * correct value). 499 * 500 * @return the number of the passes that will be decoded. 501 * 502 * @see #setSourceProgressivePasses 503 * @see #getSourceMinProgressivePass 504 */ 505 public int getSourceNumProgressivePasses() { 506 return numProgressivePasses; 507 } 508 }