001 /*
002 * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.imageio;
027
028 import java.awt.Dimension;
029 import java.awt.image.BufferedImage;
030
031 /**
032 * A class describing how a stream is to be decoded. Instances of
033 * this class or its subclasses are used to supply prescriptive
034 * "how-to" information to instances of <code>ImageReader</code>.
035 *
036 * <p> An image encoded as part of a file or stream may be thought of
037 * extending out in multiple dimensions: the spatial dimensions of
038 * width and height, a number of bands, and a number of progressive
039 * decoding passes. This class allows a contiguous (hyper)rectangular
040 * subarea of the image in all of these dimensions to be selected for
041 * decoding. Additionally, the spatial dimensions may be subsampled
042 * discontinuously. Finally, color and format conversions may be
043 * specified by controlling the <code>ColorModel</code> and
044 * <code>SampleModel</code> of the destination image, either by
045 * providing a <code>BufferedImage</code> or by using an
046 * <code>ImageTypeSpecifier</code>.
047 *
048 * <p> An <code>ImageReadParam</code> object is used to specify how an
049 * image, or a set of images, will be converted on input from
050 * a stream in the context of the Java Image I/O framework. A plug-in for a
051 * specific image format will return instances of
052 * <code>ImageReadParam</code> from the
053 * <code>getDefaultReadParam</code> method of its
054 * <code>ImageReader</code> implementation.
055 *
056 * <p> The state maintained by an instance of
057 * <code>ImageReadParam</code> is independent of any particular image
058 * being decoded. When actual decoding takes place, the values set in
059 * the read param are combined with the actual properties of the image
060 * being decoded from the stream and the destination
061 * <code>BufferedImage</code> that will receive the decoded pixel
062 * data. For example, the source region set using
063 * <code>setSourceRegion</code> will first be intersected with the
064 * actual valid source area. The result will be translated by the
065 * value returned by <code>getDestinationOffset</code>, and the
066 * resulting rectangle intersected with the actual valid destination
067 * area to yield the destination area that will be written.
068 *
069 * <p> The parameters specified by an <code>ImageReadParam</code> are
070 * applied to an image as follows. First, if a rendering size has
071 * been set by <code>setSourceRenderSize</code>, the entire decoded
072 * image is rendered at the size given by
073 * <code>getSourceRenderSize</code>. Otherwise, the image has its
074 * natural size given by <code>ImageReader.getWidth</code> and
075 * <code>ImageReader.getHeight</code>.
076 *
077 * <p> Next, the image is clipped against the source region
078 * specified by <code>getSourceXOffset</code>, <code>getSourceYOffset</code>,
079 * <code>getSourceWidth</code>, and <code>getSourceHeight</code>.
080 *
081 * <p> The resulting region is then subsampled according to the
082 * factors given in {@link IIOParam#setSourceSubsampling
083 * <code>IIOParam.setSourceSubsampling</code>}. The first pixel,
084 * the number of pixels per row, and the number of rows all depend
085 * on the subsampling settings.
086 * Call the minimum X and Y coordinates of the resulting rectangle
087 * (<code>minX</code>, <code>minY</code>), its width <code>w</code>
088 * and its height <code>h</code>.
089 *
090 * <p> This rectangle is offset by
091 * (<code>getDestinationOffset().x</code>,
092 * <code>getDestinationOffset().y</code>) and clipped against the
093 * destination bounds. If no destination image has been set, the
094 * destination is defined to have a width of
095 * <code>getDestinationOffset().x</code> + <code>w</code>, and a
096 * height of <code>getDestinationOffset().y</code> + <code>h</code> so
097 * that all pixels of the source region may be written to the
098 * destination.
099 *
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 * @version 0.5
126 *
127 * @see ImageReader
128 * @see ImageWriter
129 * @see ImageWriteParam
130 */
131 public class ImageReadParam extends IIOParam {
132
133 /**
134 * <code>true</code> if this <code>ImageReadParam</code> allows
135 * the source rendering dimensions to be set. By default, the
136 * value is <code>false</code>. Subclasses must set this value
137 * manually.
138 *
139 * <p> <code>ImageReader</code>s that do not support setting of
140 * the source render size should set this value to
141 * <code>false</code>.
142 */
143 protected boolean canSetSourceRenderSize = false;
144
145 /**
146 * The desired rendering width and height of the source, if
147 * <code>canSetSourceRenderSize</code> is <code>true</code>, or
148 * <code>null</code>.
149 *
150 * <p> <code>ImageReader</code>s that do not support setting of
151 * the source render size may ignore this value.
152 */
153 protected Dimension sourceRenderSize = null;
154
155 /**
156 * The current destination <code>BufferedImage</code>, or
157 * <code>null</code> if none has been set. By default, the value
158 * is <code>null</code>.
159 */
160 protected BufferedImage destination = null;
161
162 /**
163 * The set of destination bands to be used, as an array of
164 * <code>int</code>s. By default, the value is <code>null</code>,
165 * indicating all destination bands should be written in order.
166 */
167 protected int[] destinationBands = null;
168
169 /**
170 * The minimum index of a progressive pass to read from the
171 * source. By default, the value is set to 0, which indicates
172 * that passes starting with the first available pass should be
173 * decoded.
174 *
175 * <p> Subclasses should ensure that this value is
176 * non-negative.
177 */
178 protected int minProgressivePass = 0;
179
180 /**
181 * The maximum number of progressive passes to read from the
182 * source. By default, the value is set to
183 * <code>Integer.MAX_VALUE</code>, which indicates that passes up
184 * to and including the last available pass should be decoded.
185 *
186 * <p> Subclasses should ensure that this value is positive.
187 * Additionally, if the value is not
188 * <code>Integer.MAX_VALUE</code>, then <code>minProgressivePass +
189 * numProgressivePasses - 1</code> should not exceed
190 * <code>Integer.MAX_VALUE</code>.
191 */
192 protected int numProgressivePasses = Integer.MAX_VALUE;
193
194 /**
195 * Constructs an <code>ImageReadParam</code>.
196 */
197 public ImageReadParam() {
198 }
199
200 // Comment inherited
201 public void setDestinationType(ImageTypeSpecifier destinationType) {
202 super .setDestinationType(destinationType);
203 setDestination(null);
204 }
205
206 /**
207 * Supplies a <code>BufferedImage</code> to be used as the
208 * destination for decoded pixel data. The currently set image
209 * will be written to by the <code>read</code>,
210 * <code>readAll</code>, and <code>readRaster</code> methods, and
211 * a reference to it will be returned by those methods.
212 *
213 * <p> Pixel data from the aforementioned methods will be written
214 * starting at the offset specified by
215 * <code>getDestinationOffset</code>.
216 *
217 * <p> If <code>destination</code> is <code>null</code>, a
218 * newly-created <code>BufferedImage</code> will be returned by
219 * those methods.
220 *
221 * <p> At the time of reading, the image is checked to verify that
222 * its <code>ColorModel</code> and <code>SampleModel</code>
223 * correspond to one of the <code>ImageTypeSpecifier</code>s
224 * returned from the <code>ImageReader</code>'s
225 * <code>getImageTypes</code> method. If it does not, the reader
226 * will throw an <code>IIOException</code>.
227 *
228 * @param destination the BufferedImage to be written to, or
229 * <code>null</code>.
230 *
231 * @see #getDestination
232 */
233 public void setDestination(BufferedImage destination) {
234 this .destination = destination;
235 }
236
237 /**
238 * Returns the <code>BufferedImage</code> currently set by the
239 * <code>setDestination</code> method, or <code>null</code>
240 * if none is set.
241 *
242 * @return the BufferedImage to be written to.
243 *
244 * @see #setDestination
245 */
246 public BufferedImage getDestination() {
247 return destination;
248 }
249
250 /**
251 * Sets the indices of the destination bands where data
252 * will be placed. Duplicate indices are not allowed.
253 *
254 * <p> A <code>null</code> value indicates that all destination
255 * bands will be used.
256 *
257 * <p> Choosing a destination band subset will not affect the
258 * number of bands in the output image of a read if no destination
259 * image is specified; the created destination image will still
260 * have the same number of bands as if this method had never been
261 * called. If a different number of bands in the destination
262 * image is desired, an image must be supplied using the
263 * <code>ImageReadParam.setDestination</code> method.
264 *
265 * <p> At the time of reading or writing, an
266 * <code>IllegalArgumentException</code> will be thrown by the
267 * reader or writer if a value larger than the largest destination
268 * band index has been specified, or if the number of source bands
269 * and destination bands to be used differ. The
270 * <code>ImageReader.checkReadParamBandSettings</code> method may
271 * be used to automate this test.
272 *
273 * @param destinationBands an array of integer band indices to be
274 * used.
275 *
276 * @exception IllegalArgumentException if <code>destinationBands</code>
277 * contains a negative or duplicate value.
278 *
279 * @see #getDestinationBands
280 * @see #getSourceBands
281 * @see ImageReader#checkReadParamBandSettings
282 */
283 public void setDestinationBands(int[] destinationBands) {
284 if (destinationBands == null) {
285 this .destinationBands = null;
286 } else {
287 int numBands = destinationBands.length;
288 for (int i = 0; i < numBands; i++) {
289 int band = destinationBands[i];
290 if (band < 0) {
291 throw new IllegalArgumentException(
292 "Band value < 0!");
293 }
294 for (int j = i + 1; j < numBands; j++) {
295 if (band == destinationBands[j]) {
296 throw new IllegalArgumentException(
297 "Duplicate band value!");
298 }
299 }
300 }
301 this .destinationBands = (int[]) destinationBands.clone();
302 }
303 }
304
305 /**
306 * Returns the set of band indices where data will be placed.
307 * If no value has been set, <code>null</code> is returned to
308 * indicate that all destination bands will be used.
309 *
310 * @return the indices of the destination bands to be used,
311 * or <code>null</code>.
312 *
313 * @see #setDestinationBands
314 */
315 public int[] getDestinationBands() {
316 if (destinationBands == null) {
317 return null;
318 } else {
319 return (int[]) (destinationBands.clone());
320 }
321 }
322
323 /**
324 * Returns <code>true</code> if this reader allows the source
325 * image to be rendered at an arbitrary size as part of the
326 * decoding process, by means of the
327 * <code>setSourceRenderSize</code> method. If this method
328 * returns <code>false</code>, calls to
329 * <code>setSourceRenderSize</code> will throw an
330 * <code>UnsupportedOperationException</code>.
331 *
332 * @return <code>true</code> if setting source rendering size is
333 * supported.
334 *
335 * @see #setSourceRenderSize
336 */
337 public boolean canSetSourceRenderSize() {
338 return canSetSourceRenderSize;
339 }
340
341 /**
342 * If the image is able to be rendered at an arbitrary size, sets
343 * the source width and height to the supplied values. Note that
344 * the values returned from the <code>getWidth</code> and
345 * <code>getHeight</code> methods on <code>ImageReader</code> are
346 * not affected by this method; they will continue to return the
347 * default size for the image. Similarly, if the image is also
348 * tiled the tile width and height are given in terms of the default
349 * size.
350 *
351 * <p> Typically, the width and height should be chosen such that
352 * the ratio of width to height closely approximates the aspect
353 * ratio of the image, as returned from
354 * <code>ImageReader.getAspectRatio</code>.
355 *
356 * <p> If this plug-in does not allow the rendering size to be
357 * set, an <code>UnsupportedOperationException</code> will be
358 * thrown.
359 *
360 * <p> To remove the render size setting, pass in a value of
361 * <code>null</code> for <code>size</code>.
362 *
363 * @param size a <code>Dimension</code> indicating the desired
364 * width and height.
365 *
366 * @exception IllegalArgumentException if either the width or the
367 * height is negative or 0.
368 * @exception UnsupportedOperationException if image resizing
369 * is not supported by this plug-in.
370 *
371 * @see #getSourceRenderSize
372 * @see ImageReader#getWidth
373 * @see ImageReader#getHeight
374 * @see ImageReader#getAspectRatio
375 */
376 public void setSourceRenderSize(Dimension size)
377 throws UnsupportedOperationException {
378 if (!canSetSourceRenderSize()) {
379 throw new UnsupportedOperationException(
380 "Can't set source render size!");
381 }
382
383 if (size == null) {
384 this .sourceRenderSize = null;
385 } else {
386 if (size.width <= 0 || size.height <= 0) {
387 throw new IllegalArgumentException(
388 "width or height <= 0!");
389 }
390 this .sourceRenderSize = (Dimension) size.clone();
391 }
392 }
393
394 /**
395 * Returns the width and height of the source image as it
396 * will be rendered during decoding, if they have been set via the
397 * <code>setSourceRenderSize</code> method. A
398 * <code>null</code>value indicates that no setting has been made.
399 *
400 * @return the rendered width and height of the source image
401 * as a <code>Dimension</code>.
402 *
403 * @see #setSourceRenderSize
404 */
405 public Dimension getSourceRenderSize() {
406 return (sourceRenderSize == null) ? null
407 : (Dimension) sourceRenderSize.clone();
408 }
409
410 /**
411 * Sets the range of progressive passes that will be decoded.
412 * Passes outside of this range will be ignored.
413 *
414 * <p> A progressive pass is a re-encoding of the entire image,
415 * generally at progressively higher effective resolutions, but
416 * requiring greater transmission bandwidth. The most common use
417 * of progressive encoding is found in the JPEG format, where
418 * successive passes include more detailed representations of the
419 * high-frequency image content.
420 *
421 * <p> The actual number of passes to be decoded is determined
422 * during decoding, based on the number of actual passes available
423 * in the stream. Thus if <code>minPass + numPasses - 1</code> is
424 * larger than the index of the last available passes, decoding
425 * will end with that pass.
426 *
427 * <p> A value of <code>numPasses</code> of
428 * <code>Integer.MAX_VALUE</code> indicates that all passes from
429 * <code>minPass</code> forward should be read. Otherwise, the
430 * index of the last pass (<i>i.e.</i>, <code>minPass + numPasses
431 * - 1</code>) must not exceed <code>Integer.MAX_VALUE</code>.
432 *
433 * <p> There is no <code>unsetSourceProgressivePasses</code>
434 * method; the same effect may be obtained by calling
435 * <code>setSourceProgressivePasses(0, Integer.MAX_VALUE)</code>.
436 *
437 * @param minPass the index of the first pass to be decoded.
438 * @param numPasses the maximum number of passes to be decoded.
439 *
440 * @exception IllegalArgumentException if <code>minPass</code> is
441 * negative, <code>numPasses</code> is negative or 0, or
442 * <code>numPasses</code> is smaller than
443 * <code>Integer.MAX_VALUE</code> but <code>minPass +
444 * numPasses - 1</code> is greater than
445 * <code>INTEGER.MAX_VALUE</code>.
446 *
447 * @see #getSourceMinProgressivePass
448 * @see #getSourceMaxProgressivePass
449 */
450 public void setSourceProgressivePasses(int minPass, int numPasses) {
451 if (minPass < 0) {
452 throw new IllegalArgumentException("minPass < 0!");
453 }
454 if (numPasses <= 0) {
455 throw new IllegalArgumentException("numPasses <= 0!");
456 }
457 if ((numPasses != Integer.MAX_VALUE)
458 && (((minPass + numPasses - 1) & 0x80000000) != 0)) {
459 throw new IllegalArgumentException(
460 "minPass + numPasses - 1 > INTEGER.MAX_VALUE!");
461 }
462
463 this .minProgressivePass = minPass;
464 this .numProgressivePasses = numPasses;
465 }
466
467 /**
468 * Returns the index of the first progressive pass that will be
469 * decoded. If no value has been set, 0 will be returned (which is
470 * the correct value).
471 *
472 * @return the index of the first pass that will be decoded.
473 *
474 * @see #setSourceProgressivePasses
475 * @see #getSourceNumProgressivePasses
476 */
477 public int getSourceMinProgressivePass() {
478 return minProgressivePass;
479 }
480
481 /**
482 * If <code>getSourceNumProgressivePasses</code> is equal to
483 * <code>Integer.MAX_VALUE</code>, returns
484 * <code>Integer.MAX_VALUE</code>. Otherwise, returns
485 * <code>getSourceMinProgressivePass() +
486 * getSourceNumProgressivePasses() - 1</code>.
487 *
488 * @return the index of the last pass to be read, or
489 * <code>Integer.MAX_VALUE</code>.
490 */
491 public int getSourceMaxProgressivePass() {
492 if (numProgressivePasses == Integer.MAX_VALUE) {
493 return Integer.MAX_VALUE;
494 } else {
495 return minProgressivePass + numProgressivePasses - 1;
496 }
497 }
498
499 /**
500 * Returns the number of the progressive passes that will be
501 * decoded. If no value has been set,
502 * <code>Integer.MAX_VALUE</code> will be returned (which is the
503 * correct value).
504 *
505 * @return the number of the passes that will be decoded.
506 *
507 * @see #setSourceProgressivePasses
508 * @see #getSourceMinProgressivePass
509 */
510 public int getSourceNumProgressivePasses() {
511 return numProgressivePasses;
512 }
513 }
|