0001 /*
0002 * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.imageio;
0027
0028 import java.awt.color.ICC_Profile;
0029 import java.awt.image.LookupTable;
0030 import java.awt.image.RenderedImage;
0031 import java.awt.Dimension;
0032 import java.util.Locale;
0033
0034 /**
0035 * A class describing how a stream is to be encoded. Instances of
0036 * this class or its subclasses are used to supply prescriptive
0037 * "how-to" information to instances of <code>ImageWriter</code>.
0038 *
0039 * <p> A plug-in for a specific image format may define a subclass of
0040 * this class, and return objects of that class from the
0041 * <code>getDefaultWriteParam</code> method of its
0042 * <code>ImageWriter</code> implementation. For example, the built-in
0043 * JPEG writer plug-in will return instances of
0044 * <code>javax.imageio.plugins.jpeg.JPEGImageWriteParam</code>.
0045 *
0046 * <p> The region of the image to be written is determined by first
0047 * intersecting the actual bounds of the image with the rectangle
0048 * specified by <code>IIOParam.setSourceRegion</code>, if any. If the
0049 * resulting rectangle has a width or height of zero, the writer will
0050 * throw an <code>IIOException</code>. If the intersection is
0051 * non-empty, writing will commence with the first subsampled pixel
0052 * and include additional pixels within the intersected bounds
0053 * according to the horizontal and vertical subsampling factors
0054 * specified by {@link IIOParam#setSourceSubsampling
0055 * <code>IIOParam.setSourceSubsampling</code>}.
0056 *
0057 * <p> Individual features such as tiling, progressive encoding, and
0058 * compression may be set in one of four modes.
0059 * <code>MODE_DISABLED</code> disables the features;
0060 * <code>MODE_DEFAULT</code> enables the feature with
0061 * writer-controlled parameter values; <code>MODE_EXPLICIT</code>
0062 * enables the feature and allows the use of a <code>set</code> method
0063 * to provide additional parameters; and
0064 * <code>MODE_COPY_FROM_METADATA</code> copies relevant parameter
0065 * values from the stream and image metadata objects passed to the
0066 * writer. The default for all features is
0067 * <code>MODE_COPY_FROM_METADATA</code>. Non-standard features
0068 * supplied in subclasses are encouraged, but not required to use a
0069 * similar scheme.
0070 *
0071 * <p> Plug-in writers may extend the functionality of
0072 * <code>ImageWriteParam</code> by providing a subclass that implements
0073 * additional, plug-in specific interfaces. It is up to the plug-in
0074 * to document what interfaces are available and how they are to be
0075 * used. Writers will silently ignore any extended features of an
0076 * <code>ImageWriteParam</code> subclass of which they are not aware.
0077 * Also, they may ignore any optional features that they normally
0078 * disable when creating their own <code>ImageWriteParam</code>
0079 * instances via <code>getDefaultWriteParam</code>.
0080 *
0081 * <p> Note that unless a query method exists for a capability, it must
0082 * be supported by all <code>ImageWriter</code> implementations
0083 * (<i>e.g.</i> progressive encoding is optional, but subsampling must be
0084 * supported).
0085 *
0086 * @version 0.5
0087 *
0088 * @see ImageReadParam
0089 */
0090 public class ImageWriteParam extends IIOParam {
0091
0092 /**
0093 * A constant value that may be passed into methods such as
0094 * <code>setTilingMode</code>, <code>setProgressiveMode</code>,
0095 * and <code>setCompressionMode</code> to disable a feature for
0096 * future writes. That is, when this mode is set the stream will
0097 * <b>not</b> be tiled, progressive, or compressed, and the
0098 * relevant accessor methods will throw an
0099 * <code>IllegalStateException</code>.
0100 *
0101 * @see #MODE_EXPLICIT
0102 * @see #MODE_COPY_FROM_METADATA
0103 * @see #MODE_DEFAULT
0104 * @see #setProgressiveMode
0105 * @see #getProgressiveMode
0106 * @see #setTilingMode
0107 * @see #getTilingMode
0108 * @see #setCompressionMode
0109 * @see #getCompressionMode
0110 */
0111 public static final int MODE_DISABLED = 0;
0112
0113 /**
0114 * A constant value that may be passed into methods such as
0115 * <code>setTilingMode</code>,
0116 * <code>setProgressiveMode</code>, and
0117 * <code>setCompressionMode</code> to enable that feature for
0118 * future writes. That is, when this mode is enabled the stream
0119 * will be tiled, progressive, or compressed according to a
0120 * sensible default chosen internally by the writer in a plug-in
0121 * dependent way, and the relevant accessor methods will
0122 * throw an <code>IllegalStateException</code>.
0123 *
0124 * @see #MODE_DISABLED
0125 * @see #MODE_EXPLICIT
0126 * @see #MODE_COPY_FROM_METADATA
0127 * @see #setProgressiveMode
0128 * @see #getProgressiveMode
0129 * @see #setTilingMode
0130 * @see #getTilingMode
0131 * @see #setCompressionMode
0132 * @see #getCompressionMode
0133 */
0134 public static final int MODE_DEFAULT = 1;
0135
0136 /**
0137 * A constant value that may be passed into methods such as
0138 * <code>setTilingMode</code> or <code>setCompressionMode</code>
0139 * to enable a feature for future writes. That is, when this mode
0140 * is set the stream will be tiled or compressed according to
0141 * additional information supplied to the corresponding
0142 * <code>set</code> methods in this class and retrievable from the
0143 * corresponding <code>get</code> methods. Note that this mode is
0144 * not supported for progressive output.
0145 *
0146 * @see #MODE_DISABLED
0147 * @see #MODE_COPY_FROM_METADATA
0148 * @see #MODE_DEFAULT
0149 * @see #setProgressiveMode
0150 * @see #getProgressiveMode
0151 * @see #setTilingMode
0152 * @see #getTilingMode
0153 * @see #setCompressionMode
0154 * @see #getCompressionMode
0155 */
0156 public static final int MODE_EXPLICIT = 2;
0157
0158 /**
0159 * A constant value that may be passed into methods such as
0160 * <code>setTilingMode</code>, <code>setProgressiveMode</code>, or
0161 * <code>setCompressionMode</code> to enable that feature for
0162 * future writes. That is, when this mode is enabled the stream
0163 * will be tiled, progressive, or compressed based on the contents
0164 * of stream and/or image metadata passed into the write
0165 * operation, and any relevant accessor methods will throw an
0166 * <code>IllegalStateException</code>.
0167 *
0168 * <p> This is the default mode for all features, so that a read
0169 * including metadata followed by a write including metadata will
0170 * preserve as much information as possible.
0171 *
0172 * @see #MODE_DISABLED
0173 * @see #MODE_EXPLICIT
0174 * @see #MODE_DEFAULT
0175 * @see #setProgressiveMode
0176 * @see #getProgressiveMode
0177 * @see #setTilingMode
0178 * @see #getTilingMode
0179 * @see #setCompressionMode
0180 * @see #getCompressionMode
0181 */
0182 public static final int MODE_COPY_FROM_METADATA = 3;
0183
0184 // If more modes are added, this should be updated.
0185 private static final int MAX_MODE = MODE_COPY_FROM_METADATA;
0186
0187 /**
0188 * A <code>boolean</code> that is <code>true</code> if this
0189 * <code>ImageWriteParam</code> allows tile width and tile height
0190 * parameters to be set. By default, the value is
0191 * <code>false</code>. Subclasses must set the value manually.
0192 *
0193 * <p> Subclasses that do not support writing tiles should ensure
0194 * that this value is set to <code>false</code>.
0195 */
0196 protected boolean canWriteTiles = false;
0197
0198 /**
0199 * The mode controlling tiling settings, which Must be
0200 * set to one of the four <code>MODE_*</code> values. The default
0201 * is <code>MODE_COPY_FROM_METADATA</code>.
0202 *
0203 * <p> Subclasses that do not writing tiles may ignore this value.
0204 *
0205 * @see #MODE_DISABLED
0206 * @see #MODE_EXPLICIT
0207 * @see #MODE_COPY_FROM_METADATA
0208 * @see #MODE_DEFAULT
0209 * @see #setTilingMode
0210 * @see #getTilingMode
0211 */
0212 protected int tilingMode = MODE_COPY_FROM_METADATA;
0213
0214 /**
0215 * An array of preferred tile size range pairs. The default value
0216 * is <code>null</code>, which indicates that there are no
0217 * preferred sizes. If the value is non-<code>null</code>, it
0218 * must have an even length of at least two.
0219 *
0220 * <p> Subclasses that do not support writing tiles may ignore
0221 * this value.
0222 *
0223 * @see #getPreferredTileSizes
0224 */
0225 protected Dimension[] preferredTileSizes = null;
0226
0227 /**
0228 * A <code>boolean</code> that is <code>true</code> if tiling
0229 * parameters have been specified.
0230 *
0231 * <p> Subclasses that do not support writing tiles may ignore
0232 * this value.
0233 */
0234 protected boolean tilingSet = false;
0235
0236 /**
0237 * The width of each tile if tiling has been set, or 0 otherwise.
0238 *
0239 * <p> Subclasses that do not support tiling may ignore this
0240 * value.
0241 */
0242 protected int tileWidth = 0;
0243
0244 /**
0245 * The height of each tile if tiling has been set, or 0 otherwise.
0246 * The initial value is <code>0</code>.
0247 *
0248 * <p> Subclasses that do not support tiling may ignore this
0249 * value.
0250 */
0251 protected int tileHeight = 0;
0252
0253 /**
0254 * A <code>boolean</code> that is <code>true</code> if this
0255 * <code>ImageWriteParam</code> allows tiling grid offset
0256 * parameters to be set. By default, the value is
0257 * <code>false</code>. Subclasses must set the value manually.
0258 *
0259 * <p> Subclasses that do not support writing tiles, or that
0260 * supprt writing but not offsetting tiles must ensure that this
0261 * value is set to <code>false</code>.
0262 */
0263 protected boolean canOffsetTiles = false;
0264
0265 /**
0266 * The amount by which the tile grid origin should be offset
0267 * horizontally from the image origin if tiling has been set,
0268 * or 0 otherwise. The initial value is <code>0</code>.
0269 *
0270 * <p> Subclasses that do not support offsetting tiles may ignore
0271 * this value.
0272 */
0273 protected int tileGridXOffset = 0;
0274
0275 /**
0276 * The amount by which the tile grid origin should be offset
0277 * vertically from the image origin if tiling has been set,
0278 * or 0 otherwise. The initial value is <code>0</code>.
0279 *
0280 * <p> Subclasses that do not support offsetting tiles may ignore
0281 * this value.
0282 */
0283 protected int tileGridYOffset = 0;
0284
0285 /**
0286 * A <code>boolean</code> that is <code>true</code> if this
0287 * <code>ImageWriteParam</code> allows images to be written as a
0288 * progressive sequence of increasing quality passes. By default,
0289 * the value is <code>false</code>. Subclasses must set the value
0290 * manually.
0291 *
0292 * <p> Subclasses that do not support progressive encoding must
0293 * ensure that this value is set to <code>false</code>.
0294 */
0295 protected boolean canWriteProgressive = false;
0296
0297 /**
0298 * The mode controlling progressive encoding, which must be set to
0299 * one of the four <code>MODE_*</code> values, except
0300 * <code>MODE_EXPLICIT</code>. The default is
0301 * <code>MODE_COPY_FROM_METADATA</code>.
0302 *
0303 * <p> Subclasses that do not support progressive encoding may
0304 * ignore this value.
0305 *
0306 * @see #MODE_DISABLED
0307 * @see #MODE_EXPLICIT
0308 * @see #MODE_COPY_FROM_METADATA
0309 * @see #MODE_DEFAULT
0310 * @see #setProgressiveMode
0311 * @see #getProgressiveMode
0312 */
0313 protected int progressiveMode = MODE_COPY_FROM_METADATA;
0314
0315 /**
0316 * A <code>boolean</code> that is <code>true</code> if this writer
0317 * can write images using compression. By default, the value is
0318 * <code>false</code>. Subclasses must set the value manually.
0319 *
0320 * <p> Subclasses that do not support compression must ensure that
0321 * this value is set to <code>false</code>.
0322 */
0323 protected boolean canWriteCompressed = false;
0324
0325 /**
0326 * The mode controlling compression settings, which must be set to
0327 * one of the four <code>MODE_*</code> values. The default is
0328 * <code>MODE_COPY_FROM_METADATA</code>.
0329 *
0330 * <p> Subclasses that do not support compression may ignore this
0331 * value.
0332 *
0333 * @see #MODE_DISABLED
0334 * @see #MODE_EXPLICIT
0335 * @see #MODE_COPY_FROM_METADATA
0336 * @see #MODE_DEFAULT
0337 * @see #setCompressionMode
0338 * @see #getCompressionMode
0339 */
0340 protected int compressionMode = MODE_COPY_FROM_METADATA;
0341
0342 /**
0343 * An array of <code>String</code>s containing the names of the
0344 * available compression types. Subclasses must set the value
0345 * manually.
0346 *
0347 * <p> Subclasses that do not support compression may ignore this
0348 * value.
0349 */
0350 protected String[] compressionTypes = null;
0351
0352 /**
0353 * A <code>String</code> containing the name of the current
0354 * compression type, or <code>null</code> if none is set.
0355 *
0356 * <p> Subclasses that do not support compression may ignore this
0357 * value.
0358 */
0359 protected String compressionType = null;
0360
0361 /**
0362 * A <code>float</code> containing the current compression quality
0363 * setting. The initial value is <code>1.0F</code>.
0364 *
0365 * <p> Subclasses that do not support compression may ignore this
0366 * value.
0367 */
0368 protected float compressionQuality = 1.0F;
0369
0370 /**
0371 * A <code>Locale</code> to be used to localize compression type
0372 * names and quality descriptions, or <code>null</code> to use a
0373 * default <code>Locale</code>. Subclasses must set the value
0374 * manually.
0375 */
0376 protected Locale locale = null;
0377
0378 /**
0379 * Constructs an empty <code>ImageWriteParam</code>. It is up to
0380 * the subclass to set up the instance variables properly.
0381 */
0382 protected ImageWriteParam() {
0383 }
0384
0385 /**
0386 * Constructs an <code>ImageWriteParam</code> set to use a
0387 * given <code>Locale</code>.
0388 *
0389 * @param locale a <code>Locale</code> to be used to localize
0390 * compression type names and quality descriptions, or
0391 * <code>null</code>.
0392 */
0393 public ImageWriteParam(Locale locale) {
0394 this .locale = locale;
0395 }
0396
0397 // Return a deep copy of the array
0398 private static Dimension[] clonePreferredTileSizes(Dimension[] sizes) {
0399 if (sizes == null) {
0400 return null;
0401 }
0402 Dimension[] temp = new Dimension[sizes.length];
0403 for (int i = 0; i < sizes.length; i++) {
0404 temp[i] = new Dimension(sizes[i]);
0405 }
0406 return temp;
0407 }
0408
0409 /**
0410 * Returns the currently set <code>Locale</code>, or
0411 * <code>null</code> if only a default <code>Locale</code> is
0412 * supported.
0413 *
0414 * @return the current <code>Locale</code>, or <code>null</code>.
0415 */
0416 public Locale getLocale() {
0417 return locale;
0418 }
0419
0420 /**
0421 * Returns <code>true</code> if the writer can perform tiling
0422 * while writing. If this method returns <code>false</code>, then
0423 * <code>setTiling</code> will throw an
0424 * <code>UnsupportedOperationException</code>.
0425 *
0426 * @return <code>true</code> if the writer supports tiling.
0427 *
0428 * @see #canOffsetTiles()
0429 * @see #setTiling(int, int, int, int)
0430 */
0431 public boolean canWriteTiles() {
0432 return canWriteTiles;
0433 }
0434
0435 /**
0436 * Returns <code>true</code> if the writer can perform tiling with
0437 * non-zero grid offsets while writing. If this method returns
0438 * <code>false</code>, then <code>setTiling</code> will throw an
0439 * <code>UnsupportedOperationException</code> if the grid offset
0440 * arguments are not both zero. If <code>canWriteTiles</code>
0441 * returns <code>false</code>, this method will return
0442 * <code>false</code> as well.
0443 *
0444 * @return <code>true</code> if the writer supports non-zero tile
0445 * offsets.
0446 *
0447 * @see #canWriteTiles()
0448 * @see #setTiling(int, int, int, int)
0449 */
0450 public boolean canOffsetTiles() {
0451 return canOffsetTiles;
0452 }
0453
0454 /**
0455 * Determines whether the image will be tiled in the output
0456 * stream and, if it will, how the tiling parameters will be
0457 * determined. The modes are interpreted as follows:
0458 *
0459 * <ul>
0460 *
0461 * <li><code>MODE_DISABLED</code> - The image will not be tiled.
0462 * <code>setTiling</code> will throw an
0463 * <code>IllegalStateException</code>.
0464 *
0465 * <li><code>MODE_DEFAULT</code> - The image will be tiled using
0466 * default parameters. <code>setTiling</code> will throw an
0467 * <code>IllegalStateException</code>.
0468 *
0469 * <li><code>MODE_EXPLICIT</code> - The image will be tiled
0470 * according to parameters given in the {@link #setTiling
0471 * <code>setTiling</code>} method. Any previously set tiling
0472 * parameters are discarded.
0473 *
0474 * <li><code>MODE_COPY_FROM_METADATA</code> - The image will
0475 * conform to the metadata object passed in to a write.
0476 * <code>setTiling</code> will throw an
0477 * <code>IllegalStateException</code>.
0478 *
0479 * </ul>
0480 *
0481 * @param mode The mode to use for tiling.
0482 *
0483 * @exception UnsupportedOperationException if
0484 * <code>canWriteTiles</code> returns <code>false</code>.
0485 * @exception IllegalArgumentException if <code>mode</code> is not
0486 * one of the modes listed above.
0487 *
0488 * @see #setTiling
0489 * @see #getTilingMode
0490 */
0491 public void setTilingMode(int mode) {
0492 if (canWriteTiles() == false) {
0493 throw new UnsupportedOperationException(
0494 "Tiling not supported!");
0495 }
0496 if (mode < MODE_DISABLED || mode > MAX_MODE) {
0497 throw new IllegalArgumentException(
0498 "Illegal value for mode!");
0499 }
0500 this .tilingMode = mode;
0501 if (mode == MODE_EXPLICIT) {
0502 unsetTiling();
0503 }
0504 }
0505
0506 /**
0507 * Returns the current tiling mode, if tiling is supported.
0508 * Otherwise throws an <code>UnsupportedOperationException</code>.
0509 *
0510 * @return the current tiling mode.
0511 *
0512 * @exception UnsupportedOperationException if
0513 * <code>canWriteTiles</code> returns <code>false</code>.
0514 *
0515 * @see #setTilingMode
0516 */
0517 public int getTilingMode() {
0518 if (!canWriteTiles()) {
0519 throw new UnsupportedOperationException(
0520 "Tiling not supported");
0521 }
0522 return tilingMode;
0523 }
0524
0525 /**
0526 * Returns an array of <code>Dimension</code>s indicating the
0527 * legal size ranges for tiles as they will be encoded in the
0528 * output file or stream. The returned array is a copy.
0529 *
0530 * <p> The information is returned as a set of pairs; the first
0531 * element of a pair contains an (inclusive) minimum width and
0532 * height, and the second element contains an (inclusive) maximum
0533 * width and height. Together, each pair defines a valid range of
0534 * sizes. To specify a fixed size, use the same width and height
0535 * for both elements. To specify an arbitrary range, a value of
0536 * <code>null</code> is used in place of an actual array of
0537 * <code>Dimension</code>s.
0538 *
0539 * <p> If no array is specified on the constructor, but tiling is
0540 * allowed, then this method returns <code>null</code>.
0541 *
0542 * @exception UnsupportedOperationException if the plug-in does
0543 * not support tiling.
0544 *
0545 * @return an array of <code>Dimension</code>s with an even length
0546 * of at least two, or <code>null</code>.
0547 */
0548 public Dimension[] getPreferredTileSizes() {
0549 if (!canWriteTiles()) {
0550 throw new UnsupportedOperationException(
0551 "Tiling not supported");
0552 }
0553 return clonePreferredTileSizes(preferredTileSizes);
0554 }
0555
0556 /**
0557 * Specifies that the image should be tiled in the output stream.
0558 * The <code>tileWidth</code> and <code>tileHeight</code>
0559 * parameters specify the width and height of the tiles in the
0560 * file. If the tile width or height is greater than the width or
0561 * height of the image, the image is not tiled in that dimension.
0562 *
0563 * <p> If <code>canOffsetTiles</code> returns <code>false</code>,
0564 * then the <code>tileGridXOffset</code> and
0565 * <code>tileGridYOffset</code> parameters must be zero.
0566 *
0567 * @param tileWidth the width of each tile.
0568 * @param tileHeight the height of each tile.
0569 * @param tileGridXOffset the horizontal offset of the tile grid.
0570 * @param tileGridYOffset the vertical offset of the tile grid.
0571 *
0572 * @exception UnsupportedOperationException if the plug-in does not
0573 * support tiling.
0574 * @exception IllegalStateException if the tiling mode is not
0575 * <code>MODE_EXPLICIT</code>.
0576 * @exception UnsupportedOperationException if the plug-in does not
0577 * support grid offsets, and the grid offsets are not both zero.
0578 * @exception IllegalArgumentException if the tile size is not
0579 * within one of the allowable ranges returned by
0580 * <code>getPreferredTileSizes</code>.
0581 * @exception IllegalArgumentException if <code>tileWidth</code>
0582 * or <code>tileHeight</code> is less than or equal to 0.
0583 *
0584 * @see #canWriteTiles
0585 * @see #canOffsetTiles
0586 * @see #getTileWidth()
0587 * @see #getTileHeight()
0588 * @see #getTileGridXOffset()
0589 * @see #getTileGridYOffset()
0590 */
0591 public void setTiling(int tileWidth, int tileHeight,
0592 int tileGridXOffset, int tileGridYOffset) {
0593 if (!canWriteTiles()) {
0594 throw new UnsupportedOperationException(
0595 "Tiling not supported!");
0596 }
0597 if (getTilingMode() != MODE_EXPLICIT) {
0598 throw new IllegalStateException(
0599 "Tiling mode not MODE_EXPLICIT!");
0600 }
0601 if (tileWidth <= 0 || tileHeight <= 0) {
0602 throw new IllegalArgumentException(
0603 "tile dimensions are non-positive!");
0604 }
0605 boolean tilesOffset = (tileGridXOffset != 0)
0606 || (tileGridYOffset != 0);
0607 if (!canOffsetTiles() && tilesOffset) {
0608 throw new UnsupportedOperationException(
0609 "Can't offset tiles!");
0610 }
0611 if (preferredTileSizes != null) {
0612 boolean ok = true;
0613 for (int i = 0; i < preferredTileSizes.length; i += 2) {
0614 Dimension min = preferredTileSizes[i];
0615 Dimension max = preferredTileSizes[i + 1];
0616 if ((tileWidth < min.width) || (tileWidth > max.width)
0617 || (tileHeight < min.height)
0618 || (tileHeight > max.height)) {
0619 ok = false;
0620 break;
0621 }
0622 }
0623 if (!ok) {
0624 throw new IllegalArgumentException("Illegal tile size!");
0625 }
0626 }
0627
0628 this .tilingSet = true;
0629 this .tileWidth = tileWidth;
0630 this .tileHeight = tileHeight;
0631 this .tileGridXOffset = tileGridXOffset;
0632 this .tileGridYOffset = tileGridYOffset;
0633 }
0634
0635 /**
0636 * Removes any previous tile grid parameters specified by calls to
0637 * <code>setTiling</code>.
0638 *
0639 * <p> The default implementation sets the instance variables
0640 * <code>tileWidth</code>, <code>tileHeight</code>,
0641 * <code>tileGridXOffset</code>, and
0642 * <code>tileGridYOffset</code> to <code>0</code>.
0643 *
0644 * @exception UnsupportedOperationException if the plug-in does not
0645 * support tiling.
0646 * @exception IllegalStateException if the tiling mode is not
0647 * <code>MODE_EXPLICIT</code>.
0648 *
0649 * @see #setTiling(int, int, int, int)
0650 */
0651 public void unsetTiling() {
0652 if (!canWriteTiles()) {
0653 throw new UnsupportedOperationException(
0654 "Tiling not supported!");
0655 }
0656 if (getTilingMode() != MODE_EXPLICIT) {
0657 throw new IllegalStateException(
0658 "Tiling mode not MODE_EXPLICIT!");
0659 }
0660 this .tilingSet = false;
0661 this .tileWidth = 0;
0662 this .tileHeight = 0;
0663 this .tileGridXOffset = 0;
0664 this .tileGridYOffset = 0;
0665 }
0666
0667 /**
0668 * Returns the width of each tile in an image as it will be
0669 * written to the output stream. If tiling parameters have not
0670 * been set, an <code>IllegalStateException</code> is thrown.
0671 *
0672 * @return the tile width to be used for encoding.
0673 *
0674 * @exception UnsupportedOperationException if the plug-in does not
0675 * support tiling.
0676 * @exception IllegalStateException if the tiling mode is not
0677 * <code>MODE_EXPLICIT</code>.
0678 * @exception IllegalStateException if the tiling parameters have
0679 * not been set.
0680 *
0681 * @see #setTiling(int, int, int, int)
0682 * @see #getTileHeight()
0683 */
0684 public int getTileWidth() {
0685 if (!canWriteTiles()) {
0686 throw new UnsupportedOperationException(
0687 "Tiling not supported!");
0688 }
0689 if (getTilingMode() != MODE_EXPLICIT) {
0690 throw new IllegalStateException(
0691 "Tiling mode not MODE_EXPLICIT!");
0692 }
0693 if (!tilingSet) {
0694 throw new IllegalStateException(
0695 "Tiling parameters not set!");
0696 }
0697 return tileWidth;
0698 }
0699
0700 /**
0701 * Returns the height of each tile in an image as it will be written to
0702 * the output stream. If tiling parameters have not
0703 * been set, an <code>IllegalStateException</code> is thrown.
0704 *
0705 * @return the tile height to be used for encoding.
0706 *
0707 * @exception UnsupportedOperationException if the plug-in does not
0708 * support tiling.
0709 * @exception IllegalStateException if the tiling mode is not
0710 * <code>MODE_EXPLICIT</code>.
0711 * @exception IllegalStateException if the tiling parameters have
0712 * not been set.
0713 *
0714 * @see #setTiling(int, int, int, int)
0715 * @see #getTileWidth()
0716 */
0717 public int getTileHeight() {
0718 if (!canWriteTiles()) {
0719 throw new UnsupportedOperationException(
0720 "Tiling not supported!");
0721 }
0722 if (getTilingMode() != MODE_EXPLICIT) {
0723 throw new IllegalStateException(
0724 "Tiling mode not MODE_EXPLICIT!");
0725 }
0726 if (!tilingSet) {
0727 throw new IllegalStateException(
0728 "Tiling parameters not set!");
0729 }
0730 return tileHeight;
0731 }
0732
0733 /**
0734 * Returns the horizontal tile grid offset of an image as it will
0735 * be written to the output stream. If tiling parameters have not
0736 * been set, an <code>IllegalStateException</code> is thrown.
0737 *
0738 * @return the tile grid X offset to be used for encoding.
0739 *
0740 * @exception UnsupportedOperationException if the plug-in does not
0741 * support tiling.
0742 * @exception IllegalStateException if the tiling mode is not
0743 * <code>MODE_EXPLICIT</code>.
0744 * @exception IllegalStateException if the tiling parameters have
0745 * not been set.
0746 *
0747 * @see #setTiling(int, int, int, int)
0748 * @see #getTileGridYOffset()
0749 */
0750 public int getTileGridXOffset() {
0751 if (!canWriteTiles()) {
0752 throw new UnsupportedOperationException(
0753 "Tiling not supported!");
0754 }
0755 if (getTilingMode() != MODE_EXPLICIT) {
0756 throw new IllegalStateException(
0757 "Tiling mode not MODE_EXPLICIT!");
0758 }
0759 if (!tilingSet) {
0760 throw new IllegalStateException(
0761 "Tiling parameters not set!");
0762 }
0763 return tileGridXOffset;
0764 }
0765
0766 /**
0767 * Returns the vertical tile grid offset of an image as it will
0768 * be written to the output stream. If tiling parameters have not
0769 * been set, an <code>IllegalStateException</code> is thrown.
0770 *
0771 * @return the tile grid Y offset to be used for encoding.
0772 *
0773 * @exception UnsupportedOperationException if the plug-in does not
0774 * support tiling.
0775 * @exception IllegalStateException if the tiling mode is not
0776 * <code>MODE_EXPLICIT</code>.
0777 * @exception IllegalStateException if the tiling parameters have
0778 * not been set.
0779 *
0780 * @see #setTiling(int, int, int, int)
0781 * @see #getTileGridXOffset()
0782 */
0783 public int getTileGridYOffset() {
0784 if (!canWriteTiles()) {
0785 throw new UnsupportedOperationException(
0786 "Tiling not supported!");
0787 }
0788 if (getTilingMode() != MODE_EXPLICIT) {
0789 throw new IllegalStateException(
0790 "Tiling mode not MODE_EXPLICIT!");
0791 }
0792 if (!tilingSet) {
0793 throw new IllegalStateException(
0794 "Tiling parameters not set!");
0795 }
0796 return tileGridYOffset;
0797 }
0798
0799 /**
0800 * Returns <code>true</code> if the writer can write out images
0801 * as a series of passes of progressively increasing quality.
0802 *
0803 * @return <code>true</code> if the writer supports progressive
0804 * encoding.
0805 *
0806 * @see #setProgressiveMode
0807 * @see #getProgressiveMode
0808 */
0809 public boolean canWriteProgressive() {
0810 return canWriteProgressive;
0811 }
0812
0813 /**
0814 * Specifies that the writer is to write the image out in a
0815 * progressive mode such that the stream will contain a series of
0816 * scans of increasing quality. If progressive encoding is not
0817 * supported, an <code>UnsupportedOperationException</code> will
0818 * be thrown.
0819 *
0820 * <p> The mode argument determines how
0821 * the progression parameters are chosen, and must be either
0822 * <code>MODE_DISABLED</code>,
0823 * <code>MODE_COPY_FROM_METADATA</code>, or
0824 * <code>MODE_DEFAULT</code>. Otherwise an
0825 * <code>IllegalArgumentException</code> is thrown.
0826 *
0827 * <p> The modes are interpreted as follows:
0828 *
0829 * <ul>
0830 * <li><code>MODE_DISABLED</code> - No progression. Use this to
0831 * turn off progession.
0832 *
0833 * <li><code>MODE_COPY_FROM_METADATA</code> - The output image
0834 * will use whatever progression parameters are found in the
0835 * metadata objects passed into the writer.
0836 *
0837 * <li><code>MODE_DEFAULT</code> - The image will be written
0838 * progressively, with parameters chosen by the writer.
0839 * </ul>
0840 *
0841 * <p> The default is <code>MODE_COPY_FROM_METADATA</code>.
0842 *
0843 * @param mode The mode for setting progression in the output
0844 * stream.
0845 *
0846 * @exception UnsupportedOperationException if the writer does not
0847 * support progressive encoding.
0848 * @exception IllegalArgumentException if <code>mode</code> is not
0849 * one of the modes listed above.
0850 *
0851 * @see #getProgressiveMode
0852 */
0853 public void setProgressiveMode(int mode) {
0854 if (!canWriteProgressive()) {
0855 throw new UnsupportedOperationException(
0856 "Progressive output not supported");
0857 }
0858 if (mode < MODE_DISABLED || mode > MAX_MODE) {
0859 throw new IllegalArgumentException(
0860 "Illegal value for mode!");
0861 }
0862 if (mode == MODE_EXPLICIT) {
0863 throw new IllegalArgumentException(
0864 "MODE_EXPLICIT not supported for progressive output");
0865 }
0866 this .progressiveMode = mode;
0867 }
0868
0869 /**
0870 * Returns the current mode for writing the stream in a
0871 * progressive manner.
0872 *
0873 * @return the current mode for progressive encoding.
0874 *
0875 * @exception UnsupportedOperationException if the writer does not
0876 * support progressive encoding.
0877 *
0878 * @see #setProgressiveMode
0879 */
0880 public int getProgressiveMode() {
0881 if (!canWriteProgressive()) {
0882 throw new UnsupportedOperationException(
0883 "Progressive output not supported");
0884 }
0885 return progressiveMode;
0886 }
0887
0888 /**
0889 * Returns <code>true</code> if this writer supports compression.
0890 *
0891 * @return <code>true</code> if the writer supports compression.
0892 */
0893 public boolean canWriteCompressed() {
0894 return canWriteCompressed;
0895 }
0896
0897 /**
0898 * Specifies whether compression is to be performed, and if so how
0899 * compression parameters are to be determined. The <code>mode</code>
0900 * argument must be one of the four modes, interpreted as follows:
0901 *
0902 * <ul>
0903 * <li><code>MODE_DISABLED</code> - If the mode is set to
0904 * <code>MODE_DISABLED</code>, methods that query or modify the
0905 * compression type or parameters will throw an
0906 * <code>IllegalStateException</code> (if compression is
0907 * normally supported by the plug-in). Some writers, such as JPEG,
0908 * do not normally offer uncompressed output. In this case, attempting
0909 * to set the mode to <code>MODE_DISABLED</code> will throw an
0910 * <code>UnsupportedOperationException</code> and the mode will not be
0911 * changed.
0912 *
0913 * <li><code>MODE_EXPLICIT</code> - Compress using the
0914 * compression type and quality settings specified in this
0915 * <code>ImageWriteParam</code>. Any previously set compression
0916 * parameters are discarded.
0917 *
0918 * <li><code>MODE_COPY_FROM_METADATA</code> - Use whatever
0919 * compression parameters are specified in metadata objects
0920 * passed in to the writer.
0921 *
0922 * <li><code>MODE_DEFAULT</code> - Use default compression
0923 * parameters.
0924 * </ul>
0925 *
0926 * <p> The default is <code>MODE_COPY_FROM_METADATA</code>.
0927 *
0928 * @param mode The mode for setting compression in the output
0929 * stream.
0930 *
0931 * @exception UnsupportedOperationException if the writer does not
0932 * support compression, or does not support the requested mode.
0933 * @exception IllegalArgumentException if <code>mode</code> is not
0934 * one of the modes listed above.
0935 *
0936 * @see #getCompressionMode
0937 */
0938 public void setCompressionMode(int mode) {
0939 if (!canWriteCompressed()) {
0940 throw new UnsupportedOperationException(
0941 "Compression not supported.");
0942 }
0943 if (mode < MODE_DISABLED || mode > MAX_MODE) {
0944 throw new IllegalArgumentException(
0945 "Illegal value for mode!");
0946 }
0947 this .compressionMode = mode;
0948 if (mode == MODE_EXPLICIT) {
0949 unsetCompression();
0950 }
0951 }
0952
0953 /**
0954 * Returns the current compression mode, if compression is
0955 * supported.
0956 *
0957 * @return the current compression mode.
0958 *
0959 * @exception UnsupportedOperationException if the writer does not
0960 * support compression.
0961 *
0962 * @see #setCompressionMode
0963 */
0964 public int getCompressionMode() {
0965 if (!canWriteCompressed()) {
0966 throw new UnsupportedOperationException(
0967 "Compression not supported.");
0968 }
0969 return compressionMode;
0970 }
0971
0972 /**
0973 * Returns a list of available compression types, as an array or
0974 * <code>String</code>s, or <code>null</code> if a compression
0975 * type may not be chosen using these interfaces. The array
0976 * returned is a copy.
0977 *
0978 * <p> If the writer only offers a single, mandatory form of
0979 * compression, it is not necessary to provide any named
0980 * compression types. Named compression types should only be
0981 * used where the user is able to make a meaningful choice
0982 * between different schemes.
0983 *
0984 * <p> The default implementation checks if compression is
0985 * supported and throws an
0986 * <code>UnsupportedOperationException</code> if not. Otherwise,
0987 * it returns a clone of the <code>compressionTypes</code>
0988 * instance variable if it is non-<code>null</code>, or else
0989 * returns <code>null</code>.
0990 *
0991 * @return an array of <code>String</code>s containing the
0992 * (non-localized) names of available compression types, or
0993 * <code>null</code>.
0994 *
0995 * @exception UnsupportedOperationException if the writer does not
0996 * support compression.
0997 */
0998 public String[] getCompressionTypes() {
0999 if (!canWriteCompressed()) {
1000 throw new UnsupportedOperationException(
1001 "Compression not supported");
1002 }
1003 if (compressionTypes == null) {
1004 return null;
1005 }
1006 return (String[]) compressionTypes.clone();
1007 }
1008
1009 /**
1010 * Sets the compression type to one of the values indicated by
1011 * <code>getCompressionTypes</code>. If a value of
1012 * <code>null</code> is passed in, any previous setting is
1013 * removed.
1014 *
1015 * <p> The default implementation checks whether compression is
1016 * supported and the compression mode is
1017 * <code>MODE_EXPLICIT</code>. If so, it calls
1018 * <code>getCompressionTypes</code> and checks if
1019 * <code>compressionType</code> is one of the legal values. If it
1020 * is, the <code>compressionType</code> instance variable is set.
1021 * If <code>compressionType</code> is <code>null</code>, the
1022 * instance variable is set without performing any checking.
1023 *
1024 * @param compressionType one of the <code>String</code>s returned
1025 * by <code>getCompressionTypes</code>, or <code>null</code> to
1026 * remove any previous setting.
1027 *
1028 * @exception UnsupportedOperationException if the writer does not
1029 * support compression.
1030 * @exception IllegalStateException if the compression mode is not
1031 * <code>MODE_EXPLICIT</code>.
1032 * @exception UnsupportedOperationException if there are no
1033 * settable compression types.
1034 * @exception IllegalArgumentException if
1035 * <code>compressionType</code> is non-<code>null</code> but is not
1036 * one of the values returned by <code>getCompressionTypes</code>.
1037 *
1038 * @see #getCompressionTypes
1039 * @see #getCompressionType
1040 * @see #unsetCompression
1041 */
1042 public void setCompressionType(String compressionType) {
1043 if (!canWriteCompressed()) {
1044 throw new UnsupportedOperationException(
1045 "Compression not supported");
1046 }
1047 if (getCompressionMode() != MODE_EXPLICIT) {
1048 throw new IllegalStateException(
1049 "Compression mode not MODE_EXPLICIT!");
1050 }
1051 String[] legalTypes = getCompressionTypes();
1052 if (legalTypes == null) {
1053 throw new UnsupportedOperationException(
1054 "No settable compression types");
1055 }
1056 if (compressionType != null) {
1057 boolean found = false;
1058 if (legalTypes != null) {
1059 for (int i = 0; i < legalTypes.length; i++) {
1060 if (compressionType.equals(legalTypes[i])) {
1061 found = true;
1062 break;
1063 }
1064 }
1065 }
1066 if (!found) {
1067 throw new IllegalArgumentException(
1068 "Unknown compression type!");
1069 }
1070 }
1071 this .compressionType = compressionType;
1072 }
1073
1074 /**
1075 * Returns the currently set compression type, or
1076 * <code>null</code> if none has been set. The type is returned
1077 * as a <code>String</code> from among those returned by
1078 * <code>getCompressionTypes</code>.
1079 * If no compression type has been set, <code>null</code> is
1080 * returned.
1081 *
1082 * <p> The default implementation checks whether compression is
1083 * supported and the compression mode is
1084 * <code>MODE_EXPLICIT</code>. If so, it returns the value of the
1085 * <code>compressionType</code> instance variable.
1086 *
1087 * @return the current compression type as a <code>String</code>,
1088 * or <code>null</code> if no type is set.
1089 *
1090 * @exception UnsupportedOperationException if the writer does not
1091 * support compression.
1092 * @exception IllegalStateException if the compression mode is not
1093 * <code>MODE_EXPLICIT</code>.
1094 *
1095 * @see #setCompressionType
1096 */
1097 public String getCompressionType() {
1098 if (!canWriteCompressed()) {
1099 throw new UnsupportedOperationException(
1100 "Compression not supported.");
1101 }
1102 if (getCompressionMode() != MODE_EXPLICIT) {
1103 throw new IllegalStateException(
1104 "Compression mode not MODE_EXPLICIT!");
1105 }
1106 return compressionType;
1107 }
1108
1109 /**
1110 * Removes any previous compression type and quality settings.
1111 *
1112 * <p> The default implementation sets the instance variable
1113 * <code>compressionType</code> to <code>null</code>, and the
1114 * instance variable <code>compressionQuality</code> to
1115 * <code>1.0F</code>.
1116 *
1117 * @exception UnsupportedOperationException if the plug-in does not
1118 * support compression.
1119 * @exception IllegalStateException if the compression mode is not
1120 * <code>MODE_EXPLICIT</code>.
1121 *
1122 * @see #setCompressionType
1123 * @see #setCompressionQuality
1124 */
1125 public void unsetCompression() {
1126 if (!canWriteCompressed()) {
1127 throw new UnsupportedOperationException(
1128 "Compression not supported");
1129 }
1130 if (getCompressionMode() != MODE_EXPLICIT) {
1131 throw new IllegalStateException(
1132 "Compression mode not MODE_EXPLICIT!");
1133 }
1134 this .compressionType = null;
1135 this .compressionQuality = 1.0F;
1136 }
1137
1138 /**
1139 * Returns a localized version of the name of the current
1140 * compression type, using the <code>Locale</code> returned by
1141 * <code>getLocale</code>.
1142 *
1143 * <p> The default implementation checks whether compression is
1144 * supported and the compression mode is
1145 * <code>MODE_EXPLICIT</code>. If so, if
1146 * <code>compressionType</code> is <code>non-null</code> the value
1147 * of <code>getCompressionType</code> is returned as a
1148 * convenience.
1149 *
1150 * @return a <code>String</code> containing a localized version of
1151 * the name of the current compression type.
1152 *
1153 * @exception UnsupportedOperationException if the writer does not
1154 * support compression.
1155 * @exception IllegalStateException if the compression mode is not
1156 * <code>MODE_EXPLICIT</code>.
1157 * @exception IllegalStateException if no compression type is set.
1158 */
1159 public String getLocalizedCompressionTypeName() {
1160 if (!canWriteCompressed()) {
1161 throw new UnsupportedOperationException(
1162 "Compression not supported.");
1163 }
1164 if (getCompressionMode() != MODE_EXPLICIT) {
1165 throw new IllegalStateException(
1166 "Compression mode not MODE_EXPLICIT!");
1167 }
1168 if (getCompressionType() == null) {
1169 throw new IllegalStateException("No compression type set!");
1170 }
1171 return getCompressionType();
1172 }
1173
1174 /**
1175 * Returns <code>true</code> if the current compression type
1176 * provides lossless compression. If a plug-in provides only
1177 * one mandatory compression type, then this method may be
1178 * called without calling <code>setCompressionType</code> first.
1179 *
1180 * <p> If there are multiple compression types but none has
1181 * been set, an <code>IllegalStateException</code> is thrown.
1182 *
1183 * <p> The default implementation checks whether compression is
1184 * supported and the compression mode is
1185 * <code>MODE_EXPLICIT</code>. If so, if
1186 * <code>getCompressionTypes()</code> is <code>null</code> or
1187 * <code>getCompressionType()</code> is non-<code>null</code>
1188 * <code>true</code> is returned as a convenience.
1189 *
1190 * @return <code>true</code> if the current compression type is
1191 * lossless.
1192 *
1193 * @exception UnsupportedOperationException if the writer does not
1194 * support compression.
1195 * @exception IllegalStateException if the compression mode is not
1196 * <code>MODE_EXPLICIT</code>.
1197 * @exception IllegalStateException if the set of legal
1198 * compression types is non-<code>null</code> and the current
1199 * compression type is <code>null</code>.
1200 */
1201 public boolean isCompressionLossless() {
1202 if (!canWriteCompressed()) {
1203 throw new UnsupportedOperationException(
1204 "Compression not supported");
1205 }
1206 if (getCompressionMode() != MODE_EXPLICIT) {
1207 throw new IllegalStateException(
1208 "Compression mode not MODE_EXPLICIT!");
1209 }
1210 if ((getCompressionTypes() != null)
1211 && (getCompressionType() == null)) {
1212 throw new IllegalStateException("No compression type set!");
1213 }
1214 return true;
1215 }
1216
1217 /**
1218 * Sets the compression quality to a value between <code>0</code>
1219 * and <code>1</code>. Only a single compression quality setting
1220 * is supported by default; writers can provide extended versions
1221 * of <code>ImageWriteParam</code> that offer more control. For
1222 * lossy compression schemes, the compression quality should
1223 * control the tradeoff between file size and image quality (for
1224 * example, by choosing quantization tables when writing JPEG
1225 * images). For lossless schemes, the compression quality may be
1226 * used to control the tradeoff between file size and time taken
1227 * to perform the compression (for example, by optimizing row
1228 * filters and setting the ZLIB compression level when writing
1229 * PNG images).
1230 *
1231 * <p> A compression quality setting of 0.0 is most generically
1232 * interpreted as "high compression is important," while a setting of
1233 * 1.0 is most generically interpreted as "high image quality is
1234 * important."
1235 *
1236 * <p> If there are multiple compression types but none has been
1237 * set, an <code>IllegalStateException</code> is thrown.
1238 *
1239 * <p> The default implementation checks that compression is
1240 * supported, and that the compression mode is
1241 * <code>MODE_EXPLICIT</code>. If so, if
1242 * <code>getCompressionTypes()</code> returns <code>null</code> or
1243 * <code>compressionType</code> is non-<code>null</code> it sets
1244 * the <code>compressionQuality</code> instance variable.
1245 *
1246 * @param quality a <code>float</code> between <code>0</code>and
1247 * <code>1</code> indicating the desired quality level.
1248 *
1249 * @exception UnsupportedOperationException if the writer does not
1250 * support compression.
1251 * @exception IllegalStateException if the compression mode is not
1252 * <code>MODE_EXPLICIT</code>.
1253 * @exception IllegalStateException if the set of legal
1254 * compression types is non-<code>null</code> and the current
1255 * compression type is <code>null</code>.
1256 * @exception IllegalArgumentException if <code>quality</code> is
1257 * not between <code>0</code>and <code>1</code>, inclusive.
1258 *
1259 * @see #getCompressionQuality
1260 */
1261 public void setCompressionQuality(float quality) {
1262 if (!canWriteCompressed()) {
1263 throw new UnsupportedOperationException(
1264 "Compression not supported");
1265 }
1266 if (getCompressionMode() != MODE_EXPLICIT) {
1267 throw new IllegalStateException(
1268 "Compression mode not MODE_EXPLICIT!");
1269 }
1270 if (getCompressionTypes() != null
1271 && getCompressionType() == null) {
1272 throw new IllegalStateException("No compression type set!");
1273 }
1274 if (quality < 0.0F || quality > 1.0F) {
1275 throw new IllegalArgumentException("Quality out-of-bounds!");
1276 }
1277 this .compressionQuality = quality;
1278 }
1279
1280 /**
1281 * Returns the current compression quality setting.
1282 *
1283 * <p> If there are multiple compression types but none has been
1284 * set, an <code>IllegalStateException</code> is thrown.
1285 *
1286 * <p> The default implementation checks that compression is
1287 * supported and that the compression mode is
1288 * <code>MODE_EXPLICIT</code>. If so, if
1289 * <code>getCompressionTypes()</code> is <code>null</code> or
1290 * <code>getCompressionType()</code> is non-<code>null</code>, it
1291 * returns the value of the <code>compressionQuality</code>
1292 * instance variable.
1293 *
1294 * @return the current compression quality setting.
1295 *
1296 * @exception UnsupportedOperationException if the writer does not
1297 * support compression.
1298 * @exception IllegalStateException if the compression mode is not
1299 * <code>MODE_EXPLICIT</code>.
1300 * @exception IllegalStateException if the set of legal
1301 * compression types is non-<code>null</code> and the current
1302 * compression type is <code>null</code>.
1303 *
1304 * @see #setCompressionQuality
1305 */
1306 public float getCompressionQuality() {
1307 if (!canWriteCompressed()) {
1308 throw new UnsupportedOperationException(
1309 "Compression not supported.");
1310 }
1311 if (getCompressionMode() != MODE_EXPLICIT) {
1312 throw new IllegalStateException(
1313 "Compression mode not MODE_EXPLICIT!");
1314 }
1315 if ((getCompressionTypes() != null)
1316 && (getCompressionType() == null)) {
1317 throw new IllegalStateException("No compression type set!");
1318 }
1319 return compressionQuality;
1320 }
1321
1322 /**
1323 * Returns a <code>float</code> indicating an estimate of the
1324 * number of bits of output data for each bit of input image data
1325 * at the given quality level. The value will typically lie
1326 * between <code>0</code> and <code>1</code>, with smaller values
1327 * indicating more compression. A special value of
1328 * <code>-1.0F</code> is used to indicate that no estimate is
1329 * available.
1330 *
1331 * <p> If there are multiple compression types but none has been set,
1332 * an <code>IllegalStateException</code> is thrown.
1333 *
1334 * <p> The default implementation checks that compression is
1335 * supported and the compression mode is
1336 * <code>MODE_EXPLICIT</code>. If so, if
1337 * <code>getCompressionTypes()</code> is <code>null</code> or
1338 * <code>getCompressionType()</code> is non-<code>null</code>, and
1339 * <code>quality</code> is within bounds, it returns
1340 * <code>-1.0</code>.
1341 *
1342 * @param quality the quality setting whose bit rate is to be
1343 * queried.
1344 *
1345 * @return an estimate of the compressed bit rate, or
1346 * <code>-1.0F</code> if no estimate is available.
1347 *
1348 * @exception UnsupportedOperationException if the writer does not
1349 * support compression.
1350 * @exception IllegalStateException if the compression mode is not
1351 * <code>MODE_EXPLICIT</code>.
1352 * @exception IllegalStateException if the set of legal
1353 * compression types is non-<code>null</code> and the current
1354 * compression type is <code>null</code>.
1355 * @exception IllegalArgumentException if <code>quality</code> is
1356 * not between <code>0</code>and <code>1</code>, inclusive.
1357 */
1358 public float getBitRate(float quality) {
1359 if (!canWriteCompressed()) {
1360 throw new UnsupportedOperationException(
1361 "Compression not supported.");
1362 }
1363 if (getCompressionMode() != MODE_EXPLICIT) {
1364 throw new IllegalStateException(
1365 "Compression mode not MODE_EXPLICIT!");
1366 }
1367 if ((getCompressionTypes() != null)
1368 && (getCompressionType() == null)) {
1369 throw new IllegalStateException("No compression type set!");
1370 }
1371 if (quality < 0.0F || quality > 1.0F) {
1372 throw new IllegalArgumentException("Quality out-of-bounds!");
1373 }
1374 return -1.0F;
1375 }
1376
1377 /**
1378 * Returns an array of <code>String</code>s that may be used along
1379 * with <code>getCompressionQualityValues</code> as part of a user
1380 * interface for setting or displaying the compression quality
1381 * level. The <code>String</code> with index <code>i</code>
1382 * provides a description of the range of quality levels between
1383 * <code>getCompressionQualityValues[i]</code> and
1384 * <code>getCompressionQualityValues[i + 1]</code>. Note that the
1385 * length of the array returned from
1386 * <code>getCompressionQualityValues</code> will always be one
1387 * greater than that returned from
1388 * <code>getCompressionQualityDescriptions</code>.
1389 *
1390 * <p> As an example, the strings "Good", "Better", and "Best"
1391 * could be associated with the ranges <code>[0, .33)</code>,
1392 * <code>[.33, .66)</code>, and <code>[.66, 1.0]</code>. In this
1393 * case, <code>getCompressionQualityDescriptions</code> would
1394 * return <code>{ "Good", "Better", "Best" }</code> and
1395 * <code>getCompressionQualityValues</code> would return
1396 * <code>{ 0.0F, .33F, .66F, 1.0F }</code>.
1397 *
1398 * <p> If no descriptions are available, <code>null</code> is
1399 * returned. If <code>null</code> is returned from
1400 * <code>getCompressionQualityValues</code>, this method must also
1401 * return <code>null</code>.
1402 *
1403 * <p> The descriptions should be localized for the
1404 * <code>Locale</code> returned by <code>getLocale</code>, if it
1405 * is non-<code>null</code>.
1406 *
1407 * <p> If there are multiple compression types but none has been set,
1408 * an <code>IllegalStateException</code> is thrown.
1409 *
1410 * <p> The default implementation checks that compression is
1411 * supported and that the compression mode is
1412 * <code>MODE_EXPLICIT</code>. If so, if
1413 * <code>getCompressionTypes()</code> is <code>null</code> or
1414 * <code>getCompressionType()</code> is non-<code>null</code>, it
1415 * returns <code>null</code>.
1416 *
1417 * @return an array of <code>String</code>s containing localized
1418 * descriptions of the compression quality levels.
1419 *
1420 * @exception UnsupportedOperationException if the writer does not
1421 * support compression.
1422 * @exception IllegalStateException if the compression mode is not
1423 * <code>MODE_EXPLICIT</code>.
1424 * @exception IllegalStateException if the set of legal
1425 * compression types is non-<code>null</code> and the current
1426 * compression type is <code>null</code>.
1427 *
1428 * @see #getCompressionQualityValues
1429 */
1430 public String[] getCompressionQualityDescriptions() {
1431 if (!canWriteCompressed()) {
1432 throw new UnsupportedOperationException(
1433 "Compression not supported.");
1434 }
1435 if (getCompressionMode() != MODE_EXPLICIT) {
1436 throw new IllegalStateException(
1437 "Compression mode not MODE_EXPLICIT!");
1438 }
1439 if ((getCompressionTypes() != null)
1440 && (getCompressionType() == null)) {
1441 throw new IllegalStateException("No compression type set!");
1442 }
1443 return null;
1444 }
1445
1446 /**
1447 * Returns an array of <code>float</code>s that may be used along
1448 * with <code>getCompressionQualityDescriptions</code> as part of a user
1449 * interface for setting or displaying the compression quality
1450 * level. See {@link #getCompressionQualityDescriptions
1451 * <code>getCompressionQualityDescriptions</code>} for more information.
1452 *
1453 * <p> If no descriptions are available, <code>null</code> is
1454 * returned. If <code>null</code> is returned from
1455 * <code>getCompressionQualityDescriptions</code>, this method
1456 * must also return <code>null</code>.
1457 *
1458 * <p> If there are multiple compression types but none has been set,
1459 * an <code>IllegalStateException</code> is thrown.
1460 *
1461 * <p> The default implementation checks that compression is
1462 * supported and that the compression mode is
1463 * <code>MODE_EXPLICIT</code>. If so, if
1464 * <code>getCompressionTypes()</code> is <code>null</code> or
1465 * <code>getCompressionType()</code> is non-<code>null</code>, it
1466 * returns <code>null</code>.
1467 *
1468 * @return an array of <code>float</code>s indicating the
1469 * boundaries between the compression quality levels as described
1470 * by the <code>String</code>s from
1471 * <code>getCompressionQualityDescriptions</code>.
1472 *
1473 * @exception UnsupportedOperationException if the writer does not
1474 * support compression.
1475 * @exception IllegalStateException if the compression mode is not
1476 * <code>MODE_EXPLICIT</code>.
1477 * @exception IllegalStateException if the set of legal
1478 * compression types is non-<code>null</code> and the current
1479 * compression type is <code>null</code>.
1480 *
1481 * @see #getCompressionQualityDescriptions
1482 */
1483 public float[] getCompressionQualityValues() {
1484 if (!canWriteCompressed()) {
1485 throw new UnsupportedOperationException(
1486 "Compression not supported.");
1487 }
1488 if (getCompressionMode() != MODE_EXPLICIT) {
1489 throw new IllegalStateException(
1490 "Compression mode not MODE_EXPLICIT!");
1491 }
1492 if ((getCompressionTypes() != null)
1493 && (getCompressionType() == null)) {
1494 throw new IllegalStateException("No compression type set!");
1495 }
1496 return null;
1497 }
1498 }
|