1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /** 18 * @author Rustem V. Rafikov 19 * @version $Revision: 1.3 $ 20 */ 21 22 package javax.imageio; 23 24 import java.util.Locale; 25 import java.awt.*; 26 27 /** 28 * The ImageWriteParam class provides information to an ImageWriter about how an 29 * image is to be encoded. 30 * 31 * @since Android 1.0 32 */ 33 public class ImageWriteParam extends IIOParam { 34 35 /** 36 * The Constant MODE_DISABLED indicates that stream is not tiled, 37 * progressive, or compressed. 38 */ 39 public static final int MODE_DISABLED = 0; 40 41 /** 42 * The Constant MODE_DEFAULT indicates that the stream will be tiled, 43 * progressive, or compressed according to the plug-in's default. 44 */ 45 public static final int MODE_DEFAULT = 1; 46 47 /** 48 * The Constant MODE_EXPLICIT indicates that the stream will be tiled, 49 * progressive, or compressed according to current settings which are 50 * defined by set methods. 51 */ 52 public static final int MODE_EXPLICIT = 2; 53 54 /** 55 * The Constant MODE_COPY_FROM_METADATA indicates that the stream will be 56 * tiled, progressive, or compressed according to stream or image metadata. 57 */ 58 public static final int MODE_COPY_FROM_METADATA = 3; 59 60 /** 61 * Whether the ImageWriter can write tiles. 62 */ 63 protected boolean canWriteTiles = false; 64 65 /** 66 * The tiling mode. 67 */ 68 protected int tilingMode = MODE_COPY_FROM_METADATA; 69 70 /** 71 * The preferred tile sizes. 72 */ 73 protected Dimension[] preferredTileSizes = null; 74 75 /** 76 * The tiling set. 77 */ 78 protected boolean tilingSet = false; 79 80 /** 81 * The tile width. 82 */ 83 protected int tileWidth = 0; 84 85 /** 86 * The tile height. 87 */ 88 protected int tileHeight = 0; 89 90 /** 91 * Whether the ImageWriter can offset tiles. 92 */ 93 protected boolean canOffsetTiles = false; 94 95 /** 96 * The tile grid x offset. 97 */ 98 protected int tileGridXOffset = 0; 99 100 /** 101 * The tile grid y offset. 102 */ 103 protected int tileGridYOffset = 0; 104 105 /** 106 * Whether the ImageWriter can write in progressive mode. 107 */ 108 protected boolean canWriteProgressive = false; 109 110 /** 111 * The progressive mode. 112 */ 113 protected int progressiveMode = MODE_COPY_FROM_METADATA; 114 115 /** 116 * Whether the ImageWriter can write in compressed mode. 117 */ 118 protected boolean canWriteCompressed = false; 119 120 /** 121 * The compression mode. 122 */ 123 protected int compressionMode = MODE_COPY_FROM_METADATA; 124 125 /** 126 * The compression types. 127 */ 128 protected String[] compressionTypes = null; 129 130 /** 131 * The compression type. 132 */ 133 protected String compressionType = null; 134 135 /** 136 * The compression quality. 137 */ 138 protected float compressionQuality = 1.0f; 139 140 /** 141 * The locale. 142 */ 143 protected Locale locale = null; 144 145 /** 146 * Instantiates a new ImageWriteParam. 147 */ 148 protected ImageWriteParam() { 149 } 150 151 /** 152 * Instantiates a new ImageWriteParam with the specified Locale. 153 * 154 * @param locale 155 * the Locale. 156 */ 157 public ImageWriteParam(Locale locale) { 158 this.locale = locale; 159 160 } 161 162 /** 163 * Gets the mode for writing the stream in a progressive sequence. 164 * 165 * @return the current progressive mode. 166 */ 167 public int getProgressiveMode() { 168 if (canWriteProgressive()) { 169 return progressiveMode; 170 } 171 throw new UnsupportedOperationException("progressive mode is not supported"); 172 } 173 174 /** 175 * Returns true if images can be written using increasing quality passes by 176 * progressive. 177 * 178 * @return true if images can be written using increasing quality passes by 179 * progressive, false otherwise. 180 */ 181 public boolean canWriteProgressive() { 182 return canWriteProgressive; 183 } 184 185 /** 186 * Sets the progressive mode which defines whether the stream contains a 187 * progressive sequence of increasing quality during writing. The 188 * progressive mode should be one of the following values: MODE_DISABLED, 189 * MODE_DEFAULT, or MODE_COPY_FROM_METADATA. 190 * 191 * @param mode 192 * the new progressive mode. 193 */ 194 public void setProgressiveMode(int mode) { 195 if (canWriteProgressive()) { 196 if (mode < MODE_DISABLED || mode > MODE_COPY_FROM_METADATA || mode == MODE_EXPLICIT) { 197 throw new IllegalArgumentException("mode is not supported"); 198 } 199 this.progressiveMode = mode; 200 } 201 throw new UnsupportedOperationException("progressive mode is not supported"); 202 } 203 204 /** 205 * Returns true if the writer can use tiles with non zero grid offsets while 206 * writing. 207 * 208 * @return true, if the writer can use tiles with non zero grid offsets 209 * while writing, false otherwise. 210 */ 211 public boolean canOffsetTiles() { 212 return canOffsetTiles; 213 } 214 215 /** 216 * Returns true if this writer can write images with compression. 217 * 218 * @return true, if this writer can write images with compression, false 219 * otherwise. 220 */ 221 public boolean canWriteCompressed() { 222 return canWriteCompressed; 223 } 224 225 /** 226 * Returns true if the writer can write tiles. 227 * 228 * @return true, if the writer can write tiles, false otherwise. 229 */ 230 public boolean canWriteTiles() { 231 return canWriteTiles; 232 } 233 234 /** 235 * Check write compressed. 236 */ 237 private final void checkWriteCompressed() { 238 if (!canWriteCompressed()) { 239 throw new UnsupportedOperationException("Compression not supported."); 240 } 241 } 242 243 /** 244 * Check compression mode. 245 */ 246 private final void checkCompressionMode() { 247 if (getCompressionMode() != MODE_EXPLICIT) { 248 throw new IllegalStateException("Compression mode not MODE_EXPLICIT!"); 249 } 250 } 251 252 /** 253 * Check compression type. 254 */ 255 private final void checkCompressionType() { 256 if (getCompressionTypes() != null && getCompressionType() == null) { 257 throw new IllegalStateException("No compression type set!"); 258 } 259 } 260 261 /** 262 * Gets the compression mode. 263 * 264 * @return the compression mode if it's supported. 265 */ 266 public int getCompressionMode() { 267 checkWriteCompressed(); 268 return compressionMode; 269 } 270 271 /** 272 * Gets the an array of supported compression types. 273 * 274 * @return the an array of supported compression types. 275 */ 276 public String[] getCompressionTypes() { 277 checkWriteCompressed(); 278 if (compressionTypes != null) { 279 return compressionTypes.clone(); 280 } 281 return null; 282 } 283 284 /** 285 * Gets the current compression type, or returns null. 286 * 287 * @return the current compression type, or returns null if it is not set. 288 */ 289 public String getCompressionType() { 290 checkWriteCompressed(); 291 checkCompressionMode(); 292 return compressionType; 293 } 294 295 /** 296 * Gets a bit rate which represents an estimate of the number of bits of 297 * output data for each bit of input image data with the specified quality. 298 * 299 * @param quality 300 * the quality. 301 * @return an estimate of the bit rate, or -1.0F if there is no estimate. 302 */ 303 public float getBitRate(float quality) { 304 checkWriteCompressed(); 305 checkCompressionMode(); 306 checkCompressionType(); 307 if (quality < 0 || quality > 1) { 308 throw new IllegalArgumentException("Quality out-of-bounds!"); 309 } 310 return -1.0f; 311 } 312 313 /** 314 * Gets the compression quality. 315 * 316 * @return the compression quality. 317 */ 318 public float getCompressionQuality() { 319 checkWriteCompressed(); 320 checkCompressionMode(); 321 checkCompressionType(); 322 return compressionQuality; 323 } 324 325 /** 326 * Gets the array of compression quality descriptions. 327 * 328 * @return the string array of compression quality descriptions. 329 */ 330 public String[] getCompressionQualityDescriptions() { 331 checkWriteCompressed(); 332 checkCompressionMode(); 333 checkCompressionType(); 334 return null; 335 } 336 337 /** 338 * Gets an array of floats which describes compression quality levels. 339 * 340 * @return the array of compression quality values. 341 */ 342 public float[] getCompressionQualityValues() { 343 checkWriteCompressed(); 344 checkCompressionMode(); 345 checkCompressionType(); 346 return null; 347 } 348 349 /** 350 * Gets the locale of this ImageWriteParam. 351 * 352 * @return the locale of this ImageWriteParam. 353 */ 354 public Locale getLocale() { 355 return locale; 356 } 357 358 /** 359 * Gets the current compression type using the current Locale. 360 * 361 * @return the current compression type using the current Locale. 362 */ 363 public String getLocalizedCompressionTypeName() { 364 checkWriteCompressed(); 365 checkCompressionMode(); 366 367 String compressionType = getCompressionType(); 368 if (compressionType == null) { 369 throw new IllegalStateException("No compression type set!"); 370 } 371 return compressionType; 372 373 } 374 375 /** 376 * Check tiling. 377 */ 378 private final void checkTiling() { 379 if (!canWriteTiles()) { 380 throw new UnsupportedOperationException("Tiling not supported!"); 381 } 382 } 383 384 /** 385 * Check tiling mode. 386 */ 387 private final void checkTilingMode() { 388 if (getTilingMode() != MODE_EXPLICIT) { 389 throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!"); 390 } 391 } 392 393 /** 394 * Check tiling params. 395 */ 396 private final void checkTilingParams() { 397 if (!tilingSet) { 398 throw new IllegalStateException("Tiling parameters not set!"); 399 } 400 } 401 402 /** 403 * Gets the tiling mode if tiling is supported. 404 * 405 * @return the tiling mode if tiling is supported. 406 */ 407 public int getTilingMode() { 408 checkTiling(); 409 return tilingMode; 410 } 411 412 /** 413 * Gets an array of Dimensions giving the sizes of the tiles as they are 414 * encoded in the output file or stream. 415 * 416 * @return the preferred tile sizes. 417 */ 418 public Dimension[] getPreferredTileSizes() { 419 checkTiling(); 420 if (preferredTileSizes == null) { 421 return null; 422 } 423 424 Dimension[] retval = new Dimension[preferredTileSizes.length]; 425 for (int i = 0; i < preferredTileSizes.length; i++) { 426 retval[i] = new Dimension(retval[i]); 427 } 428 return retval; 429 } 430 431 /** 432 * Gets the tile grid X offset for encoding. 433 * 434 * @return the tile grid X offset for encoding. 435 */ 436 public int getTileGridXOffset() { 437 checkTiling(); 438 checkTilingMode(); 439 checkTilingParams(); 440 return tileGridXOffset; 441 } 442 443 /** 444 * Gets the tile grid Y offset for encoding. 445 * 446 * @return the tile grid Y offset for encoding. 447 */ 448 public int getTileGridYOffset() { 449 checkTiling(); 450 checkTilingMode(); 451 checkTilingParams(); 452 return tileGridYOffset; 453 } 454 455 /** 456 * Gets the tile height in an image as it is written to the output stream. 457 * 458 * @return the tile height in an image as it is written to the output 459 * stream. 460 */ 461 public int getTileHeight() { 462 checkTiling(); 463 checkTilingMode(); 464 checkTilingParams(); 465 return tileHeight; 466 } 467 468 /** 469 * Gets the tile width in an image as it is written to the output stream. 470 * 471 * @return the tile width in an image as it is written to the output stream. 472 */ 473 public int getTileWidth() { 474 checkTiling(); 475 checkTilingMode(); 476 checkTilingParams(); 477 return tileWidth; 478 } 479 480 /** 481 * Checks if the current compression type has lossless compression or not. 482 * 483 * @return true, if the current compression type has lossless compression, 484 * false otherwise. 485 */ 486 public boolean isCompressionLossless() { 487 checkWriteCompressed(); 488 checkCompressionMode(); 489 checkCompressionType(); 490 return true; 491 } 492 493 /** 494 * Removes current compression type. 495 */ 496 public void unsetCompression() { 497 checkWriteCompressed(); 498 checkCompressionMode(); 499 compressionType = null; 500 compressionQuality = 1; 501 } 502 503 /** 504 * Sets the compression mode to the specified value. The specified mode can 505 * be one of the predefined constants: MODE_DEFAULT, MODE_DISABLED, 506 * MODE_EXPLICIT, or MODE_COPY_FROM_METADATA. 507 * 508 * @param mode 509 * the new compression mode to be set. 510 */ 511 public void setCompressionMode(int mode) { 512 checkWriteCompressed(); 513 switch (mode) { 514 case MODE_EXPLICIT: { 515 compressionMode = mode; 516 unsetCompression(); 517 break; 518 } 519 case MODE_COPY_FROM_METADATA: 520 case MODE_DISABLED: 521 case MODE_DEFAULT: { 522 compressionMode = mode; 523 break; 524 } 525 default: { 526 throw new IllegalArgumentException("Illegal value for mode!"); 527 } 528 } 529 } 530 531 /** 532 * Sets the compression quality. The value should be between 0 and 1. 533 * 534 * @param quality 535 * the new compression quality, float value between 0 and 1. 536 */ 537 public void setCompressionQuality(float quality) { 538 checkWriteCompressed(); 539 checkCompressionMode(); 540 checkCompressionType(); 541 if (quality < 0 || quality > 1) { 542 throw new IllegalArgumentException("Quality out-of-bounds!"); 543 } 544 compressionQuality = quality; 545 } 546 547 /** 548 * Sets the compression type. The specified string should be one of the 549 * values returned by getCompressionTypes method. 550 * 551 * @param compressionType 552 * the new compression type. 553 */ 554 public void setCompressionType(String compressionType) { 555 checkWriteCompressed(); 556 checkCompressionMode(); 557 558 if (compressionType == null) { // Don't check anything 559 this.compressionType = null; 560 } else { 561 String[] compressionTypes = getCompressionTypes(); 562 if (compressionTypes == null) { 563 throw new UnsupportedOperationException("No settable compression types"); 564 } 565 566 for (int i = 0; i < compressionTypes.length; i++) { 567 if (compressionTypes[i].equals(compressionType)) { 568 this.compressionType = compressionType; 569 return; 570 } 571 } 572 573 // Compression type is not in the list. 574 throw new IllegalArgumentException("Unknown compression type!"); 575 } 576 } 577 578 /** 579 * Sets the instruction that tiling should be performed for the image in the 580 * output stream with the specified parameters. 581 * 582 * @param tileWidth 583 * the tile's width. 584 * @param tileHeight 585 * the tile's height. 586 * @param tileGridXOffset 587 * the tile grid's x offset. 588 * @param tileGridYOffset 589 * the tile grid's y offset. 590 */ 591 public void setTiling(int tileWidth, int tileHeight, int tileGridXOffset, int tileGridYOffset) { 592 checkTiling(); 593 checkTilingMode(); 594 595 if (!canOffsetTiles() && (tileGridXOffset != 0 || tileGridYOffset != 0)) { 596 throw new UnsupportedOperationException("Can't offset tiles!"); 597 } 598 599 if (tileWidth <= 0 || tileHeight <= 0) { 600 throw new IllegalArgumentException("tile dimensions are non-positive!"); 601 } 602 603 Dimension preferredTileSizes[] = getPreferredTileSizes(); 604 if (preferredTileSizes != null) { 605 for (int i = 0; i < preferredTileSizes.length; i += 2) { 606 Dimension minSize = preferredTileSizes[i]; 607 Dimension maxSize = preferredTileSizes[i + 1]; 608 if (tileWidth < minSize.width || tileWidth > maxSize.width 609 || tileHeight < minSize.height || tileHeight > maxSize.height) { 610 throw new IllegalArgumentException("Illegal tile size!"); 611 } 612 } 613 } 614 615 tilingSet = true; 616 this.tileWidth = tileWidth; 617 this.tileHeight = tileHeight; 618 this.tileGridXOffset = tileGridXOffset; 619 this.tileGridYOffset = tileGridYOffset; 620 } 621 622 /** 623 * Clears all tiling settings. 624 */ 625 public void unsetTiling() { 626 checkTiling(); 627 checkTilingMode(); 628 629 tilingSet = false; 630 tileWidth = 0; 631 tileHeight = 0; 632 tileGridXOffset = 0; 633 tileGridYOffset = 0; 634 } 635 636 /** 637 * Sets the tiling mode. The specified mode should be one of the following 638 * values: MODE_DISABLED, MODE_DEFAULT, MODE_EXPLICIT, or 639 * MODE_COPY_FROM_METADATA. 640 * 641 * @param mode 642 * the new tiling mode. 643 */ 644 public void setTilingMode(int mode) { 645 checkTiling(); 646 647 switch (mode) { 648 case MODE_EXPLICIT: { 649 tilingMode = mode; 650 unsetTiling(); 651 break; 652 } 653 case MODE_COPY_FROM_METADATA: 654 case MODE_DISABLED: 655 case MODE_DEFAULT: { 656 tilingMode = mode; 657 break; 658 } 659 default: { 660 throw new IllegalArgumentException("Illegal value for mode!"); 661 } 662 } 663 } 664 } 665