1 /*
   2  * Copyright (c) 1999, 2014, 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}.
  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} and
  44  * {@code SampleModel} of the destination image, either by
  45  * providing a {@code BufferedImage} or by using an
  46  * {@code ImageTypeSpecifier}.
  47  *
  48  * <p> An {@code ImageReadParam} 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} from the
  53  * {@code getDefaultReadParam} method of its
  54  * {@code ImageReader} implementation.
  55  *
  56  * <p> The state maintained by an instance of
  57  * {@code ImageReadParam} 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} that will receive the decoded pixel
  62  * data.  For example, the source region set using
  63  * {@code setSourceRegion} will first be intersected with the
  64  * actual valid source area.  The result will be translated by the
  65  * value returned by {@code getDestinationOffset}, 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} are
  70  * applied to an image as follows.  First, if a rendering size has
  71  * been set by {@code setSourceRenderSize}, the entire decoded
  72  * image is rendered at the size given by
  73  * {@code getSourceRenderSize}.  Otherwise, the image has its
  74  * natural size given by {@code ImageReader.getWidth} and
  75  * {@code ImageReader.getHeight}.
  76  *
  77  * <p> Next, the image is clipped against the source region
  78  * specified by {@code getSourceXOffset}, {@code getSourceYOffset},
  79  * {@code getSourceWidth}, and {@code getSourceHeight}.
  80  *
  81  * <p> The resulting region is then subsampled according to the
  82  * factors given in {@link IIOParam#setSourceSubsampling
  83  * IIOParam.setSourceSubsampling}.  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 minY}), its width {@code w}
  88  * and its height {@code h}.
  89  *
  90  * <p> This rectangle is offset by
  91  * ({@code getDestinationOffset().x},
  92  * {@code getDestinationOffset().y}) 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 w}, and a
  96  * height of {@code getDestinationOffset().y} + {@code h} 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} and
 103  * {@code getSourceNumProgressivePasses} 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}.
 109  *
 110  * <p> Plug-in writers may extend the functionality of
 111  * {@code ImageReadParam} 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} 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}
 118  * instances via {@code getDefaultReadParam}.
 119  *
 120  * <p> Note that unless a query method exists for a capability, it must
 121  * be supported by all {@code ImageReader} 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} if this {@code ImageReadParam} allows
 134      * the source rendering dimensions to be set.  By default, the
 135      * value is {@code false}.  Subclasses must set this value
 136      * manually.
 137      *
 138      * <p> {@code ImageReader}s that do not support setting of
 139      * the source render size should set this value to
 140      * {@code false}.
 141      */
 142     protected boolean canSetSourceRenderSize = false;
 143 
 144     /**
 145      * The desired rendering width and height of the source, if
 146      * {@code canSetSourceRenderSize} is {@code true}, or
 147      * {@code null}.
 148      *
 149      * <p> {@code ImageReader}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}, or
 156      * {@code null} if none has been set.  By default, the value
 157      * is {@code null}.
 158      */
 159     protected BufferedImage destination = null;
 160 
 161     /**
 162      * The set of destination bands to be used, as an array of
 163      * {@code int}s.  By default, the value is {@code null},
 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}, 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}, then
 188      * {@code minProgressivePass + numProgressivePasses - 1}
 189      * should not exceed
 190      * {@code Integer.MAX_VALUE}.
 191      */
 192     protected int numProgressivePasses = Integer.MAX_VALUE;
 193 
 194     /**
 195      * Constructs an {@code ImageReadParam}.
 196      */
 197     public ImageReadParam() {}
 198 
 199     // Comment inherited
 200     public void setDestinationType(ImageTypeSpecifier destinationType) {
 201         super.setDestinationType(destinationType);
 202         setDestination(null);
 203     }
 204 
 205     /**
 206      * Supplies a {@code BufferedImage} to be used as the
 207      * destination for decoded pixel data.  The currently set image
 208      * will be written to by the {@code read},
 209      * {@code readAll}, and {@code readRaster} methods, and
 210      * a reference to it will be returned by those methods.
 211      *
 212      * <p> Pixel data from the aforementioned methods will be written
 213      * starting at the offset specified by
 214      * {@code getDestinationOffset}.
 215      *
 216      * <p> If {@code destination} is {@code null}, a
 217      * newly-created {@code BufferedImage} will be returned by
 218      * those methods.
 219      *
 220      * <p> At the time of reading, the image is checked to verify that
 221      * its {@code ColorModel} and {@code SampleModel}
 222      * correspond to one of the {@code ImageTypeSpecifier}s
 223      * returned from the {@code ImageReader}'s
 224      * {@code getImageTypes} method.  If it does not, the reader
 225      * will throw an {@code IIOException}.
 226      *
 227      * @param destination the BufferedImage to be written to, or
 228      * {@code null}.
 229      *
 230      * @see #getDestination
 231      */
 232     public void setDestination(BufferedImage destination) {
 233         this.destination = destination;
 234     }
 235 
 236     /**
 237      * Returns the {@code BufferedImage} currently set by the
 238      * {@code setDestination} method, or {@code null}
 239      * if none is set.
 240      *
 241      * @return the BufferedImage to be written to.
 242      *
 243      * @see #setDestination
 244      */
 245     public BufferedImage getDestination() {
 246         return destination;
 247     }
 248 
 249     /**
 250      * Sets the indices of the destination bands where data
 251      * will be placed.  Duplicate indices are not allowed.
 252      *
 253      * <p> A {@code null} value indicates that all destination
 254      * bands will be used.
 255      *
 256      * <p> Choosing a destination band subset will not affect the
 257      * number of bands in the output image of a read if no destination
 258      * image is specified; the created destination image will still
 259      * have the same number of bands as if this method had never been
 260      * called.  If a different number of bands in the destination
 261      * image is desired, an image must be supplied using the
 262      * {@code ImageReadParam.setDestination} method.
 263      *
 264      * <p> At the time of reading or writing, an
 265      * {@code IllegalArgumentException} will be thrown by the
 266      * reader or writer if a value larger than the largest destination
 267      * band index has been specified, or if the number of source bands
 268      * and destination bands to be used differ.  The
 269      * {@code ImageReader.checkReadParamBandSettings} method may
 270      * be used to automate this test.
 271      *
 272      * @param destinationBands an array of integer band indices to be
 273      * used.
 274      *
 275      * @exception IllegalArgumentException if {@code destinationBands}
 276      * contains a negative or duplicate value.
 277      *
 278      * @see #getDestinationBands
 279      * @see #getSourceBands
 280      * @see ImageReader#checkReadParamBandSettings
 281      */
 282     public void setDestinationBands(int[] destinationBands) {
 283         if (destinationBands == null) {
 284             this.destinationBands = null;
 285         } else {
 286             int numBands = destinationBands.length;
 287             for (int i = 0; i < numBands; i++) {
 288                 int band = destinationBands[i];
 289                 if (band < 0) {
 290                     throw new IllegalArgumentException("Band value < 0!");
 291                 }
 292                 for (int j = i + 1; j < numBands; j++) {
 293                     if (band == destinationBands[j]) {
 294                         throw new IllegalArgumentException("Duplicate band value!");
 295                     }
 296                 }
 297             }
 298             this.destinationBands = destinationBands.clone();
 299         }
 300     }
 301 
 302     /**
 303      * Returns the set of band indices where data will be placed.
 304      * If no value has been set, {@code null} is returned to
 305      * indicate that all destination bands will be used.
 306      *
 307      * @return the indices of the destination bands to be used,
 308      * or {@code null}.
 309      *
 310      * @see #setDestinationBands
 311      */
 312     public int[] getDestinationBands() {
 313         if (destinationBands == null) {
 314             return null;
 315         } else {
 316             return destinationBands.clone();
 317         }
 318     }
 319 
 320     /**
 321      * Returns {@code true} if this reader allows the source
 322      * image to be rendered at an arbitrary size as part of the
 323      * decoding process, by means of the
 324      * {@code setSourceRenderSize} method.  If this method
 325      * returns {@code false}, calls to
 326      * {@code setSourceRenderSize} will throw an
 327      * {@code UnsupportedOperationException}.
 328      *
 329      * @return {@code true} if setting source rendering size is
 330      * supported.
 331      *
 332      * @see #setSourceRenderSize
 333      */
 334     public boolean canSetSourceRenderSize() {
 335         return canSetSourceRenderSize;
 336     }
 337 
 338     /**
 339      * If the image is able to be rendered at an arbitrary size, sets
 340      * the source width and height to the supplied values.  Note that
 341      * the values returned from the {@code getWidth} and
 342      * {@code getHeight} methods on {@code ImageReader} are
 343      * not affected by this method; they will continue to return the
 344      * default size for the image.  Similarly, if the image is also
 345      * tiled the tile width and height are given in terms of the default
 346      * size.
 347      *
 348      * <p> Typically, the width and height should be chosen such that
 349      * the ratio of width to height closely approximates the aspect
 350      * ratio of the image, as returned from
 351      * {@code ImageReader.getAspectRatio}.
 352      *
 353      * <p> If this plug-in does not allow the rendering size to be
 354      * set, an {@code UnsupportedOperationException} will be
 355      * thrown.
 356      *
 357      * <p> To remove the render size setting, pass in a value of
 358      * {@code null} for {@code size}.
 359      *
 360      * @param size a {@code Dimension} indicating the desired
 361      * width and height.
 362      *
 363      * @exception IllegalArgumentException if either the width or the
 364      * height is negative or 0.
 365      * @exception UnsupportedOperationException if image resizing
 366      * is not supported by this plug-in.
 367      *
 368      * @see #getSourceRenderSize
 369      * @see ImageReader#getWidth
 370      * @see ImageReader#getHeight
 371      * @see ImageReader#getAspectRatio
 372      */
 373     public void setSourceRenderSize(Dimension size)
 374         throws UnsupportedOperationException {
 375         if (!canSetSourceRenderSize()) {
 376             throw new UnsupportedOperationException
 377                 ("Can't set source render size!");
 378         }
 379 
 380         if (size == null) {
 381             this.sourceRenderSize = null;
 382         } else {
 383             if (size.width <= 0 || size.height <= 0) {
 384                 throw new IllegalArgumentException("width or height <= 0!");
 385             }
 386             this.sourceRenderSize = (Dimension)size.clone();
 387         }
 388     }
 389 
 390     /**
 391      * Returns the width and height of the source image as it
 392      * will be rendered during decoding, if they have been set via the
 393      * {@code setSourceRenderSize} method.  A
 394      * {@code null} value indicates that no setting has been made.
 395      *
 396      * @return the rendered width and height of the source image
 397      * as a {@code Dimension}.
 398      *
 399      * @see #setSourceRenderSize
 400      */
 401     public Dimension getSourceRenderSize() {
 402         return (sourceRenderSize == null) ?
 403             null : (Dimension)sourceRenderSize.clone();
 404     }
 405 
 406     /**
 407      * Sets the range of progressive passes that will be decoded.
 408      * Passes outside of this range will be ignored.
 409      *
 410      * <p> A progressive pass is a re-encoding of the entire image,
 411      * generally at progressively higher effective resolutions, but
 412      * requiring greater transmission bandwidth.  The most common use
 413      * of progressive encoding is found in the JPEG format, where
 414      * successive passes include more detailed representations of the
 415      * high-frequency image content.
 416      *
 417      * <p> The actual number of passes to be decoded is determined
 418      * during decoding, based on the number of actual passes available
 419      * in the stream.  Thus if {@code minPass + numPasses - 1} is
 420      * larger than the index of the last available passes, decoding
 421      * will end with that pass.
 422      *
 423      * <p> A value of {@code numPasses} of
 424      * {@code Integer.MAX_VALUE} indicates that all passes from
 425      * {@code minPass} forward should be read.  Otherwise, the
 426      * index of the last pass (<i>i.e.</i>, {@code minPass + numPasses - 1})
 427      * must not exceed {@code Integer.MAX_VALUE}.
 428      *
 429      * <p> There is no {@code unsetSourceProgressivePasses}
 430      * method; the same effect may be obtained by calling
 431      * {@code setSourceProgressivePasses(0, Integer.MAX_VALUE)}.
 432      *
 433      * @param minPass the index of the first pass to be decoded.
 434      * @param numPasses the maximum number of passes to be decoded.
 435      *
 436      * @exception IllegalArgumentException if {@code minPass} is
 437      * negative, {@code numPasses} is negative or 0, or
 438      * {@code numPasses} is smaller than
 439      * {@code Integer.MAX_VALUE} but
 440      * {@code minPass + numPasses - 1} is greater than
 441      * {@code INTEGER.MAX_VALUE}.
 442      *
 443      * @see #getSourceMinProgressivePass
 444      * @see #getSourceMaxProgressivePass
 445      */
 446     public void setSourceProgressivePasses(int minPass, int numPasses) {
 447         if (minPass < 0) {
 448             throw new IllegalArgumentException("minPass < 0!");
 449         }
 450         if (numPasses <= 0) {
 451             throw new IllegalArgumentException("numPasses <= 0!");
 452         }
 453         if ((numPasses != Integer.MAX_VALUE) &&
 454             (((minPass + numPasses - 1) & 0x80000000) != 0)) {
 455             throw new IllegalArgumentException
 456                 ("minPass + numPasses - 1 > INTEGER.MAX_VALUE!");
 457         }
 458 
 459         this.minProgressivePass = minPass;
 460         this.numProgressivePasses = numPasses;
 461     }
 462 
 463     /**
 464      * Returns the index of the first progressive pass that will be
 465      * decoded. If no value has been set, 0 will be returned (which is
 466      * the correct value).
 467      *
 468      * @return the index of the first pass that will be decoded.
 469      *
 470      * @see #setSourceProgressivePasses
 471      * @see #getSourceNumProgressivePasses
 472      */
 473     public int getSourceMinProgressivePass() {
 474         return minProgressivePass;
 475     }
 476 
 477     /**
 478      * If {@code getSourceNumProgressivePasses} is equal to
 479      * {@code Integer.MAX_VALUE}, returns
 480      * {@code Integer.MAX_VALUE}.  Otherwise, returns
 481      * {@code getSourceMinProgressivePass() +
 482      * getSourceNumProgressivePasses() - 1}.
 483      *
 484      * @return the index of the last pass to be read, or
 485      * {@code Integer.MAX_VALUE}.
 486      */
 487     public int getSourceMaxProgressivePass() {
 488         if (numProgressivePasses == Integer.MAX_VALUE) {
 489             return Integer.MAX_VALUE;
 490         } else {
 491             return minProgressivePass + numProgressivePasses - 1;
 492         }
 493     }
 494 
 495     /**
 496      * Returns the number of the progressive passes that will be
 497      * decoded. If no value has been set,
 498      * {@code Integer.MAX_VALUE} will be returned (which is the
 499      * correct value).
 500      *
 501      * @return the number of the passes that will be decoded.
 502      *
 503      * @see #setSourceProgressivePasses
 504      * @see #getSourceMinProgressivePass
 505      */
 506     public int getSourceNumProgressivePasses() {
 507         return numProgressivePasses;
 508     }
 509 }
--- EOF ---