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 }
510