blob: 3abb225268f5173bb48cb3eb230a5f3942da783d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.imageio;
27
28import java.awt.Dimension;
29import 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 */
130public 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 = (int[])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 (int[])(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}