1 /* 2 * Copyright (c) 2000, 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.util.Locale; 30 31 /** 32 * A class describing how a stream is to be encoded. Instances of 33 * this class or its subclasses are used to supply prescriptive 34 * "how-to" information to instances of <code>ImageWriter</code>. 35 * 36 * <p> A plug-in for a specific image format may define a subclass of 37 * this class, and return objects of that class from the 38 * <code>getDefaultWriteParam</code> method of its 39 * <code>ImageWriter</code> implementation. For example, the built-in 40 * JPEG writer plug-in will return instances of 41 * <code>javax.imageio.plugins.jpeg.JPEGImageWriteParam</code>. 42 * 43 * <p> The region of the image to be written is determined by first 44 * intersecting the actual bounds of the image with the rectangle 45 * specified by <code>IIOParam.setSourceRegion</code>, if any. If the 46 * resulting rectangle has a width or height of zero, the writer will 47 * throw an <code>IIOException</code>. If the intersection is 48 * non-empty, writing will commence with the first subsampled pixel 49 * and include additional pixels within the intersected bounds 50 * according to the horizontal and vertical subsampling factors 51 * specified by {@link IIOParam#setSourceSubsampling 52 * IIOParam.setSourceSubsampling}. 53 * 54 * <p> Individual features such as tiling, progressive encoding, and 55 * compression may be set in one of four modes. 56 * <code>MODE_DISABLED</code> disables the features; 57 * <code>MODE_DEFAULT</code> enables the feature with 58 * writer-controlled parameter values; <code>MODE_EXPLICIT</code> 59 * enables the feature and allows the use of a <code>set</code> method 60 * to provide additional parameters; and 61 * <code>MODE_COPY_FROM_METADATA</code> copies relevant parameter 62 * values from the stream and image metadata objects passed to the 63 * writer. The default for all features is 64 * <code>MODE_COPY_FROM_METADATA</code>. Non-standard features 65 * supplied in subclasses are encouraged, but not required to use a 66 * similar scheme. 67 * 68 * <p> Plug-in writers may extend the functionality of 69 * <code>ImageWriteParam</code> by providing a subclass that implements 70 * additional, plug-in specific interfaces. It is up to the plug-in 71 * to document what interfaces are available and how they are to be 72 * used. Writers will silently ignore any extended features of an 73 * <code>ImageWriteParam</code> subclass of which they are not aware. 74 * Also, they may ignore any optional features that they normally 75 * disable when creating their own <code>ImageWriteParam</code> 76 * instances via <code>getDefaultWriteParam</code>. 77 * 78 * <p> Note that unless a query method exists for a capability, it must 79 * be supported by all <code>ImageWriter</code> implementations 80 * (<i>e.g.</i> progressive encoding is optional, but subsampling must be 81 * supported). 82 * 83 * 84 * @see ImageReadParam 85 */ 86 public class ImageWriteParam extends IIOParam { 87 88 /** 89 * A constant value that may be passed into methods such as 90 * <code>setTilingMode</code>, <code>setProgressiveMode</code>, 91 * and <code>setCompressionMode</code> to disable a feature for 92 * future writes. That is, when this mode is set the stream will 93 * <b>not</b> be tiled, progressive, or compressed, and the 94 * relevant accessor methods will throw an 95 * <code>IllegalStateException</code>. 96 * 97 * @see #MODE_EXPLICIT 98 * @see #MODE_COPY_FROM_METADATA 99 * @see #MODE_DEFAULT 100 * @see #setProgressiveMode 101 * @see #getProgressiveMode 102 * @see #setTilingMode 103 * @see #getTilingMode 104 * @see #setCompressionMode 105 * @see #getCompressionMode 106 */ 107 public static final int MODE_DISABLED = 0; 108 109 /** 110 * A constant value that may be passed into methods such as 111 * <code>setTilingMode</code>, 112 * <code>setProgressiveMode</code>, and 113 * <code>setCompressionMode</code> to enable that feature for 114 * future writes. That is, when this mode is enabled the stream 115 * will be tiled, progressive, or compressed according to a 116 * sensible default chosen internally by the writer in a plug-in 117 * dependent way, and the relevant accessor methods will 118 * throw an <code>IllegalStateException</code>. 119 * 120 * @see #MODE_DISABLED 121 * @see #MODE_EXPLICIT 122 * @see #MODE_COPY_FROM_METADATA 123 * @see #setProgressiveMode 124 * @see #getProgressiveMode 125 * @see #setTilingMode 126 * @see #getTilingMode 127 * @see #setCompressionMode 128 * @see #getCompressionMode 129 */ 130 public static final int MODE_DEFAULT = 1; 131 132 /** 133 * A constant value that may be passed into methods such as 134 * <code>setTilingMode</code> or <code>setCompressionMode</code> 135 * to enable a feature for future writes. That is, when this mode 136 * is set the stream will be tiled or compressed according to 137 * additional information supplied to the corresponding 138 * <code>set</code> methods in this class and retrievable from the 139 * corresponding <code>get</code> methods. Note that this mode is 140 * not supported for progressive output. 141 * 142 * @see #MODE_DISABLED 143 * @see #MODE_COPY_FROM_METADATA 144 * @see #MODE_DEFAULT 145 * @see #setProgressiveMode 146 * @see #getProgressiveMode 147 * @see #setTilingMode 148 * @see #getTilingMode 149 * @see #setCompressionMode 150 * @see #getCompressionMode 151 */ 152 public static final int MODE_EXPLICIT = 2; 153 154 /** 155 * A constant value that may be passed into methods such as 156 * <code>setTilingMode</code>, <code>setProgressiveMode</code>, or 157 * <code>setCompressionMode</code> to enable that feature for 158 * future writes. That is, when this mode is enabled the stream 159 * will be tiled, progressive, or compressed based on the contents 160 * of stream and/or image metadata passed into the write 161 * operation, and any relevant accessor methods will throw an 162 * <code>IllegalStateException</code>. 163 * 164 * <p> This is the default mode for all features, so that a read 165 * including metadata followed by a write including metadata will 166 * preserve as much information as possible. 167 * 168 * @see #MODE_DISABLED 169 * @see #MODE_EXPLICIT 170 * @see #MODE_DEFAULT 171 * @see #setProgressiveMode 172 * @see #getProgressiveMode 173 * @see #setTilingMode 174 * @see #getTilingMode 175 * @see #setCompressionMode 176 * @see #getCompressionMode 177 */ 178 public static final int MODE_COPY_FROM_METADATA = 3; 179 180 // If more modes are added, this should be updated. 181 private static final int MAX_MODE = MODE_COPY_FROM_METADATA; 182 183 /** 184 * A <code>boolean</code> that is <code>true</code> if this 185 * <code>ImageWriteParam</code> allows tile width and tile height 186 * parameters to be set. By default, the value is 187 * <code>false</code>. Subclasses must set the value manually. 188 * 189 * <p> Subclasses that do not support writing tiles should ensure 190 * that this value is set to <code>false</code>. 191 */ 192 protected boolean canWriteTiles = false; 193 194 /** 195 * The mode controlling tiling settings, which Must be 196 * set to one of the four <code>MODE_*</code> values. The default 197 * is <code>MODE_COPY_FROM_METADATA</code>. 198 * 199 * <p> Subclasses that do not writing tiles may ignore this value. 200 * 201 * @see #MODE_DISABLED 202 * @see #MODE_EXPLICIT 203 * @see #MODE_COPY_FROM_METADATA 204 * @see #MODE_DEFAULT 205 * @see #setTilingMode 206 * @see #getTilingMode 207 */ 208 protected int tilingMode = MODE_COPY_FROM_METADATA; 209 210 /** 211 * An array of preferred tile size range pairs. The default value 212 * is <code>null</code>, which indicates that there are no 213 * preferred sizes. If the value is non-<code>null</code>, it 214 * must have an even length of at least two. 215 * 216 * <p> Subclasses that do not support writing tiles may ignore 217 * this value. 218 * 219 * @see #getPreferredTileSizes 220 */ 221 protected Dimension[] preferredTileSizes = null; 222 223 /** 224 * A <code>boolean</code> that is <code>true</code> if tiling 225 * parameters have been specified. 226 * 227 * <p> Subclasses that do not support writing tiles may ignore 228 * this value. 229 */ 230 protected boolean tilingSet = false; 231 232 /** 233 * The width of each tile if tiling has been set, or 0 otherwise. 234 * 235 * <p> Subclasses that do not support tiling may ignore this 236 * value. 237 */ 238 protected int tileWidth = 0; 239 240 /** 241 * The height of each tile if tiling has been set, or 0 otherwise. 242 * The initial value is <code>0</code>. 243 * 244 * <p> Subclasses that do not support tiling may ignore this 245 * value. 246 */ 247 protected int tileHeight = 0; 248 249 /** 250 * A <code>boolean</code> that is <code>true</code> if this 251 * <code>ImageWriteParam</code> allows tiling grid offset 252 * parameters to be set. By default, the value is 253 * <code>false</code>. Subclasses must set the value manually. 254 * 255 * <p> Subclasses that do not support writing tiles, or that 256 * support writing but not offsetting tiles must ensure that this 257 * value is set to <code>false</code>. 258 */ 259 protected boolean canOffsetTiles = false; 260 261 /** 262 * The amount by which the tile grid origin should be offset 263 * horizontally from the image origin if tiling has been set, 264 * or 0 otherwise. The initial value is <code>0</code>. 265 * 266 * <p> Subclasses that do not support offsetting tiles may ignore 267 * this value. 268 */ 269 protected int tileGridXOffset = 0; 270 271 /** 272 * The amount by which the tile grid origin should be offset 273 * vertically from the image origin if tiling has been set, 274 * or 0 otherwise. The initial value is <code>0</code>. 275 * 276 * <p> Subclasses that do not support offsetting tiles may ignore 277 * this value. 278 */ 279 protected int tileGridYOffset = 0; 280 281 /** 282 * A <code>boolean</code> that is <code>true</code> if this 283 * <code>ImageWriteParam</code> allows images to be written as a 284 * progressive sequence of increasing quality passes. By default, 285 * the value is <code>false</code>. Subclasses must set the value 286 * manually. 287 * 288 * <p> Subclasses that do not support progressive encoding must 289 * ensure that this value is set to <code>false</code>. 290 */ 291 protected boolean canWriteProgressive = false; 292 293 /** 294 * The mode controlling progressive encoding, which must be set to 295 * one of the four <code>MODE_*</code> values, except 296 * <code>MODE_EXPLICIT</code>. The default is 297 * <code>MODE_COPY_FROM_METADATA</code>. 298 * 299 * <p> Subclasses that do not support progressive encoding may 300 * ignore this value. 301 * 302 * @see #MODE_DISABLED 303 * @see #MODE_EXPLICIT 304 * @see #MODE_COPY_FROM_METADATA 305 * @see #MODE_DEFAULT 306 * @see #setProgressiveMode 307 * @see #getProgressiveMode 308 */ 309 protected int progressiveMode = MODE_COPY_FROM_METADATA; 310 311 /** 312 * A <code>boolean</code> that is <code>true</code> if this writer 313 * can write images using compression. By default, the value is 314 * <code>false</code>. Subclasses must set the value manually. 315 * 316 * <p> Subclasses that do not support compression must ensure that 317 * this value is set to <code>false</code>. 318 */ 319 protected boolean canWriteCompressed = false; 320 321 /** 322 * The mode controlling compression settings, which must be set to 323 * one of the four <code>MODE_*</code> values. The default is 324 * <code>MODE_COPY_FROM_METADATA</code>. 325 * 326 * <p> Subclasses that do not support compression may ignore this 327 * value. 328 * 329 * @see #MODE_DISABLED 330 * @see #MODE_EXPLICIT 331 * @see #MODE_COPY_FROM_METADATA 332 * @see #MODE_DEFAULT 333 * @see #setCompressionMode 334 * @see #getCompressionMode 335 */ 336 protected int compressionMode = MODE_COPY_FROM_METADATA; 337 338 /** 339 * An array of <code>String</code>s containing the names of the 340 * available compression types. Subclasses must set the value 341 * manually. 342 * 343 * <p> Subclasses that do not support compression may ignore this 344 * value. 345 */ 346 protected String[] compressionTypes = null; 347 348 /** 349 * A <code>String</code> containing the name of the current 350 * compression type, or <code>null</code> if none is set. 351 * 352 * <p> Subclasses that do not support compression may ignore this 353 * value. 354 */ 355 protected String compressionType = null; 356 357 /** 358 * A <code>float</code> containing the current compression quality 359 * setting. The initial value is <code>1.0F</code>. 360 * 361 * <p> Subclasses that do not support compression may ignore this 362 * value. 363 */ 364 protected float compressionQuality = 1.0F; 365 366 /** 367 * A <code>Locale</code> to be used to localize compression type 368 * names and quality descriptions, or <code>null</code> to use a 369 * default <code>Locale</code>. Subclasses must set the value 370 * manually. 371 */ 372 protected Locale locale = null; 373 374 /** 375 * Constructs an empty <code>ImageWriteParam</code>. It is up to 376 * the subclass to set up the instance variables properly. 377 */ 378 protected ImageWriteParam() {} 379 380 /** 381 * Constructs an <code>ImageWriteParam</code> set to use a 382 * given <code>Locale</code>. 383 * 384 * @param locale a <code>Locale</code> to be used to localize 385 * compression type names and quality descriptions, or 386 * <code>null</code>. 387 */ 388 public ImageWriteParam(Locale locale) { 389 this.locale = locale; 390 } 391 392 // Return a deep copy of the array 393 private static Dimension[] clonePreferredTileSizes(Dimension[] sizes) { 394 if (sizes == null) { 395 return null; 396 } 397 Dimension[] temp = new Dimension[sizes.length]; 398 for (int i = 0; i < sizes.length; i++) { 399 temp[i] = new Dimension(sizes[i]); 400 } 401 return temp; 402 } 403 404 /** 405 * Returns the currently set <code>Locale</code>, or 406 * <code>null</code> if only a default <code>Locale</code> is 407 * supported. 408 * 409 * @return the current <code>Locale</code>, or <code>null</code>. 410 */ 411 public Locale getLocale() { 412 return locale; 413 } 414 415 /** 416 * Returns <code>true</code> if the writer can perform tiling 417 * while writing. If this method returns <code>false</code>, then 418 * <code>setTiling</code> will throw an 419 * <code>UnsupportedOperationException</code>. 420 * 421 * @return <code>true</code> if the writer supports tiling. 422 * 423 * @see #canOffsetTiles() 424 * @see #setTiling(int, int, int, int) 425 */ 426 public boolean canWriteTiles() { 427 return canWriteTiles; 428 } 429 430 /** 431 * Returns <code>true</code> if the writer can perform tiling with 432 * non-zero grid offsets while writing. If this method returns 433 * <code>false</code>, then <code>setTiling</code> will throw an 434 * <code>UnsupportedOperationException</code> if the grid offset 435 * arguments are not both zero. If <code>canWriteTiles</code> 436 * returns <code>false</code>, this method will return 437 * <code>false</code> as well. 438 * 439 * @return <code>true</code> if the writer supports non-zero tile 440 * offsets. 441 * 442 * @see #canWriteTiles() 443 * @see #setTiling(int, int, int, int) 444 */ 445 public boolean canOffsetTiles() { 446 return canOffsetTiles; 447 } 448 449 /** 450 * Determines whether the image will be tiled in the output 451 * stream and, if it will, how the tiling parameters will be 452 * determined. The modes are interpreted as follows: 453 * 454 * <ul> 455 * 456 * <li><code>MODE_DISABLED</code> - The image will not be tiled. 457 * <code>setTiling</code> will throw an 458 * <code>IllegalStateException</code>. 459 * 460 * <li><code>MODE_DEFAULT</code> - The image will be tiled using 461 * default parameters. <code>setTiling</code> will throw an 462 * <code>IllegalStateException</code>. 463 * 464 * <li><code>MODE_EXPLICIT</code> - The image will be tiled 465 * according to parameters given in the {@link #setTiling setTiling} 466 * method. Any previously set tiling parameters are discarded. 467 * 468 * <li><code>MODE_COPY_FROM_METADATA</code> - The image will 469 * conform to the metadata object passed in to a write. 470 * <code>setTiling</code> will throw an 471 * <code>IllegalStateException</code>. 472 * 473 * </ul> 474 * 475 * @param mode The mode to use for tiling. 476 * 477 * @exception UnsupportedOperationException if 478 * <code>canWriteTiles</code> returns <code>false</code>. 479 * @exception IllegalArgumentException if <code>mode</code> is not 480 * one of the modes listed above. 481 * 482 * @see #setTiling 483 * @see #getTilingMode 484 */ 485 public void setTilingMode(int mode) { 486 if (canWriteTiles() == false) { 487 throw new UnsupportedOperationException("Tiling not supported!"); 488 } 489 if (mode < MODE_DISABLED || mode > MAX_MODE) { 490 throw new IllegalArgumentException("Illegal value for mode!"); 491 } 492 this.tilingMode = mode; 493 if (mode == MODE_EXPLICIT) { 494 unsetTiling(); 495 } 496 } 497 498 /** 499 * Returns the current tiling mode, if tiling is supported. 500 * Otherwise throws an <code>UnsupportedOperationException</code>. 501 * 502 * @return the current tiling mode. 503 * 504 * @exception UnsupportedOperationException if 505 * <code>canWriteTiles</code> returns <code>false</code>. 506 * 507 * @see #setTilingMode 508 */ 509 public int getTilingMode() { 510 if (!canWriteTiles()) { 511 throw new UnsupportedOperationException("Tiling not supported"); 512 } 513 return tilingMode; 514 } 515 516 /** 517 * Returns an array of <code>Dimension</code>s indicating the 518 * legal size ranges for tiles as they will be encoded in the 519 * output file or stream. The returned array is a copy. 520 * 521 * <p> The information is returned as a set of pairs; the first 522 * element of a pair contains an (inclusive) minimum width and 523 * height, and the second element contains an (inclusive) maximum 524 * width and height. Together, each pair defines a valid range of 525 * sizes. To specify a fixed size, use the same width and height 526 * for both elements. To specify an arbitrary range, a value of 527 * <code>null</code> is used in place of an actual array of 528 * <code>Dimension</code>s. 529 * 530 * <p> If no array is specified on the constructor, but tiling is 531 * allowed, then this method returns <code>null</code>. 532 * 533 * @exception UnsupportedOperationException if the plug-in does 534 * not support tiling. 535 * 536 * @return an array of <code>Dimension</code>s with an even length 537 * of at least two, or <code>null</code>. 538 */ 539 public Dimension[] getPreferredTileSizes() { 540 if (!canWriteTiles()) { 541 throw new UnsupportedOperationException("Tiling not supported"); 542 } 543 return clonePreferredTileSizes(preferredTileSizes); 544 } 545 546 /** 547 * Specifies that the image should be tiled in the output stream. 548 * The <code>tileWidth</code> and <code>tileHeight</code> 549 * parameters specify the width and height of the tiles in the 550 * file. If the tile width or height is greater than the width or 551 * height of the image, the image is not tiled in that dimension. 552 * 553 * <p> If <code>canOffsetTiles</code> returns <code>false</code>, 554 * then the <code>tileGridXOffset</code> and 555 * <code>tileGridYOffset</code> parameters must be zero. 556 * 557 * @param tileWidth the width of each tile. 558 * @param tileHeight the height of each tile. 559 * @param tileGridXOffset the horizontal offset of the tile grid. 560 * @param tileGridYOffset the vertical offset of the tile grid. 561 * 562 * @exception UnsupportedOperationException if the plug-in does not 563 * support tiling. 564 * @exception IllegalStateException if the tiling mode is not 565 * <code>MODE_EXPLICIT</code>. 566 * @exception UnsupportedOperationException if the plug-in does not 567 * support grid offsets, and the grid offsets are not both zero. 568 * @exception IllegalArgumentException if the tile size is not 569 * within one of the allowable ranges returned by 570 * <code>getPreferredTileSizes</code>. 571 * @exception IllegalArgumentException if <code>tileWidth</code> 572 * or <code>tileHeight</code> is less than or equal to 0. 573 * 574 * @see #canWriteTiles 575 * @see #canOffsetTiles 576 * @see #getTileWidth() 577 * @see #getTileHeight() 578 * @see #getTileGridXOffset() 579 * @see #getTileGridYOffset() 580 */ 581 public void setTiling(int tileWidth, 582 int tileHeight, 583 int tileGridXOffset, 584 int tileGridYOffset) { 585 if (!canWriteTiles()) { 586 throw new UnsupportedOperationException("Tiling not supported!"); 587 } 588 if (getTilingMode() != MODE_EXPLICIT) { 589 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 590 } 591 if (tileWidth <= 0 || tileHeight <= 0) { 592 throw new IllegalArgumentException 593 ("tile dimensions are non-positive!"); 594 } 595 boolean tilesOffset = (tileGridXOffset != 0) || (tileGridYOffset != 0); 596 if (!canOffsetTiles() && tilesOffset) { 597 throw new UnsupportedOperationException("Can't offset tiles!"); 598 } 599 if (preferredTileSizes != null) { 600 boolean ok = true; 601 for (int i = 0; i < preferredTileSizes.length; i += 2) { 602 Dimension min = preferredTileSizes[i]; 603 Dimension max = preferredTileSizes[i+1]; 604 if ((tileWidth < min.width) || 605 (tileWidth > max.width) || 606 (tileHeight < min.height) || 607 (tileHeight > max.height)) { 608 ok = false; 609 break; 610 } 611 } 612 if (!ok) { 613 throw new IllegalArgumentException("Illegal tile size!"); 614 } 615 } 616 617 this.tilingSet = true; 618 this.tileWidth = tileWidth; 619 this.tileHeight = tileHeight; 620 this.tileGridXOffset = tileGridXOffset; 621 this.tileGridYOffset = tileGridYOffset; 622 } 623 624 /** 625 * Removes any previous tile grid parameters specified by calls to 626 * <code>setTiling</code>. 627 * 628 * <p> The default implementation sets the instance variables 629 * <code>tileWidth</code>, <code>tileHeight</code>, 630 * <code>tileGridXOffset</code>, and 631 * <code>tileGridYOffset</code> to <code>0</code>. 632 * 633 * @exception UnsupportedOperationException if the plug-in does not 634 * support tiling. 635 * @exception IllegalStateException if the tiling mode is not 636 * <code>MODE_EXPLICIT</code>. 637 * 638 * @see #setTiling(int, int, int, int) 639 */ 640 public void unsetTiling() { 641 if (!canWriteTiles()) { 642 throw new UnsupportedOperationException("Tiling not supported!"); 643 } 644 if (getTilingMode() != MODE_EXPLICIT) { 645 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 646 } 647 this.tilingSet = false; 648 this.tileWidth = 0; 649 this.tileHeight = 0; 650 this.tileGridXOffset = 0; 651 this.tileGridYOffset = 0; 652 } 653 654 /** 655 * Returns the width of each tile in an image as it will be 656 * written to the output stream. If tiling parameters have not 657 * been set, an <code>IllegalStateException</code> is thrown. 658 * 659 * @return the tile width to be used for encoding. 660 * 661 * @exception UnsupportedOperationException if the plug-in does not 662 * support tiling. 663 * @exception IllegalStateException if the tiling mode is not 664 * <code>MODE_EXPLICIT</code>. 665 * @exception IllegalStateException if the tiling parameters have 666 * not been set. 667 * 668 * @see #setTiling(int, int, int, int) 669 * @see #getTileHeight() 670 */ 671 public int getTileWidth() { 672 if (!canWriteTiles()) { 673 throw new UnsupportedOperationException("Tiling not supported!"); 674 } 675 if (getTilingMode() != MODE_EXPLICIT) { 676 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 677 } 678 if (!tilingSet) { 679 throw new IllegalStateException("Tiling parameters not set!"); 680 } 681 return tileWidth; 682 } 683 684 /** 685 * Returns the height of each tile in an image as it will be written to 686 * the output stream. If tiling parameters have not 687 * been set, an <code>IllegalStateException</code> is thrown. 688 * 689 * @return the tile height to be used for encoding. 690 * 691 * @exception UnsupportedOperationException if the plug-in does not 692 * support tiling. 693 * @exception IllegalStateException if the tiling mode is not 694 * <code>MODE_EXPLICIT</code>. 695 * @exception IllegalStateException if the tiling parameters have 696 * not been set. 697 * 698 * @see #setTiling(int, int, int, int) 699 * @see #getTileWidth() 700 */ 701 public int getTileHeight() { 702 if (!canWriteTiles()) { 703 throw new UnsupportedOperationException("Tiling not supported!"); 704 } 705 if (getTilingMode() != MODE_EXPLICIT) { 706 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 707 } 708 if (!tilingSet) { 709 throw new IllegalStateException("Tiling parameters not set!"); 710 } 711 return tileHeight; 712 } 713 714 /** 715 * Returns the horizontal tile grid offset of an image as it will 716 * be written to the output stream. If tiling parameters have not 717 * been set, an <code>IllegalStateException</code> is thrown. 718 * 719 * @return the tile grid X offset to be used for encoding. 720 * 721 * @exception UnsupportedOperationException if the plug-in does not 722 * support tiling. 723 * @exception IllegalStateException if the tiling mode is not 724 * <code>MODE_EXPLICIT</code>. 725 * @exception IllegalStateException if the tiling parameters have 726 * not been set. 727 * 728 * @see #setTiling(int, int, int, int) 729 * @see #getTileGridYOffset() 730 */ 731 public int getTileGridXOffset() { 732 if (!canWriteTiles()) { 733 throw new UnsupportedOperationException("Tiling not supported!"); 734 } 735 if (getTilingMode() != MODE_EXPLICIT) { 736 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 737 } 738 if (!tilingSet) { 739 throw new IllegalStateException("Tiling parameters not set!"); 740 } 741 return tileGridXOffset; 742 } 743 744 /** 745 * Returns the vertical tile grid offset of an image as it will 746 * be written to the output stream. If tiling parameters have not 747 * been set, an <code>IllegalStateException</code> is thrown. 748 * 749 * @return the tile grid Y offset to be used for encoding. 750 * 751 * @exception UnsupportedOperationException if the plug-in does not 752 * support tiling. 753 * @exception IllegalStateException if the tiling mode is not 754 * <code>MODE_EXPLICIT</code>. 755 * @exception IllegalStateException if the tiling parameters have 756 * not been set. 757 * 758 * @see #setTiling(int, int, int, int) 759 * @see #getTileGridXOffset() 760 */ 761 public int getTileGridYOffset() { 762 if (!canWriteTiles()) { 763 throw new UnsupportedOperationException("Tiling not supported!"); 764 } 765 if (getTilingMode() != MODE_EXPLICIT) { 766 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 767 } 768 if (!tilingSet) { 769 throw new IllegalStateException("Tiling parameters not set!"); 770 } 771 return tileGridYOffset; 772 } 773 774 /** 775 * Returns <code>true</code> if the writer can write out images 776 * as a series of passes of progressively increasing quality. 777 * 778 * @return <code>true</code> if the writer supports progressive 779 * encoding. 780 * 781 * @see #setProgressiveMode 782 * @see #getProgressiveMode 783 */ 784 public boolean canWriteProgressive() { 785 return canWriteProgressive; 786 } 787 788 /** 789 * Specifies that the writer is to write the image out in a 790 * progressive mode such that the stream will contain a series of 791 * scans of increasing quality. If progressive encoding is not 792 * supported, an <code>UnsupportedOperationException</code> will 793 * be thrown. 794 * 795 * <p> The mode argument determines how 796 * the progression parameters are chosen, and must be either 797 * <code>MODE_DISABLED</code>, 798 * <code>MODE_COPY_FROM_METADATA</code>, or 799 * <code>MODE_DEFAULT</code>. Otherwise an 800 * <code>IllegalArgumentException</code> is thrown. 801 * 802 * <p> The modes are interpreted as follows: 803 * 804 * <ul> 805 * <li><code>MODE_DISABLED</code> - No progression. Use this to 806 * turn off progression. 807 * 808 * <li><code>MODE_COPY_FROM_METADATA</code> - The output image 809 * will use whatever progression parameters are found in the 810 * metadata objects passed into the writer. 811 * 812 * <li><code>MODE_DEFAULT</code> - The image will be written 813 * progressively, with parameters chosen by the writer. 814 * </ul> 815 * 816 * <p> The default is <code>MODE_COPY_FROM_METADATA</code>. 817 * 818 * @param mode The mode for setting progression in the output 819 * stream. 820 * 821 * @exception UnsupportedOperationException if the writer does not 822 * support progressive encoding. 823 * @exception IllegalArgumentException if <code>mode</code> is not 824 * one of the modes listed above. 825 * 826 * @see #getProgressiveMode 827 */ 828 public void setProgressiveMode(int mode) { 829 if (!canWriteProgressive()) { 830 throw new UnsupportedOperationException( 831 "Progressive output not supported"); 832 } 833 if (mode < MODE_DISABLED || mode > MAX_MODE) { 834 throw new IllegalArgumentException("Illegal value for mode!"); 835 } 836 if (mode == MODE_EXPLICIT) { 837 throw new IllegalArgumentException( 838 "MODE_EXPLICIT not supported for progressive output"); 839 } 840 this.progressiveMode = mode; 841 } 842 843 /** 844 * Returns the current mode for writing the stream in a 845 * progressive manner. 846 * 847 * @return the current mode for progressive encoding. 848 * 849 * @exception UnsupportedOperationException if the writer does not 850 * support progressive encoding. 851 * 852 * @see #setProgressiveMode 853 */ 854 public int getProgressiveMode() { 855 if (!canWriteProgressive()) { 856 throw new UnsupportedOperationException 857 ("Progressive output not supported"); 858 } 859 return progressiveMode; 860 } 861 862 /** 863 * Returns <code>true</code> if this writer supports compression. 864 * 865 * @return <code>true</code> if the writer supports compression. 866 */ 867 public boolean canWriteCompressed() { 868 return canWriteCompressed; 869 } 870 871 /** 872 * Specifies whether compression is to be performed, and if so how 873 * compression parameters are to be determined. The <code>mode</code> 874 * argument must be one of the four modes, interpreted as follows: 875 * 876 * <ul> 877 * <li><code>MODE_DISABLED</code> - If the mode is set to 878 * <code>MODE_DISABLED</code>, methods that query or modify the 879 * compression type or parameters will throw an 880 * <code>IllegalStateException</code> (if compression is 881 * normally supported by the plug-in). Some writers, such as JPEG, 882 * do not normally offer uncompressed output. In this case, attempting 883 * to set the mode to <code>MODE_DISABLED</code> will throw an 884 * <code>UnsupportedOperationException</code> and the mode will not be 885 * changed. 886 * 887 * <li><code>MODE_EXPLICIT</code> - Compress using the 888 * compression type and quality settings specified in this 889 * <code>ImageWriteParam</code>. Any previously set compression 890 * parameters are discarded. 891 * 892 * <li><code>MODE_COPY_FROM_METADATA</code> - Use whatever 893 * compression parameters are specified in metadata objects 894 * passed in to the writer. 895 * 896 * <li><code>MODE_DEFAULT</code> - Use default compression 897 * parameters. 898 * </ul> 899 * 900 * <p> The default is <code>MODE_COPY_FROM_METADATA</code>. 901 * 902 * @param mode The mode for setting compression in the output 903 * stream. 904 * 905 * @exception UnsupportedOperationException if the writer does not 906 * support compression, or does not support the requested mode. 907 * @exception IllegalArgumentException if <code>mode</code> is not 908 * one of the modes listed above. 909 * 910 * @see #getCompressionMode 911 */ 912 public void setCompressionMode(int mode) { 913 if (!canWriteCompressed()) { 914 throw new UnsupportedOperationException( 915 "Compression not supported."); 916 } 917 if (mode < MODE_DISABLED || mode > MAX_MODE) { 918 throw new IllegalArgumentException("Illegal value for mode!"); 919 } 920 this.compressionMode = mode; 921 if (mode == MODE_EXPLICIT) { 922 unsetCompression(); 923 } 924 } 925 926 /** 927 * Returns the current compression mode, if compression is 928 * supported. 929 * 930 * @return the current compression mode. 931 * 932 * @exception UnsupportedOperationException if the writer does not 933 * support compression. 934 * 935 * @see #setCompressionMode 936 */ 937 public int getCompressionMode() { 938 if (!canWriteCompressed()) { 939 throw new UnsupportedOperationException( 940 "Compression not supported."); 941 } 942 return compressionMode; 943 } 944 945 /** 946 * Returns a list of available compression types, as an array or 947 * <code>String</code>s, or <code>null</code> if a compression 948 * type may not be chosen using these interfaces. The array 949 * returned is a copy. 950 * 951 * <p> If the writer only offers a single, mandatory form of 952 * compression, it is not necessary to provide any named 953 * compression types. Named compression types should only be 954 * used where the user is able to make a meaningful choice 955 * between different schemes. 956 * 957 * <p> The default implementation checks if compression is 958 * supported and throws an 959 * <code>UnsupportedOperationException</code> if not. Otherwise, 960 * it returns a clone of the <code>compressionTypes</code> 961 * instance variable if it is non-<code>null</code>, or else 962 * returns <code>null</code>. 963 * 964 * @return an array of <code>String</code>s containing the 965 * (non-localized) names of available compression types, or 966 * <code>null</code>. 967 * 968 * @exception UnsupportedOperationException if the writer does not 969 * support compression. 970 */ 971 public String[] getCompressionTypes() { 972 if (!canWriteCompressed()) { 973 throw new UnsupportedOperationException( 974 "Compression not supported"); 975 } 976 if (compressionTypes == null) { 977 return null; 978 } 979 return compressionTypes.clone(); 980 } 981 982 /** 983 * Sets the compression type to one of the values indicated by 984 * <code>getCompressionTypes</code>. If a value of 985 * <code>null</code> is passed in, any previous setting is 986 * removed. 987 * 988 * <p> The default implementation checks whether compression is 989 * supported and the compression mode is 990 * <code>MODE_EXPLICIT</code>. If so, it calls 991 * <code>getCompressionTypes</code> and checks if 992 * <code>compressionType</code> is one of the legal values. If it 993 * is, the <code>compressionType</code> instance variable is set. 994 * If <code>compressionType</code> is <code>null</code>, the 995 * instance variable is set without performing any checking. 996 * 997 * @param compressionType one of the <code>String</code>s returned 998 * by <code>getCompressionTypes</code>, or <code>null</code> to 999 * remove any previous setting. 1000 * 1001 * @exception UnsupportedOperationException if the writer does not 1002 * support compression. 1003 * @exception IllegalStateException if the compression mode is not 1004 * <code>MODE_EXPLICIT</code>. 1005 * @exception UnsupportedOperationException if there are no 1006 * settable compression types. 1007 * @exception IllegalArgumentException if 1008 * <code>compressionType</code> is non-<code>null</code> but is not 1009 * one of the values returned by <code>getCompressionTypes</code>. 1010 * 1011 * @see #getCompressionTypes 1012 * @see #getCompressionType 1013 * @see #unsetCompression 1014 */ 1015 public void setCompressionType(String compressionType) { 1016 if (!canWriteCompressed()) { 1017 throw new UnsupportedOperationException( 1018 "Compression not supported"); 1019 } 1020 if (getCompressionMode() != MODE_EXPLICIT) { 1021 throw new IllegalStateException 1022 ("Compression mode not MODE_EXPLICIT!"); 1023 } 1024 String[] legalTypes = getCompressionTypes(); 1025 if (legalTypes == null) { 1026 throw new UnsupportedOperationException( 1027 "No settable compression types"); 1028 } 1029 if (compressionType != null) { 1030 boolean found = false; 1031 if (legalTypes != null) { 1032 for (int i = 0; i < legalTypes.length; i++) { 1033 if (compressionType.equals(legalTypes[i])) { 1034 found = true; 1035 break; 1036 } 1037 } 1038 } 1039 if (!found) { 1040 throw new IllegalArgumentException("Unknown compression type!"); 1041 } 1042 } 1043 this.compressionType = compressionType; 1044 } 1045 1046 /** 1047 * Returns the currently set compression type, or 1048 * <code>null</code> if none has been set. The type is returned 1049 * as a <code>String</code> from among those returned by 1050 * <code>getCompressionTypes</code>. 1051 * If no compression type has been set, <code>null</code> is 1052 * returned. 1053 * 1054 * <p> The default implementation checks whether compression is 1055 * supported and the compression mode is 1056 * <code>MODE_EXPLICIT</code>. If so, it returns the value of the 1057 * <code>compressionType</code> instance variable. 1058 * 1059 * @return the current compression type as a <code>String</code>, 1060 * or <code>null</code> if no type is set. 1061 * 1062 * @exception UnsupportedOperationException if the writer does not 1063 * support compression. 1064 * @exception IllegalStateException if the compression mode is not 1065 * <code>MODE_EXPLICIT</code>. 1066 * 1067 * @see #setCompressionType 1068 */ 1069 public String getCompressionType() { 1070 if (!canWriteCompressed()) { 1071 throw new UnsupportedOperationException( 1072 "Compression not supported."); 1073 } 1074 if (getCompressionMode() != MODE_EXPLICIT) { 1075 throw new IllegalStateException 1076 ("Compression mode not MODE_EXPLICIT!"); 1077 } 1078 return compressionType; 1079 } 1080 1081 /** 1082 * Removes any previous compression type and quality settings. 1083 * 1084 * <p> The default implementation sets the instance variable 1085 * <code>compressionType</code> to <code>null</code>, and the 1086 * instance variable <code>compressionQuality</code> to 1087 * <code>1.0F</code>. 1088 * 1089 * @exception UnsupportedOperationException if the plug-in does not 1090 * support compression. 1091 * @exception IllegalStateException if the compression mode is not 1092 * <code>MODE_EXPLICIT</code>. 1093 * 1094 * @see #setCompressionType 1095 * @see #setCompressionQuality 1096 */ 1097 public void unsetCompression() { 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 this.compressionType = null; 1107 this.compressionQuality = 1.0F; 1108 } 1109 1110 /** 1111 * Returns a localized version of the name of the current 1112 * compression type, using the <code>Locale</code> returned by 1113 * <code>getLocale</code>. 1114 * 1115 * <p> The default implementation checks whether compression is 1116 * supported and the compression mode is 1117 * <code>MODE_EXPLICIT</code>. If so, if 1118 * <code>compressionType</code> is <code>non-null</code> the value 1119 * of <code>getCompressionType</code> is returned as a 1120 * convenience. 1121 * 1122 * @return a <code>String</code> containing a localized version of 1123 * the name of the current compression type. 1124 * 1125 * @exception UnsupportedOperationException if the writer does not 1126 * support compression. 1127 * @exception IllegalStateException if the compression mode is not 1128 * <code>MODE_EXPLICIT</code>. 1129 * @exception IllegalStateException if no compression type is set. 1130 */ 1131 public String getLocalizedCompressionTypeName() { 1132 if (!canWriteCompressed()) { 1133 throw new UnsupportedOperationException( 1134 "Compression not supported."); 1135 } 1136 if (getCompressionMode() != MODE_EXPLICIT) { 1137 throw new IllegalStateException 1138 ("Compression mode not MODE_EXPLICIT!"); 1139 } 1140 if (getCompressionType() == null) { 1141 throw new IllegalStateException("No compression type set!"); 1142 } 1143 return getCompressionType(); 1144 } 1145 1146 /** 1147 * Returns <code>true</code> if the current compression type 1148 * provides lossless compression. If a plug-in provides only 1149 * one mandatory compression type, then this method may be 1150 * called without calling <code>setCompressionType</code> first. 1151 * 1152 * <p> If there are multiple compression types but none has 1153 * been set, an <code>IllegalStateException</code> is thrown. 1154 * 1155 * <p> The default implementation checks whether compression is 1156 * supported and the compression mode is 1157 * <code>MODE_EXPLICIT</code>. If so, if 1158 * <code>getCompressionTypes()</code> is <code>null</code> or 1159 * <code>getCompressionType()</code> is non-<code>null</code> 1160 * <code>true</code> is returned as a convenience. 1161 * 1162 * @return <code>true</code> if the current compression type is 1163 * lossless. 1164 * 1165 * @exception UnsupportedOperationException if the writer does not 1166 * support compression. 1167 * @exception IllegalStateException if the compression mode is not 1168 * <code>MODE_EXPLICIT</code>. 1169 * @exception IllegalStateException if the set of legal 1170 * compression types is non-<code>null</code> and the current 1171 * compression type is <code>null</code>. 1172 */ 1173 public boolean isCompressionLossless() { 1174 if (!canWriteCompressed()) { 1175 throw new UnsupportedOperationException( 1176 "Compression not supported"); 1177 } 1178 if (getCompressionMode() != MODE_EXPLICIT) { 1179 throw new IllegalStateException 1180 ("Compression mode not MODE_EXPLICIT!"); 1181 } 1182 if ((getCompressionTypes() != null) && 1183 (getCompressionType() == null)) { 1184 throw new IllegalStateException("No compression type set!"); 1185 } 1186 return true; 1187 } 1188 1189 /** 1190 * Sets the compression quality to a value between <code>0</code> 1191 * and <code>1</code>. Only a single compression quality setting 1192 * is supported by default; writers can provide extended versions 1193 * of <code>ImageWriteParam</code> that offer more control. For 1194 * lossy compression schemes, the compression quality should 1195 * control the tradeoff between file size and image quality (for 1196 * example, by choosing quantization tables when writing JPEG 1197 * images). For lossless schemes, the compression quality may be 1198 * used to control the tradeoff between file size and time taken 1199 * to perform the compression (for example, by optimizing row 1200 * filters and setting the ZLIB compression level when writing 1201 * PNG images). 1202 * 1203 * <p> A compression quality setting of 0.0 is most generically 1204 * interpreted as "high compression is important," while a setting of 1205 * 1.0 is most generically interpreted as "high image quality is 1206 * important." 1207 * 1208 * <p> If there are multiple compression types but none has been 1209 * set, an <code>IllegalStateException</code> is thrown. 1210 * 1211 * <p> The default implementation checks that compression is 1212 * supported, and that the compression mode is 1213 * <code>MODE_EXPLICIT</code>. If so, if 1214 * <code>getCompressionTypes()</code> returns <code>null</code> or 1215 * <code>compressionType</code> is non-<code>null</code> it sets 1216 * the <code>compressionQuality</code> instance variable. 1217 * 1218 * @param quality a <code>float</code> between <code>0</code>and 1219 * <code>1</code> indicating the desired quality level. 1220 * 1221 * @exception UnsupportedOperationException if the writer does not 1222 * support compression. 1223 * @exception IllegalStateException if the compression mode is not 1224 * <code>MODE_EXPLICIT</code>. 1225 * @exception IllegalStateException if the set of legal 1226 * compression types is non-<code>null</code> and the current 1227 * compression type is <code>null</code>. 1228 * @exception IllegalArgumentException if <code>quality</code> is 1229 * not between <code>0</code>and <code>1</code>, inclusive. 1230 * 1231 * @see #getCompressionQuality 1232 */ 1233 public void setCompressionQuality(float quality) { 1234 if (!canWriteCompressed()) { 1235 throw new UnsupportedOperationException( 1236 "Compression not supported"); 1237 } 1238 if (getCompressionMode() != MODE_EXPLICIT) { 1239 throw new IllegalStateException 1240 ("Compression mode not MODE_EXPLICIT!"); 1241 } 1242 if (getCompressionTypes() != null && getCompressionType() == null) { 1243 throw new IllegalStateException("No compression type set!"); 1244 } 1245 if (quality < 0.0F || quality > 1.0F) { 1246 throw new IllegalArgumentException("Quality out-of-bounds!"); 1247 } 1248 this.compressionQuality = quality; 1249 } 1250 1251 /** 1252 * Returns the current compression quality setting. 1253 * 1254 * <p> If there are multiple compression types but none has been 1255 * set, an <code>IllegalStateException</code> is thrown. 1256 * 1257 * <p> The default implementation checks that compression is 1258 * supported and that the compression mode is 1259 * <code>MODE_EXPLICIT</code>. If so, if 1260 * <code>getCompressionTypes()</code> is <code>null</code> or 1261 * <code>getCompressionType()</code> is non-<code>null</code>, it 1262 * returns the value of the <code>compressionQuality</code> 1263 * instance variable. 1264 * 1265 * @return the current compression quality setting. 1266 * 1267 * @exception UnsupportedOperationException if the writer does not 1268 * support compression. 1269 * @exception IllegalStateException if the compression mode is not 1270 * <code>MODE_EXPLICIT</code>. 1271 * @exception IllegalStateException if the set of legal 1272 * compression types is non-<code>null</code> and the current 1273 * compression type is <code>null</code>. 1274 * 1275 * @see #setCompressionQuality 1276 */ 1277 public float getCompressionQuality() { 1278 if (!canWriteCompressed()) { 1279 throw new UnsupportedOperationException( 1280 "Compression not supported."); 1281 } 1282 if (getCompressionMode() != MODE_EXPLICIT) { 1283 throw new IllegalStateException 1284 ("Compression mode not MODE_EXPLICIT!"); 1285 } 1286 if ((getCompressionTypes() != null) && 1287 (getCompressionType() == null)) { 1288 throw new IllegalStateException("No compression type set!"); 1289 } 1290 return compressionQuality; 1291 } 1292 1293 1294 /** 1295 * Returns a <code>float</code> indicating an estimate of the 1296 * number of bits of output data for each bit of input image data 1297 * at the given quality level. The value will typically lie 1298 * between <code>0</code> and <code>1</code>, with smaller values 1299 * indicating more compression. A special value of 1300 * <code>-1.0F</code> is used to indicate that no estimate is 1301 * available. 1302 * 1303 * <p> If there are multiple compression types but none has been set, 1304 * an <code>IllegalStateException</code> is thrown. 1305 * 1306 * <p> The default implementation checks that compression is 1307 * supported and the compression mode is 1308 * <code>MODE_EXPLICIT</code>. If so, if 1309 * <code>getCompressionTypes()</code> is <code>null</code> or 1310 * <code>getCompressionType()</code> is non-<code>null</code>, and 1311 * <code>quality</code> is within bounds, it returns 1312 * <code>-1.0</code>. 1313 * 1314 * @param quality the quality setting whose bit rate is to be 1315 * queried. 1316 * 1317 * @return an estimate of the compressed bit rate, or 1318 * <code>-1.0F</code> if no estimate is available. 1319 * 1320 * @exception UnsupportedOperationException if the writer does not 1321 * support compression. 1322 * @exception IllegalStateException if the compression mode is not 1323 * <code>MODE_EXPLICIT</code>. 1324 * @exception IllegalStateException if the set of legal 1325 * compression types is non-<code>null</code> and the current 1326 * compression type is <code>null</code>. 1327 * @exception IllegalArgumentException if <code>quality</code> is 1328 * not between <code>0</code>and <code>1</code>, inclusive. 1329 */ 1330 public float getBitRate(float quality) { 1331 if (!canWriteCompressed()) { 1332 throw new UnsupportedOperationException( 1333 "Compression not supported."); 1334 } 1335 if (getCompressionMode() != MODE_EXPLICIT) { 1336 throw new IllegalStateException 1337 ("Compression mode not MODE_EXPLICIT!"); 1338 } 1339 if ((getCompressionTypes() != null) && 1340 (getCompressionType() == null)) { 1341 throw new IllegalStateException("No compression type set!"); 1342 } 1343 if (quality < 0.0F || quality > 1.0F) { 1344 throw new IllegalArgumentException("Quality out-of-bounds!"); 1345 } 1346 return -1.0F; 1347 } 1348 1349 /** 1350 * Returns an array of <code>String</code>s that may be used along 1351 * with <code>getCompressionQualityValues</code> as part of a user 1352 * interface for setting or displaying the compression quality 1353 * level. The <code>String</code> with index <code>i</code> 1354 * provides a description of the range of quality levels between 1355 * <code>getCompressionQualityValues[i]</code> and 1356 * <code>getCompressionQualityValues[i + 1]</code>. Note that the 1357 * length of the array returned from 1358 * <code>getCompressionQualityValues</code> will always be one 1359 * greater than that returned from 1360 * <code>getCompressionQualityDescriptions</code>. 1361 * 1362 * <p> As an example, the strings "Good", "Better", and "Best" 1363 * could be associated with the ranges <code>[0, .33)</code>, 1364 * <code>[.33, .66)</code>, and <code>[.66, 1.0]</code>. In this 1365 * case, <code>getCompressionQualityDescriptions</code> would 1366 * return <code>{ "Good", "Better", "Best" }</code> and 1367 * <code>getCompressionQualityValues</code> would return 1368 * <code>{ 0.0F, .33F, .66F, 1.0F }</code>. 1369 * 1370 * <p> If no descriptions are available, <code>null</code> is 1371 * returned. If <code>null</code> is returned from 1372 * <code>getCompressionQualityValues</code>, this method must also 1373 * return <code>null</code>. 1374 * 1375 * <p> The descriptions should be localized for the 1376 * <code>Locale</code> returned by <code>getLocale</code>, if it 1377 * is non-<code>null</code>. 1378 * 1379 * <p> If there are multiple compression types but none has been set, 1380 * an <code>IllegalStateException</code> is thrown. 1381 * 1382 * <p> The default implementation checks that compression is 1383 * supported and that the compression mode is 1384 * <code>MODE_EXPLICIT</code>. If so, if 1385 * <code>getCompressionTypes()</code> is <code>null</code> or 1386 * <code>getCompressionType()</code> is non-<code>null</code>, it 1387 * returns <code>null</code>. 1388 * 1389 * @return an array of <code>String</code>s containing localized 1390 * descriptions of the compression quality levels. 1391 * 1392 * @exception UnsupportedOperationException if the writer does not 1393 * support compression. 1394 * @exception IllegalStateException if the compression mode is not 1395 * <code>MODE_EXPLICIT</code>. 1396 * @exception IllegalStateException if the set of legal 1397 * compression types is non-<code>null</code> and the current 1398 * compression type is <code>null</code>. 1399 * 1400 * @see #getCompressionQualityValues 1401 */ 1402 public String[] getCompressionQualityDescriptions() { 1403 if (!canWriteCompressed()) { 1404 throw new UnsupportedOperationException( 1405 "Compression not supported."); 1406 } 1407 if (getCompressionMode() != MODE_EXPLICIT) { 1408 throw new IllegalStateException 1409 ("Compression mode not MODE_EXPLICIT!"); 1410 } 1411 if ((getCompressionTypes() != null) && 1412 (getCompressionType() == null)) { 1413 throw new IllegalStateException("No compression type set!"); 1414 } 1415 return null; 1416 } 1417 1418 /** 1419 * Returns an array of <code>float</code>s that may be used along 1420 * with <code>getCompressionQualityDescriptions</code> as part of a user 1421 * interface for setting or displaying the compression quality 1422 * level. See {@link #getCompressionQualityDescriptions 1423 * getCompressionQualityDescriptions} for more information. 1424 * 1425 * <p> If no descriptions are available, <code>null</code> is 1426 * returned. If <code>null</code> is returned from 1427 * <code>getCompressionQualityDescriptions</code>, this method 1428 * must also return <code>null</code>. 1429 * 1430 * <p> If there are multiple compression types but none has been set, 1431 * an <code>IllegalStateException</code> is thrown. 1432 * 1433 * <p> The default implementation checks that compression is 1434 * supported and that the compression mode is 1435 * <code>MODE_EXPLICIT</code>. If so, if 1436 * <code>getCompressionTypes()</code> is <code>null</code> or 1437 * <code>getCompressionType()</code> is non-<code>null</code>, it 1438 * returns <code>null</code>. 1439 * 1440 * @return an array of <code>float</code>s indicating the 1441 * boundaries between the compression quality levels as described 1442 * by the <code>String</code>s from 1443 * <code>getCompressionQualityDescriptions</code>. 1444 * 1445 * @exception UnsupportedOperationException if the writer does not 1446 * support compression. 1447 * @exception IllegalStateException if the compression mode is not 1448 * <code>MODE_EXPLICIT</code>. 1449 * @exception IllegalStateException if the set of legal 1450 * compression types is non-<code>null</code> and the current 1451 * compression type is <code>null</code>. 1452 * 1453 * @see #getCompressionQualityDescriptions 1454 */ 1455 public float[] getCompressionQualityValues() { 1456 if (!canWriteCompressed()) { 1457 throw new UnsupportedOperationException( 1458 "Compression not supported."); 1459 } 1460 if (getCompressionMode() != MODE_EXPLICIT) { 1461 throw new IllegalStateException 1462 ("Compression mode not MODE_EXPLICIT!"); 1463 } 1464 if ((getCompressionTypes() != null) && 1465 (getCompressionType() == null)) { 1466 throw new IllegalStateException("No compression type set!"); 1467 } 1468 return null; 1469 } 1470 }