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