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 }