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