1. /*
  2. * @(#)ImageWriter.java 1.94 04/05/05
  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.Dimension;
  9. import java.awt.Rectangle;
  10. import java.awt.image.BufferedImage;
  11. import java.awt.image.RenderedImage;
  12. import java.awt.image.Raster;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.Locale;
  17. import java.util.MissingResourceException;
  18. import java.util.ResourceBundle;
  19. import javax.imageio.event.IIOWriteWarningListener;
  20. import javax.imageio.event.IIOWriteProgressListener;
  21. import javax.imageio.metadata.IIOMetadata;
  22. import javax.imageio.stream.ImageOutputStream;
  23. import javax.imageio.spi.ImageWriterSpi;
  24. /**
  25. * An abstract superclass for encoding and writing images. This class
  26. * must be subclassed by classes that write out images in the context
  27. * of the Java Image I/O framework.
  28. *
  29. * <p> <code>ImageWriter</code> objects are normally instantiated by
  30. * the service provider class for the specific format. Service
  31. * provider classes are registered with the <code>IIORegistry</code>,
  32. * which uses them for format recognition and presentation of
  33. * available format readers and writers.
  34. *
  35. * <p>
  36. *
  37. * @see ImageReader
  38. * @see ImageWriteParam
  39. * @see javax.imageio.spi.IIORegistry
  40. * @see javax.imageio.spi.ImageWriterSpi
  41. *
  42. * @version 0.5
  43. */
  44. public abstract class ImageWriter implements ImageTranscoder {
  45. /**
  46. * The <code>ImageWriterSpi</code> that instantiated this object,
  47. * or <code>null</code> if its identity is not known or none
  48. * exists. By default it is initialized to <code>null</code>.
  49. */
  50. protected ImageWriterSpi originatingProvider = null;
  51. /**
  52. * The <code>ImageOutputStream</code> or other <code>Object</code>
  53. * set by <code>setOutput</code> and retrieved by
  54. * <code>getOutput</code>. By default it is initialized to
  55. * <code>null</code>.
  56. */
  57. protected Object output = null;
  58. /**
  59. * An array of <code>Locale</code>s that may be used to localize
  60. * warning messages and compression setting values, or
  61. * <code>null</code> if localization is not supported. By default
  62. * it is initialized to <code>null</code>.
  63. */
  64. protected Locale[] availableLocales = null;
  65. /**
  66. * The current <code>Locale</code> to be used for localization, or
  67. * <code>null</code> if none has been set. By default it is
  68. * initialized to <code>null</code>.
  69. */
  70. protected Locale locale = null;
  71. /**
  72. * A <code>List</code> of currently registered
  73. * <code>IIOWriteWarningListener</code>s, initialized by default to
  74. * <code>null</code>, which is synonymous with an empty
  75. * <code>List</code>.
  76. */
  77. protected List<IIOWriteWarningListener> warningListeners = null;
  78. /**
  79. * A <code>List</code> of <code>Locale</code>s, one for each
  80. * element of <code>warningListeners</code>, initialized by default
  81. * <code>null</code>, which is synonymous with an empty
  82. * <code>List</code>.
  83. */
  84. protected List<Locale> warningLocales = null;
  85. /**
  86. * A <code>List</code> of currently registered
  87. * <code>IIOWriteProgressListener</code>s, initialized by default
  88. * <code>null</code>, which is synonymous with an empty
  89. * <code>List</code>.
  90. */
  91. protected List<IIOWriteProgressListener> progressListeners = null;
  92. /**
  93. * If <code>true</code>, the current write operation should be
  94. * aborted.
  95. */
  96. private boolean abortFlag = false;
  97. /**
  98. * Constructs an <code>ImageWriter</code> and sets its
  99. * <code>originatingProvider</code> instance variable to the
  100. * supplied value.
  101. *
  102. * <p> Subclasses that make use of extensions should provide a
  103. * constructor with signature <code>(ImageWriterSpi,
  104. * Object)</code> in order to retrieve the extension object. If
  105. * the extension object is unsuitable, an
  106. * <code>IllegalArgumentException</code> should be thrown.
  107. *
  108. * @param originatingProvider the <code>ImageWriterSpi</code> that
  109. * is constructing this object, or <code>null</code>.
  110. */
  111. protected ImageWriter(ImageWriterSpi originatingProvider) {
  112. this.originatingProvider = originatingProvider;
  113. }
  114. /**
  115. * Returns the <code>ImageWriterSpi</code> object that created
  116. * this <code>ImageWriter</code>, or <code>null</code> if this
  117. * object was not created through the <code>IIORegistry</code>.
  118. *
  119. * <p> The default implementation returns the value of the
  120. * <code>originatingProvider</code> instance variable.
  121. *
  122. * @return an <code>ImageWriterSpi</code>, or <code>null</code>.
  123. *
  124. * @see ImageWriterSpi
  125. */
  126. public ImageWriterSpi getOriginatingProvider() {
  127. return originatingProvider;
  128. }
  129. /**
  130. * Sets the destination to the given
  131. * <code>ImageOutputStream</code> or other <code>Object</code>.
  132. * The destination is assumed to be ready to accept data, and will
  133. * not be closed at the end of each write. This allows distributed
  134. * imaging applications to transmit a series of images over a
  135. * single network connection. If <code>output</code> is
  136. * <code>null</code>, any currently set output will be removed.
  137. *
  138. * <p> If <code>output</code> is an
  139. * <code>ImageOutputStream</code>, calls to the
  140. * <code>write</code>, <code>writeToSequence</code>, and
  141. * <code>prepareWriteEmpty</code>/<code>endWriteEmpty</code>
  142. * methods will preserve the existing contents of the stream.
  143. * Other write methods, such as <code>writeInsert</code>,
  144. * <code>replaceStreamMetadata</code>,
  145. * <code>replaceImageMetadata</code>, <code>replacePixels</code>,
  146. * <code>prepareInsertEmpty</code>/<code>endInsertEmpty</code>,
  147. * and <code>endWriteSequence</code>, require the full contents
  148. * of the stream to be readable and writable, and may alter any
  149. * portion of the stream.
  150. *
  151. * <p> Use of a general <code>Object</code> other than an
  152. * <code>ImageOutputStream</code> is intended for writers that
  153. * interact directly with an output device or imaging protocol.
  154. * The set of legal classes is advertised by the writer's service
  155. * provider's <code>getOutputTypes</code> method; most writers
  156. * will return a single-element array containing only
  157. * <code>ImageOutputStream.class</code> to indicate that they
  158. * accept only an <code>ImageOutputStream</code>.
  159. *
  160. * <p> The default implementation sets the <code>output</code>
  161. * instance variable to the value of <code>output</code> after
  162. * checking <code>output</code> against the set of classes
  163. * advertised by the originating provider, if there is one.
  164. *
  165. * @param output the <code>ImageOutputStream</code> or other
  166. * <code>Object</code> to use for future writing.
  167. *
  168. * @exception IllegalArgumentException if <code>output</code> is
  169. * not an instance of one of the classes returned by the
  170. * originating service provider's <code>getOutputTypes</code>
  171. * method.
  172. *
  173. * @see #getOutput
  174. */
  175. public void setOutput(Object output) {
  176. if (output != null) {
  177. ImageWriterSpi provider = getOriginatingProvider();
  178. if (provider != null) {
  179. Class[] classes = provider.getOutputTypes();
  180. boolean found = false;
  181. for (int i = 0; i < classes.length; i++) {
  182. if (classes[i].isInstance(output)) {
  183. found = true;
  184. break;
  185. }
  186. }
  187. if (!found) {
  188. throw new IllegalArgumentException("Illegal output type!");
  189. }
  190. }
  191. }
  192. this.output = output;
  193. }
  194. /**
  195. * Returns the <code>ImageOutputStream</code> or other
  196. * <code>Object</code> set by the most recent call to the
  197. * <code>setOutput</code> method. If no destination has been
  198. * set, <code>null</code> is returned.
  199. *
  200. * <p> The default implementation returns the value of the
  201. * <code>output</code> instance variable.
  202. *
  203. * @return the <code>Object</code> that was specified using
  204. * <code>setOutput</code>, or <code>null</code>.
  205. *
  206. * @see #setOutput
  207. */
  208. public Object getOutput() {
  209. return output;
  210. }
  211. // Localization
  212. /**
  213. * Returns an array of <code>Locale</code>s that may be used to
  214. * localize warning listeners and compression settings. A return
  215. * value of <code>null</code> indicates that localization is not
  216. * supported.
  217. *
  218. * <p> The default implementation returns a clone of the
  219. * <code>availableLocales</code> instance variable if it is
  220. * non-<code>null</code>, or else returns <code>null</code>.
  221. *
  222. * @return an array of <code>Locale</code>s that may be used as
  223. * arguments to <code>setLocale</code>, or <code>null</code>.
  224. */
  225. public Locale[] getAvailableLocales() {
  226. return (availableLocales == null) ?
  227. null : (Locale[])availableLocales.clone();
  228. }
  229. /**
  230. * Sets the current <code>Locale</code> of this
  231. * <code>ImageWriter</code> to the given value. A value of
  232. * <code>null</code> removes any previous setting, and indicates
  233. * that the writer should localize as it sees fit.
  234. *
  235. * <p> The default implementation checks <code>locale</code>
  236. * against the values returned by
  237. * <code>getAvailableLocales</code>, and sets the
  238. * <code>locale</code> instance variable if it is found. If
  239. * <code>locale</code> is <code>null</code>, the instance variable
  240. * is set to <code>null</code> without any checking.
  241. *
  242. * @param locale the desired <code>Locale</code>, or
  243. * <code>null</code>.
  244. *
  245. * @exception IllegalArgumentException if <code>locale</code> is
  246. * non-<code>null</code> but is not one of the values returned by
  247. * <code>getAvailableLocales</code>.
  248. *
  249. * @see #getLocale
  250. */
  251. public void setLocale(Locale locale) {
  252. if (locale != null) {
  253. Locale[] locales = getAvailableLocales();
  254. boolean found = false;
  255. if (locales != null) {
  256. for (int i = 0; i < locales.length; i++) {
  257. if (locale.equals(locales[i])) {
  258. found = true;
  259. break;
  260. }
  261. }
  262. }
  263. if (!found) {
  264. throw new IllegalArgumentException("Invalid locale!");
  265. }
  266. }
  267. this.locale = locale;
  268. }
  269. /**
  270. * Returns the currently set <code>Locale</code>, or
  271. * <code>null</code> if none has been set.
  272. *
  273. * <p> The default implementation returns the value of the
  274. * <code>locale</code> instance variable.
  275. *
  276. * @return the current <code>Locale</code>, or <code>null</code>.
  277. *
  278. * @see #setLocale
  279. */
  280. public Locale getLocale() {
  281. return locale;
  282. }
  283. // Write params
  284. /**
  285. * Returns a new <code>ImageWriteParam</code> object of the
  286. * appropriate type for this file format containing default
  287. * values, that is, those values that would be used
  288. * if no <code>ImageWriteParam</code> object were specified. This
  289. * is useful as a starting point for tweaking just a few parameters
  290. * and otherwise leaving the default settings alone.
  291. *
  292. * <p> The default implementation constructs and returns a new
  293. * <code>ImageWriteParam</code> object that does not allow tiling,
  294. * progressive encoding, or compression, and that will be
  295. * localized for the current <code>Locale</code> (<i>i.e.</i>,
  296. * what you would get by calling <code>new
  297. * ImageWriteParam(getLocale())</code>.
  298. *
  299. * <p> Individual plug-ins may return an instance of
  300. * <code>ImageWriteParam</code> with additional optional features
  301. * enabled, or they may return an instance of a plug-in specific
  302. * subclass of <code>ImageWriteParam</code>.
  303. *
  304. * @return a new <code>ImageWriteParam</code> object containing
  305. * default values.
  306. */
  307. public ImageWriteParam getDefaultWriteParam() {
  308. return new ImageWriteParam(getLocale());
  309. }
  310. // Metadata
  311. /**
  312. * Returns an <code>IIOMetadata</code> object containing default
  313. * values for encoding a stream of images. The contents of the
  314. * object may be manipulated using either the XML tree structure
  315. * returned by the <code>IIOMetadata.getAsTree</code> method, an
  316. * <code>IIOMetadataController</code> object, or via plug-in
  317. * specific interfaces, and the resulting data supplied to one of
  318. * the <code>write</code> methods that take a stream metadata
  319. * parameter.
  320. *
  321. * <p> An optional <code>ImageWriteParam</code> may be supplied
  322. * for cases where it may affect the structure of the stream
  323. * metadata.
  324. *
  325. * <p> If the supplied <code>ImageWriteParam</code> contains
  326. * optional setting values not supported by this writer (<i>e.g.</i>
  327. * progressive encoding or any format-specific settings), they
  328. * will be ignored.
  329. *
  330. * <p> Writers that do not make use of stream metadata
  331. * (<i>e.g.</i>, writers for single-image formats) should return
  332. * <code>null</code>.
  333. *
  334. * @param param an <code>ImageWriteParam</code> that will be used to
  335. * encode the image, or <code>null</code>.
  336. *
  337. * @return an <code>IIOMetadata</code> object.
  338. */
  339. public abstract IIOMetadata
  340. getDefaultStreamMetadata(ImageWriteParam param);
  341. /**
  342. * Returns an <code>IIOMetadata</code> object containing default
  343. * values for encoding an image of the given type. The contents
  344. * of the object may be manipulated using either the XML tree
  345. * structure returned by the <code>IIOMetadata.getAsTree</code>
  346. * method, an <code>IIOMetadataController</code> object, or via
  347. * plug-in specific interfaces, and the resulting data supplied to
  348. * one of the <code>write</code> methods that take a stream
  349. * metadata parameter.
  350. *
  351. * <p> An optional <code>ImageWriteParam</code> may be supplied
  352. * for cases where it may affect the structure of the image
  353. * metadata.
  354. *
  355. * <p> If the supplied <code>ImageWriteParam</code> contains
  356. * optional setting values not supported by this writer (<i>e.g.</i>
  357. * progressive encoding or any format-specific settings), they
  358. * will be ignored.
  359. *
  360. * @param imageType an <code>ImageTypeSpecifier</code> indicating the
  361. * format of the image to be written later.
  362. * @param param an <code>ImageWriteParam</code> that will be used to
  363. * encode the image, or <code>null</code>.
  364. *
  365. * @return an <code>IIOMetadata</code> object.
  366. */
  367. public abstract IIOMetadata
  368. getDefaultImageMetadata(ImageTypeSpecifier imageType,
  369. ImageWriteParam param);
  370. // comment inherited
  371. public abstract IIOMetadata convertStreamMetadata(IIOMetadata inData,
  372. ImageWriteParam param);
  373. // comment inherited
  374. public abstract IIOMetadata
  375. convertImageMetadata(IIOMetadata inData,
  376. ImageTypeSpecifier imageType,
  377. ImageWriteParam param);
  378. // Thumbnails
  379. /**
  380. * Returns the number of thumbnails suported by the format being
  381. * written, given the image type and any additional write
  382. * parameters and metadata objects that will be used during
  383. * encoding. A return value of <code>-1</code> indicates that
  384. * insufficient information is available.
  385. *
  386. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  387. * for cases where it may affect thumbnail handling.
  388. *
  389. * <p> If the supplied <code>ImageWriteParam</code> contains
  390. * optional setting values not supported by this writer (<i>e.g.</i>
  391. * progressive encoding or any format-specific settings), they
  392. * will be ignored.
  393. *
  394. * <p> The default implementation returns 0.
  395. *
  396. * @param imageType an <code>ImageTypeSpecifier</code> indicating
  397. * the type of image to be written, or <code>null</code>.
  398. * @param param the <code>ImageWriteParam</code> that will be used for
  399. * writing, or <code>null</code>.
  400. * @param streamMetadata an <code>IIOMetadata</code> object that will
  401. * be used for writing, or <code>null</code>.
  402. * @param imageMetadata an <code>IIOMetadata</code> object that will
  403. * be used for writing, or <code>null</code>.
  404. *
  405. * @return the number of thumbnails that may be written given the
  406. * supplied parameters, or <code>-1</code> if insufficient
  407. * information is available.
  408. */
  409. public int getNumThumbnailsSupported(ImageTypeSpecifier imageType,
  410. ImageWriteParam param,
  411. IIOMetadata streamMetadata,
  412. IIOMetadata imageMetadata) {
  413. return 0;
  414. }
  415. /**
  416. * Returns an array of <code>Dimension</code>s indicating the
  417. * legal size ranges for thumbnail images as they will be encoded
  418. * in the output file or stream. This information is merely
  419. * advisory; the writer will resize any supplied thumbnails as
  420. * necessary.
  421. *
  422. * <p> The information is returned as a set of pairs; the first
  423. * element of a pair contains an (inclusive) minimum width and
  424. * height, and the second element contains an (inclusive) maximum
  425. * width and height. Together, each pair defines a valid range of
  426. * sizes. To specify a fixed size, the same width and height will
  427. * appear for both elements. A return value of <code>null</code>
  428. * indicates that the size is arbitrary or unknown.
  429. *
  430. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  431. * for cases where it may affect thumbnail handling.
  432. *
  433. * <p> If the supplied <code>ImageWriteParam</code> contains
  434. * optional setting values not supported by this writer (<i>e.g.</i>
  435. * progressive encoding or any format-specific settings), they
  436. * will be ignored.
  437. *
  438. * <p> The default implementation returns <code>null</code>.
  439. *
  440. * @param imageType an <code>ImageTypeSpecifier</code> indicating the
  441. * type of image to be written, or <code>null</code>.
  442. * @param param the <code>ImageWriteParam</code> that will be used for
  443. * writing, or <code>null</code>.
  444. * @param streamMetadata an <code>IIOMetadata</code> object that will
  445. * be used for writing, or <code>null</code>.
  446. * @param imageMetadata an <code>IIOMetadata</code> object that will
  447. * be used for writing, or <code>null</code>.
  448. *
  449. * @return an array of <code>Dimension</code>s with an even length
  450. * of at least two, or <code>null</code>.
  451. */
  452. public Dimension[] getPreferredThumbnailSizes(ImageTypeSpecifier imageType,
  453. ImageWriteParam param,
  454. IIOMetadata streamMetadata,
  455. IIOMetadata imageMetadata) {
  456. return null;
  457. }
  458. /**
  459. * Returns <code>true</code> if the methods that take an
  460. * <code>IIOImage</code> parameter are capable of dealing with a
  461. * <code>Raster</code> (as opposed to <code>RenderedImage</code>)
  462. * source image. If this method returns <code>false</code>, then
  463. * those methods will throw an
  464. * <code>UnsupportedOperationException</code> if supplied with an
  465. * <code>IIOImage</code> containing a <code>Raster</code>.
  466. *
  467. * <p> The default implementation returns <code>false</code>.
  468. *
  469. * @return <code>true</code> if <code>Raster</code> sources are
  470. * supported.
  471. */
  472. public boolean canWriteRasters() {
  473. return false;
  474. }
  475. /**
  476. * Appends a complete image stream containing a single image and
  477. * associated stream and image metadata and thumbnails to the
  478. * output. Any necessary header information is included. If the
  479. * output is an <code>ImageOutputStream</code>, its existing
  480. * contents prior to the current seek position are not affected,
  481. * and need not be readable or writable.
  482. *
  483. * <p> The output must have been set beforehand using the
  484. * <code>setOutput</code> method.
  485. *
  486. * <p> Stream metadata may optionally be supplied; if it is
  487. * <code>null</code>, default stream metadata will be used.
  488. *
  489. * <p> If <code>canWriteRasters</code> returns <code>true</code>,
  490. * the <code>IIOImage</code> may contain a <code>Raster</code>
  491. * source. Otherwise, it must contain a
  492. * <code>RenderedImage</code> source.
  493. *
  494. * <p> The supplied thumbnails will be resized if needed, and any
  495. * thumbnails in excess of the supported number will be ignored.
  496. * If the format requires additional thumbnails that are not
  497. * provided, the writer should generate them internally.
  498. *
  499. * <p> An <code>ImageWriteParam</code> may
  500. * optionally be supplied to control the writing process. If
  501. * <code>param</code> is <code>null</code>, a default write param
  502. * will be used.
  503. *
  504. * <p> If the supplied <code>ImageWriteParam</code> contains
  505. * optional setting values not supported by this writer (<i>e.g.</i>
  506. * progressive encoding or any format-specific settings), they
  507. * will be ignored.
  508. *
  509. * @param streamMetadata an <code>IIOMetadata</code> object representing
  510. * stream metadata, or <code>null</code> to use default values.
  511. * @param image an <code>IIOImage</code> object containing an
  512. * image, thumbnails, and metadata to be written.
  513. * @param param an <code>ImageWriteParam</code>, or
  514. * <code>null</code> to use a default
  515. * <code>ImageWriteParam</code>.
  516. *
  517. * @exception IllegalStateException if the output has not
  518. * been set.
  519. * @exception UnsupportedOperationException if <code>image</code>
  520. * contains a <code>Raster</code> and <code>canWriteRasters</code>
  521. * returns <code>false</code>.
  522. * @exception IllegalArgumentException if <code>image</code> is
  523. * <code>null</code>.
  524. * @exception IOException if an error occurs during writing.
  525. */
  526. public abstract void write(IIOMetadata streamMetadata,
  527. IIOImage image,
  528. ImageWriteParam param) throws IOException;
  529. /**
  530. * Appends a complete image stream containing a single image with
  531. * default metadata and thumbnails to the output. This method is
  532. * a shorthand for <code>write(null, image, null)</code>.
  533. *
  534. * @param image an <code>IIOImage</code> object containing an
  535. * image, thumbnails, and metadata to be written.
  536. *
  537. * @exception IllegalStateException if the output has not
  538. * been set.
  539. * @exception IllegalArgumentException if <code>image</code> is
  540. * <code>null</code>.
  541. * @exception UnsupportedOperationException if <code>image</code>
  542. * contains a <code>Raster</code> and <code>canWriteRasters</code>
  543. * returns <code>false</code>.
  544. * @exception IOException if an error occurs during writing.
  545. */
  546. public void write(IIOImage image) throws IOException {
  547. write(null, image, null);
  548. }
  549. /**
  550. * Appends a complete image stream consisting of a single image
  551. * with default metadata and thumbnails to the output. This
  552. * method is a shorthand for <code>write(null, new IIOImage(image,
  553. * null, null), null)</code>.
  554. *
  555. * @param image a <code>RenderedImage</code> to be written.
  556. *
  557. * @exception IllegalStateException if the output has not
  558. * been set.
  559. * @exception IllegalArgumentException if <code>image</code> is
  560. * <code>null</code>.
  561. * @exception IOException if an error occurs during writing.
  562. */
  563. public void write(RenderedImage image) throws IOException {
  564. write(null, new IIOImage(image, null, null), null);
  565. }
  566. // Check that the output has been set, then throw an
  567. // UnsupportedOperationException.
  568. private void unsupported() {
  569. if (getOutput() == null) {
  570. throw new IllegalStateException("getOutput() == null!");
  571. }
  572. throw new UnsupportedOperationException("Unsupported write variant!");
  573. }
  574. // Sequence writes
  575. /**
  576. * Returns <code>true</code> if the writer is able to append an
  577. * image to an image stream that already contains header
  578. * information and possibly prior images.
  579. *
  580. * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  581. * <code>writeToSequence</code> and <code>endWriteSequence</code>
  582. * will throw an <code>UnsupportedOperationException</code>.
  583. *
  584. * <p> The default implementation returns <code>false</code>.
  585. *
  586. * @return <code>true</code> if images may be appended sequentially.
  587. */
  588. public boolean canWriteSequence() {
  589. return false;
  590. }
  591. /**
  592. * Prepares a stream to accept a series of subsequent
  593. * <code>writeToSequence</code> calls, using the provided stream
  594. * metadata object. The metadata will be written to the stream if
  595. * it should precede the image data. If the argument is <code>null</code>,
  596. * default stream metadata is used.
  597. *
  598. * <p> If the output is an <code>ImageOutputStream</code>, the existing
  599. * contents of the output prior to the current seek position are
  600. * flushed, and need not be readable or writable. If the format
  601. * requires that <code>endWriteSequence</code> be able to rewind to
  602. * patch up the header information, such as for a sequence of images
  603. * in a single TIFF file, then the metadata written by this method
  604. * must remain in a writable portion of the stream. Other formats
  605. * may flush the stream after this method and after each image.
  606. *
  607. * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  608. * this method will throw an
  609. * <code>UnsupportedOperationException</code>.
  610. *
  611. * <p> The output must have been set beforehand using either
  612. * the <code>setOutput</code> method.
  613. *
  614. * <p> The default implementation throws an
  615. * <code>IllegalStateException</code> if the output is
  616. * <code>null</code>, and otherwise throws an
  617. * <code>UnsupportedOperationException</code>.
  618. *
  619. * @param streamMetadata A stream metadata object, or <code>null</code>.
  620. *
  621. * @exception IllegalStateException if the output has not
  622. * been set.
  623. * @exception UnsupportedOperationException if
  624. * <code>canWriteSequence</code> returns <code>false</code>.
  625. * @exception IOException if an error occurs writing the stream
  626. * metadata.
  627. */
  628. public void prepareWriteSequence(IIOMetadata streamMetadata)
  629. throws IOException {
  630. unsupported();
  631. }
  632. /**
  633. * Appends a single image and possibly associated metadata and
  634. * thumbnails, to the output. If the output is an
  635. * <code>ImageOutputStream</code>, the existing contents of the
  636. * output prior to the current seek position may be flushed, and
  637. * need not be readable or writable, unless the plug-in needs to
  638. * be able to patch up the header information when
  639. * <code>endWriteSequence</code> is called (<italic>e.g.</italic> TIFF).
  640. *
  641. * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  642. * this method will throw an
  643. * <code>UnsupportedOperationException</code>.
  644. *
  645. * <p> The output must have been set beforehand using
  646. * the <code>setOutput</code> method.
  647. *
  648. * <p> <code>prepareWriteSequence</code> must have been called
  649. * beforehand, or an <code>IllegalStateException</code> is thrown.
  650. *
  651. * <p> If <code>canWriteRasters</code> returns <code>true</code>,
  652. * the <code>IIOImage</code> may contain a <code>Raster</code>
  653. * source. Otherwise, it must contain a
  654. * <code>RenderedImage</code> source.
  655. *
  656. * <p> The supplied thumbnails will be resized if needed, and any
  657. * thumbnails in excess of the supported number will be ignored.
  658. * If the format requires additional thumbnails that are not
  659. * provided, the writer will generate them internally.
  660. *
  661. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  662. * to control the writing process. If <code>param</code> is
  663. * <code>null</code>, a default write param will be used.
  664. *
  665. * <p> If the supplied <code>ImageWriteParam</code> contains
  666. * optional setting values not supported by this writer (<i>e.g.</i>
  667. * progressive encoding or any format-specific settings), they
  668. * will be ignored.
  669. *
  670. * <p> The default implementation throws an
  671. * <code>IllegalStateException</code> if the output is
  672. * <code>null</code>, and otherwise throws an
  673. * <code>UnsupportedOperationException</code>.
  674. *
  675. * @param image an <code>IIOImage</code> object containing an
  676. * image, thumbnails, and metadata to be written.
  677. * @param param an <code>ImageWriteParam</code>, or
  678. * <code>null</code> to use a default
  679. * <code>ImageWriteParam</code>.
  680. *
  681. * @exception IllegalStateException if the output has not
  682. * been set, or <code>prepareWriteSequence</code> has not been called.
  683. * @exception UnsupportedOperationException if
  684. * <code>canWriteSequence</code> returns <code>false</code>.
  685. * @exception IllegalArgumentException if <code>image</code> is
  686. * <code>null</code>.
  687. * @exception UnsupportedOperationException if <code>image</code>
  688. * contains a <code>Raster</code> and <code>canWriteRasters</code>
  689. * returns <code>false</code>.
  690. * @exception IOException if an error occurs during writing.
  691. */
  692. public void writeToSequence(IIOImage image, ImageWriteParam param)
  693. throws IOException {
  694. unsupported();
  695. }
  696. /**
  697. * Completes the writing of a sequence of images begun with
  698. * <code>prepareWriteSequence</code>. Any stream metadata that
  699. * should come at the end of the sequence of images is written out,
  700. * and any header information at the beginning of the sequence is
  701. * patched up if necessary. If the output is an
  702. * <code>ImageOutputStream</code>, data through the stream metadata
  703. * at the end of the sequence are flushed and need not be readable
  704. * or writable.
  705. *
  706. * <p> If <code>canWriteSequence</code> returns <code>false</code>,
  707. * this method will throw an
  708. * <code>UnsupportedOperationException</code>.
  709. *
  710. * <p> The default implementation throws an
  711. * <code>IllegalStateException</code> if the output is
  712. * <code>null</code>, and otherwise throws an
  713. * <code>UnsupportedOperationException</code>.
  714. *
  715. * @exception IllegalStateException if the output has not
  716. * been set, or <code>prepareWriteSequence</code> has not been called.
  717. * @exception UnsupportedOperationException if
  718. * <code>canWriteSequence</code> returns <code>false</code>.
  719. * @exception IOException if an error occurs during writing.
  720. */
  721. public void endWriteSequence() throws IOException {
  722. unsupported();
  723. }
  724. // Metadata replacement
  725. /**
  726. * Returns <code>true</code> if it is possible to replace the
  727. * stream metadata already present in the output.
  728. *
  729. * <p> The default implementation throws an
  730. * <code>IllegalStateException</code> if the output is
  731. * <code>null</code>, and otherwise returns <code>false</code>.
  732. *
  733. * @return <code>true</code> if replacement of stream metadata is
  734. * allowed.
  735. *
  736. * @exception IllegalStateException if the output has not
  737. * been set.
  738. * @exception IOException if an I/O error occurs during the query.
  739. */
  740. public boolean canReplaceStreamMetadata() throws IOException {
  741. if (getOutput() == null) {
  742. throw new IllegalStateException("getOutput() == null!");
  743. }
  744. return false;
  745. }
  746. /**
  747. * Replaces the stream metadata in the output with new
  748. * information. If the output is an
  749. * <code>ImageOutputStream</code>, the prior contents of the
  750. * stream are examined and possibly edited to make room for the
  751. * new data. All of the prior contents of the output must be
  752. * available for reading and writing.
  753. *
  754. * <p> If <code>canReplaceStreamMetadata</code> returns
  755. * <code>false</code>, an
  756. * <code>UnsupportedOperationException</code> will be thrown.
  757. *
  758. * <p> The default implementation throws an
  759. * <code>IllegalStateException</code> if the output is
  760. * <code>null</code>, and otherwise throws an
  761. * <code>UnsupportedOperationException</code>.
  762. *
  763. * @param streamMetadata an <code>IIOMetadata</code> object representing
  764. * stream metadata, or <code>null</code> to use default values.
  765. *
  766. * @exception IllegalStateException if the output has not
  767. * been set.
  768. * @exception UnsupportedOperationException if the
  769. * <code>canReplaceStreamMetadata</code> returns
  770. * <code>false</code>. modes do not include
  771. * @exception IOException if an error occurs during writing.
  772. */
  773. public void replaceStreamMetadata(IIOMetadata streamMetadata)
  774. throws IOException {
  775. unsupported();
  776. }
  777. /**
  778. * Returns <code>true</code> if it is possible to replace the
  779. * image metadata associated with an existing image with index
  780. * <code>imageIndex</code>. If this method returns
  781. * <code>false</code>, a call to
  782. * <code>replaceImageMetadata(imageIndex)</code> will throw an
  783. * <code>UnsupportedOperationException</code>.
  784. *
  785. * <p> A writer that does not support any image metadata
  786. * replacement may return <code>false</code> without performing
  787. * bounds checking on the index.
  788. *
  789. * <p> The default implementation throws an
  790. * <code>IllegalStateException</code> if the output is
  791. * <code>null</code>, and otherwise returns <code>false</code>
  792. * without checking the value of <code>imageIndex</code>.
  793. *
  794. * @param imageIndex the index of the image whose metadata is to
  795. * be replaced.
  796. *
  797. * @return <code>true</code> if the image metadata of the given
  798. * image can be replaced.
  799. *
  800. * @exception IllegalStateException if the output has not
  801. * been set.
  802. * @exception IndexOutOfBoundsException if the writer supports
  803. * image metadata replacement in general, but
  804. * <code>imageIndex</code> is less than 0 or greater than the
  805. * largest available index.
  806. * @exception IOException if an I/O error occurs during the query.
  807. */
  808. public boolean canReplaceImageMetadata(int imageIndex)
  809. throws IOException {
  810. if (getOutput() == null) {
  811. throw new IllegalStateException("getOutput() == null!");
  812. }
  813. return false;
  814. }
  815. /**
  816. * Replaces the image metadata associated with an existing image.
  817. *
  818. * <p> If <code>canReplaceImageMetadata(imageIndex)</code> returns
  819. * <code>false</code>, an
  820. * <code>UnsupportedOperationException</code> will be thrown.
  821. *
  822. * <p> The default implementation throws an
  823. * <code>IllegalStateException</code> if the output is
  824. * <code>null</code>, and otherwise throws an
  825. * <code>UnsupportedOperationException</code>.
  826. *
  827. * @param imageIndex the index of the image whose metadata is to
  828. * be replaced.
  829. * @param imageMetadata an <code>IIOMetadata</code> object
  830. * representing image metadata, or <code>null</code>.
  831. *
  832. * @exception IllegalStateException if the output has not been
  833. * set.
  834. * @exception UnsupportedOperationException if
  835. * <code>canReplaceImageMetadata</code> returns
  836. * <code>false</code>.
  837. * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  838. * is less than 0 or greater than the largest available index.
  839. * @exception IOException if an error occurs during writing.
  840. */
  841. public void replaceImageMetadata(int imageIndex,
  842. IIOMetadata imageMetadata)
  843. throws IOException {
  844. unsupported();
  845. }
  846. // Image insertion
  847. /**
  848. * Returns <code>true</code> if the writer supports the insertion
  849. * of a new image at the given index. Existing images with
  850. * indices greater than or equal to the insertion index will have
  851. * their indices increased by 1. A value for
  852. * <code>imageIndex</code> of <code>-1</code> may be used to
  853. * signify an index one larger than the current largest index.
  854. *
  855. * <p> A writer that does not support any image insertion may
  856. * return <code>false</code> without performing bounds checking on
  857. * the index.
  858. *
  859. * <p> The default implementation throws an
  860. * <code>IllegalStateException</code> if the output is
  861. * <code>null</code>, and otherwise returns <code>false</code>
  862. * withour checking the value of <code>imageIndex</code>.
  863. *
  864. * @param imageIndex the index at which the image is to be
  865. * inserted.
  866. *
  867. * @return <code>true</code> if an image may be inserted at the
  868. * given index.
  869. *
  870. * @exception IllegalStateException if the output has not
  871. * been set.
  872. * @exception IndexOutOfBoundsException if the writer supports
  873. * image insertion in general, but <code>imageIndex</code> is less
  874. * than -1 or greater than the largest available index.
  875. * @exception IOException if an I/O error occurs during the query.
  876. */
  877. public boolean canInsertImage(int imageIndex) throws IOException {
  878. if (getOutput() == null) {
  879. throw new IllegalStateException("getOutput() == null!");
  880. }
  881. return false;
  882. }
  883. /**
  884. * Inserts a new image into an existing image stream. Existing
  885. * images with an index greater than <code>imageIndex</code> are
  886. * preserved, and their indices are each increased by 1. A value
  887. * for <code>imageIndex</code> of -1 may be used to signify an
  888. * index one larger than the previous largest index; that is, it
  889. * will cause the image to be logically appended to the end of the
  890. * sequence. If the output is an <code>ImageOutputStream</code>,
  891. * the entirety of the stream must be both readable and writeable.
  892. *
  893. * <p> If <code>canInsertImage(imageIndex)</code> returns
  894. * <code>false</code>, an
  895. * <code>UnsupportedOperationException</code> will be thrown.
  896. *
  897. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  898. * to control the writing process. If <code>param</code> is
  899. * <code>null</code>, a default write param will be used.
  900. *
  901. * <p> If the supplied <code>ImageWriteParam</code> contains
  902. * optional setting values not supported by this writer (<i>e.g.</i>
  903. * progressive encoding or any format-specific settings), they
  904. * will be ignored.
  905. *
  906. * <p> The default implementation throws an
  907. * <code>IllegalStateException</code> if the output is
  908. * <code>null</code>, and otherwise throws an
  909. * <code>UnsupportedOperationException</code>.
  910. *
  911. * @param imageIndex the index at which to write the image.
  912. * @param image an <code>IIOImage</code> object containing an
  913. * image, thumbnails, and metadata to be written.
  914. * @param param an <code>ImageWriteParam</code>, or
  915. * <code>null</code> to use a default
  916. * <code>ImageWriteParam</code>.
  917. *
  918. * @exception IllegalStateException if the output has not
  919. * been set.
  920. * @exception UnsupportedOperationException if
  921. * <code>canInsertImage(imageIndex)</code> returns <code>false</code>.
  922. * @exception IllegalArgumentException if <code>image</code> is
  923. * <code>null</code>.
  924. * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  925. * is less than -1 or greater than the largest available index.
  926. * @exception UnsupportedOperationException if <code>image</code>
  927. * contains a <code>Raster</code> and <code>canWriteRasters</code>
  928. * returns <code>false</code>.
  929. * @exception IOException if an error occurs during writing.
  930. */
  931. public void writeInsert(int imageIndex,
  932. IIOImage image,
  933. ImageWriteParam param) throws IOException {
  934. unsupported();
  935. }
  936. // Image removal
  937. /**
  938. * Returns <code>true</code> if the writer supports the removal
  939. * of an existing image at the given index. Existing images with
  940. * indices greater than the insertion index will have
  941. * their indices decreased by 1.
  942. *
  943. * <p> A writer that does not support any image removal may
  944. * return <code>false</code> without performing bounds checking on
  945. * the index.
  946. *
  947. * <p> The default implementation throws an
  948. * <code>IllegalStateException</code> if the output is
  949. * <code>null</code>, and otherwise returns <code>false</code>
  950. * without checking the value of <code>imageIndex</code>.
  951. *
  952. * @param imageIndex the index of the image to be removed.
  953. *
  954. * @return <code>true</code> if it is possible to remove the given
  955. * image.
  956. *
  957. * @exception IllegalStateException if the output has not
  958. * been set.
  959. * @exception IndexOutOfBoundsException if the writer supports
  960. * image removal in general, but <code>imageIndex</code> is less
  961. * than 0 or greater than the largest available index.
  962. * @exception IOException if an I/O error occurs during the
  963. * query.
  964. */
  965. public boolean canRemoveImage(int imageIndex) throws IOException {
  966. if (getOutput() == null) {
  967. throw new IllegalStateException("getOutput() == null!");
  968. }
  969. return false;
  970. }
  971. /**
  972. * Removes an image from the stream.
  973. *
  974. * <p> If <code>canRemoveImage(imageIndex)</code> returns false,
  975. * an <code>UnsupportedOperationException</code>will be thrown.
  976. *
  977. * <p> The removal may or may not cause a reduction in the actual
  978. * file size.
  979. *
  980. * <p> The default implementation throws an
  981. * <code>IllegalStateException</code> if the output is
  982. * <code>null</code>, and otherwise throws an
  983. * <code>UnsupportedOperationException</code>.
  984. *
  985. * @param imageIndex the index of the image to be removed.
  986. *
  987. * @exception IllegalStateException if the output has not
  988. * been set.
  989. * @exception UnsupportedOperationException if
  990. * <code>canRemoveImage(imageIndex)</code> returns <code>false</code>.
  991. * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  992. * is less than 0 or greater than the largest available index.
  993. * @exception IOException if an I/O error occurs during the
  994. * removal.
  995. */
  996. public void removeImage(int imageIndex) throws IOException {
  997. unsupported();
  998. }
  999. // Empty images
  1000. /**
  1001. * Returns <code>true</code> if the writer supports the writing of
  1002. * a complete image stream consisting of a single image with
  1003. * undefined pixel values and associated metadata and thumbnails
  1004. * to the output. The pixel values may be defined by future
  1005. * calls to the <code>replacePixels</code> methods. If the output
  1006. * is an <code>ImageOutputStream</code>, its existing contents
  1007. * prior to the current seek position are not affected, and need
  1008. * not be readable or writable.
  1009. *
  1010. * <p> The default implementation throws an
  1011. * <code>IllegalStateException</code> if the output is
  1012. * <code>null</code>, and otherwise returns <code>false</code>.
  1013. *
  1014. * @return <code>true</code> if the writing of complete image
  1015. * stream with contents to be defined later is supported.
  1016. *
  1017. * @exception IllegalStateException if the output has not been
  1018. * set.
  1019. * @exception IOException if an I/O error occurs during the
  1020. * query.
  1021. */
  1022. public boolean canWriteEmpty() throws IOException {
  1023. if (getOutput() == null) {
  1024. throw new IllegalStateException("getOutput() == null!");
  1025. }
  1026. return false;
  1027. }
  1028. /**
  1029. * Begins the writing of a complete image stream, consisting of a
  1030. * single image with undefined pixel values and associated
  1031. * metadata and thumbnails, to the output. The pixel values will
  1032. * be defined by future calls to the <code>replacePixels</code>
  1033. * methods. If the output is an <code>ImageOutputStream</code>,
  1034. * its existing contents prior to the current seek position are
  1035. * not affected, and need not be readable or writable.
  1036. *
  1037. * <p> The writing is not complete until a call to
  1038. * <code>endWriteEmpty</code> occurs. Calls to
  1039. * <code>prepareReplacePixels</code>, <code>replacePixels</code>,
  1040. * and <code>endReplacePixels</code> may occur between calls to
  1041. * <code>prepareWriteEmpty</code> and <code>endWriteEmpty</code>.
  1042. * However, calls to <code>prepareWriteEmpty</code> cannot be
  1043. * nested, and calls to <code>prepareWriteEmpty</code> and
  1044. * <code>prepareInsertEmpty</code> may not be interspersed.
  1045. *
  1046. * <p> If <code>canWriteEmpty</code> returns <code>false</code>,
  1047. * an <code>UnsupportedOperationException</code> will be thrown.
  1048. *
  1049. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  1050. * to control the writing process. If <code>param</code> is
  1051. * <code>null</code>, a default write param will be used.
  1052. *
  1053. * <p> If the supplied <code>ImageWriteParam</code> contains
  1054. * optional setting values not supported by this writer (<i>e.g.</i>
  1055. * progressive encoding or any format-specific settings), they
  1056. * will be ignored.
  1057. *
  1058. * <p> The default implementation throws an
  1059. * <code>IllegalStateException</code> if the output is
  1060. * <code>null</code>, and otherwise throws an
  1061. * <code>UnsupportedOperationException</code>.
  1062. *
  1063. * @param streamMetadata an <code>IIOMetadata</code> object representing
  1064. * stream metadata, or <code>null</code> to use default values.
  1065. * @param imageType an <code>ImageTypeSpecifier</code> describing
  1066. * the layout of the image.
  1067. * @param width the width of the image.
  1068. * @param height the height of the image.
  1069. * @param imageMetadata an <code>IIOMetadata</code> object
  1070. * representing image metadata, or <code>null</code>.
  1071. * @param thumbnails a <code>List</code> of
  1072. * <code>BufferedImage</code> thumbnails for this image, or
  1073. * <code>null</code>.
  1074. * @param param an <code>ImageWriteParam</code>, or
  1075. * <code>null</code> to use a default
  1076. * <code>ImageWriteParam</code>.
  1077. *
  1078. * @exception IllegalStateException if the output has not
  1079. * been set.
  1080. * @exception UnsupportedOperationException if
  1081. * <code>canWriteEmpty</code> returns <code>false</code>.
  1082. * @exception IllegalStateException if a previous call to
  1083. * <code>prepareWriteEmpty</code> has been made without a
  1084. * corresponding call to <code>endWriteEmpty</code>.
  1085. * @exception IllegalStateException if a previous call to
  1086. * <code>prepareInsertEmpty</code> has been made without a
  1087. * corresponding call to <code>endInsertEmpty</code>.
  1088. * @exception IllegalArgumentException if <code>imageType</code>
  1089. * is <code>null</code> or <code>thumbnails</code> contains
  1090. * <code>null</code> references or objects other than
  1091. * <code>BufferedImage</code>s.
  1092. * @exception IllegalArgumentException if width or height are less
  1093. * than 1.
  1094. * @exception IOException if an I/O error occurs during writing.
  1095. */
  1096. public void prepareWriteEmpty(IIOMetadata streamMetadata,
  1097. ImageTypeSpecifier imageType,
  1098. int width, int height,
  1099. IIOMetadata imageMetadata,
  1100. List<? extends BufferedImage> thumbnails,
  1101. ImageWriteParam param) throws IOException {
  1102. unsupported();
  1103. }
  1104. /**
  1105. * Completes the writing of a new image that was begun with a
  1106. * prior call to <code>prepareWriteEmpty</code>.
  1107. *
  1108. * <p> If <code>canWriteEmpty()</code> returns <code>false</code>,
  1109. * an <code>UnsupportedOperationException</code> will be thrown.
  1110. *
  1111. * <p> The default implementation throws an
  1112. * <code>IllegalStateException</code> if the output is
  1113. * <code>null</code>, and otherwise throws an
  1114. * <code>UnsupportedOperationException</code>.
  1115. *
  1116. * @exception IllegalStateException if the output has not
  1117. * been set.
  1118. * @exception UnsupportedOperationException if
  1119. * <code>canWriteEmpty(imageIndex)</code> returns
  1120. * <code>false</code>.
  1121. * @exception IllegalStateException if a previous call to
  1122. * <code>prepareWriteEmpty</code> without a corresponding call to
  1123. * <code>endWriteEmpty</code> has not been made.
  1124. * @exception IllegalStateException if a previous call to
  1125. * <code>prepareInsertEmpty</code> without a corresponding call to
  1126. * <code>endInsertEmpty</code> has been made.
  1127. * @exception IllegalStateException if a call to
  1128. * <code>prepareReiplacePixels</code> has been made without a
  1129. * matching call to <code>endReplacePixels</code>.
  1130. * @exception IOException if an I/O error occurs during writing.
  1131. */
  1132. public void endWriteEmpty() throws IOException {
  1133. if (getOutput() == null) {
  1134. throw new IllegalStateException("getOutput() == null!");
  1135. }
  1136. throw new IllegalStateException("No call to prepareWriteEmpty!");
  1137. }
  1138. /**
  1139. * Returns <code>true</code> if the writer supports the insertion
  1140. * of a new, empty image at the given index. The pixel values of
  1141. * the image are undefined, and may be specified in pieces using
  1142. * the <code>replacePixels</code> methods. Existing images with
  1143. * indices greater than or equal to the insertion index will have
  1144. * their indices increased by 1. A value for
  1145. * <code>imageIndex</code> of <code>-1</code> may be used to
  1146. * signify an index one larger than the current largest index.
  1147. *
  1148. * <p> A writer that does not support insertion of empty images
  1149. * may return <code>false</code> without performing bounds
  1150. * checking on the index.
  1151. *
  1152. * <p> The default implementation throws an
  1153. * <code>IllegalStateException</code> if the output is
  1154. * <code>null</code>, and otherwise returns <code>false</code>
  1155. * without checking the value of <code>imageIndex</code>.
  1156. *
  1157. * @param imageIndex the index at which the image is to be
  1158. * inserted.
  1159. *
  1160. * @return <code>true</code> if an empty image may be inserted at
  1161. * the given index.
  1162. *
  1163. * @exception IllegalStateException if the output has not been
  1164. * set.
  1165. * @exception IndexOutOfBoundsException if the writer supports
  1166. * empty image insertion in general, but <code>imageIndex</code>
  1167. * is less than -1 or greater than the largest available index.
  1168. * @exception IOException if an I/O error occurs during the
  1169. * query.
  1170. */
  1171. public boolean canInsertEmpty(int imageIndex) throws IOException {
  1172. if (getOutput() == null) {
  1173. throw new IllegalStateException("getOutput() == null!");
  1174. }
  1175. return false;
  1176. }
  1177. /**
  1178. * Begins the insertion of a new image with undefined pixel values
  1179. * into an existing image stream. Existing images with an index
  1180. * greater than <code>imageIndex</code> are preserved, and their
  1181. * indices are each increased by 1. A value for
  1182. * <code>imageIndex</code> of -1 may be used to signify an index
  1183. * one larger than the previous largest index; that is, it will
  1184. * cause the image to be logically appended to the end of the
  1185. * sequence. If the output is an <code>ImageOutputStream</code>,
  1186. * the entirety of the stream must be both readable and writeable.
  1187. *
  1188. * <p> The image contents may be
  1189. * supplied later using the <code>replacePixels</code> method.
  1190. * The insertion is not complete until a call to
  1191. * <code>endInsertEmpty</code> occurs. Calls to
  1192. * <code>prepareReplacePixels</code>, <code>replacePixels</code>,
  1193. * and <code>endReplacePixels</code> may occur between calls to
  1194. * <code>prepareInsertEmpty</code> and
  1195. * <code>endInsertEmpty</code>. However, calls to
  1196. * <code>prepareInsertEmpty</code> cannot be nested, and calls to
  1197. * <code>prepareWriteEmpty</code> and
  1198. * <code>prepareInsertEmpty</code> may not be interspersed.
  1199. *
  1200. * <p> If <code>canInsertEmpty(imageIndex)</code> returns
  1201. * <code>false</code>, an
  1202. * <code>UnsupportedOperationException</code> will be thrown.
  1203. *
  1204. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  1205. * to control the writing process. If <code>param</code> is
  1206. * <code>null</code>, a default write param will be used.
  1207. *
  1208. * <p> If the supplied <code>ImageWriteParam</code> contains
  1209. * optional setting values not supported by this writer (<i>e.g.</i>
  1210. * progressive encoding or any format-specific settings), they
  1211. * will be ignored.
  1212. *
  1213. * <p> The default implementation throws an
  1214. * <code>IllegalStateException</code> if the output is
  1215. * <code>null</code>, and otherwise throws an
  1216. * <code>UnsupportedOperationException</code>.
  1217. *
  1218. * @param imageIndex the index at which to write the image.
  1219. * @param imageType an <code>ImageTypeSpecifier</code> describing
  1220. * the layout of the image.
  1221. * @param width the width of the image.
  1222. * @param height the height of the image.
  1223. * @param imageMetadata an <code>IIOMetadata</code> object
  1224. * representing image metadata, or <code>null</code>.
  1225. * @param thumbnails a <code>List</code> of
  1226. * <code>BufferedImage</code> thumbnails for this image, or
  1227. * <code>null</code>.
  1228. * @param param an <code>ImageWriteParam</code>, or
  1229. * <code>null</code> to use a default
  1230. * <code>ImageWriteParam</code>.
  1231. *
  1232. * @exception IllegalStateException if the output has not
  1233. * been set.
  1234. * @exception UnsupportedOperationException if
  1235. * <code>canInsertEmpty(imageIndex)</code> returns
  1236. * <code>false</code>.
  1237. * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  1238. * is less than -1 or greater than the largest available index.
  1239. * @exception IllegalStateException if a previous call to
  1240. * <code>prepareInsertEmpty</code> has been made without a
  1241. * corresponding call to <code>endInsertEmpty</code>.
  1242. * @exception IllegalStateException if a previous call to
  1243. * <code>prepareWriteEmpty</code> has been made without a
  1244. * corresponding call to <code>endWriteEmpty</code>.
  1245. * @exception IllegalArgumentException if <code>imageType</code>
  1246. * is <code>null</code> or <code>thumbnails</code> contains
  1247. * <code>null</code> references or objects other than
  1248. * <code>BufferedImage</code>s.
  1249. * @exception IllegalArgumentException if width or height are less
  1250. * than 1.
  1251. * @exception IOException if an I/O error occurs during writing.
  1252. */
  1253. public void prepareInsertEmpty(int imageIndex,
  1254. ImageTypeSpecifier imageType,
  1255. int width, int height,
  1256. IIOMetadata imageMetadata,
  1257. List<? extends BufferedImage> thumbnails,
  1258. ImageWriteParam param) throws IOException {
  1259. unsupported();
  1260. }
  1261. /**
  1262. * Completes the insertion of a new image that was begun with a
  1263. * prior call to <code>prepareInsertEmpty</code>.
  1264. *
  1265. * <p> The default implementation throws an
  1266. * <code>IllegalStateException</code> if the output is
  1267. * <code>null</code>, and otherwise throws an
  1268. * <code>UnsupportedOperationException</code>.
  1269. *
  1270. * @exception IllegalStateException if the output has not
  1271. * been set.
  1272. * @exception UnsupportedOperationException if
  1273. * <code>canInsertEmpty(imageIndex)</code> returns
  1274. * <code>false</code>.
  1275. * @exception IllegalStateException if a previous call to
  1276. * <code>prepareInsertEmpty</code> without a corresponding call to
  1277. * <code>endInsertEmpty</code> has not been made.
  1278. * @exception IllegalStateException if a previous call to
  1279. * <code>prepareWriteEmpty</code> without a corresponding call to
  1280. * <code>endWriteEmpty</code> has been made.
  1281. * @exception IllegalStateException if a call to
  1282. * <code>prepareReplacePixels</code> has been made without a
  1283. * matching call to <code>endReplacePixels</code>.
  1284. * @exception IOException if an I/O error occurs during writing.
  1285. */
  1286. public void endInsertEmpty() throws IOException {
  1287. unsupported();
  1288. }
  1289. // Pixel replacement
  1290. /**
  1291. * Returns <code>true</code> if the writer allows pixels of the
  1292. * given image to be replaced using the <code>replacePixels</code>
  1293. * methods.
  1294. *
  1295. * <p> A writer that does not support any pixel replacement may
  1296. * return <code>false</code> without performing bounds checking on
  1297. * the index.
  1298. *
  1299. * <p> The default implementation throws an
  1300. * <code>IllegalStateException</code> if the output is
  1301. * <code>null</code>, and otherwise returns <code>false</code>
  1302. * without checking the value of <code>imageIndex</code>.
  1303. *
  1304. * @param imageIndex the index of the image whose pixels are to be
  1305. * replaced.
  1306. *
  1307. * @return <code>true</code> if the pixels of the given
  1308. * image can be replaced.
  1309. *
  1310. * @exception IllegalStateException if the output has not been
  1311. * set.
  1312. * @exception IndexOutOfBoundsException if the writer supports
  1313. * pixel replacement in general, but <code>imageIndex</code> is
  1314. * less than 0 or greater than the largest available index.
  1315. * @exception IOException if an I/O error occurs during the query.
  1316. */
  1317. public boolean canReplacePixels(int imageIndex) throws IOException {
  1318. if (getOutput() == null) {
  1319. throw new IllegalStateException("getOutput() == null!");
  1320. }
  1321. return false;
  1322. }
  1323. /**
  1324. * Prepares the writer to handle a series of calls to the
  1325. * <code>replacePixels</code> methods. The affected pixel area
  1326. * will be clipped against the supplied
  1327. *
  1328. * <p> If <code>canReplacePixels</code> returns
  1329. * <code>false</code>, and
  1330. * <code>UnsupportedOperationException</code> will be thrown.
  1331. *
  1332. * <p> The default implementation throws an
  1333. * <code>IllegalStateException</code> if the output is
  1334. * <code>null</code>, and otherwise throws an
  1335. * <code>UnsupportedOperationException</code>.
  1336. *
  1337. * @param imageIndex the index of the image whose pixels are to be
  1338. * replaced.
  1339. * @param region a <code>Rectangle</code> that will be used to clip
  1340. * future pixel regions.
  1341. *
  1342. * @exception IllegalStateException if the output has not
  1343. * been set.
  1344. * @exception UnsupportedOperationException if
  1345. * <code>canReplacePixels(imageIndex)</code> returns
  1346. * <code>false</code>.
  1347. * @exception IndexOutOfBoundsException if <code>imageIndex</code>
  1348. * is less than 0 or greater than the largest available index.
  1349. * @exception IllegalStateException if there is a previous call to
  1350. * <code>prepareReplacePixels</code> without a matching call to
  1351. * <code>endReplacePixels</code> (<i>i.e.</i>, nesting is not
  1352. * allowed).
  1353. * @exception IllegalArgumentException if <code>region</code> is
  1354. * <code>null</code> or has a width or height less than 1.
  1355. * @exception IOException if an I/O error occurs during the
  1356. * preparation.
  1357. */
  1358. public void prepareReplacePixels(int imageIndex,
  1359. Rectangle region) throws IOException {
  1360. unsupported();
  1361. }
  1362. /**
  1363. * Replaces a portion of an image already present in the output
  1364. * with a portion of the given image. The image data must match,
  1365. * or be convertible to, the image layout of the existing image.
  1366. *
  1367. * <p> The destination region is specified in the
  1368. * <code>param</code> argument, and will be clipped to the image
  1369. * boundaries and the region supplied to
  1370. * <code>prepareReplacePixels</code>. At least one pixel of the
  1371. * source must not be clipped, or an exception is thrown.
  1372. *
  1373. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  1374. * to control the writing process. If <code>param</code> is
  1375. * <code>null</code>, a default write param will be used.
  1376. *
  1377. * <p> If the supplied <code>ImageWriteParam</code> contains
  1378. * optional setting values not supported by this writer (<i>e.g.</i>
  1379. * progressive encoding or any format-specific settings), they
  1380. * will be ignored.
  1381. *
  1382. * <p> This method may only be called after a call to
  1383. * <code>prepareReplacePixels</code>, or else an
  1384. * <code>IllegalStateException</code> will be thrown.
  1385. *
  1386. * <p> The default implementation throws an
  1387. * <code>IllegalStateException</code> if the output is
  1388. * <code>null</code>, and otherwise throws an
  1389. * <code>UnsupportedOperationException</code>.
  1390. *
  1391. * @param image a <code>RenderedImage</code> containing source
  1392. * pixels.
  1393. * @param param an <code>ImageWriteParam</code>, or
  1394. * <code>null</code> to use a default
  1395. * <code>ImageWriteParam</code>.
  1396. *
  1397. * @exception IllegalStateException if the output has not
  1398. * been set.
  1399. * @exception UnsupportedOperationException if
  1400. * <code>canReplacePixels(imageIndex)</code> returns
  1401. * <code>false</code>.
  1402. * @exception IllegalStateException if there is no previous call to
  1403. * <code>prepareReplacePixels</code> without a matching call to
  1404. * <code>endReplacePixels</code>.
  1405. * @exception IllegalArgumentException if any of the following are true:
  1406. * <li> <code>image</code> is <code>null</code>.
  1407. * <li> <code>param</code> is <code>null</code>.
  1408. * <li> the intersected region does not contain at least one pixel.
  1409. * <li> the layout of <code>image</code> does not match, or this
  1410. * writer cannot convert it to, the existing image layout.
  1411. * </ul>
  1412. * @exception IOException if an I/O error occurs during writing.
  1413. */
  1414. public void replacePixels(RenderedImage image, ImageWriteParam param)
  1415. throws IOException {
  1416. unsupported();
  1417. }
  1418. /**
  1419. * Replaces a portion of an image already present in the output
  1420. * with a portion of the given <code>Raster</code>. The image
  1421. * data must match, or be convertible to, the image layout of the
  1422. * existing image.
  1423. *
  1424. * <p> An <code>ImageWriteParam</code> may optionally be supplied
  1425. * to control the writing process. If <code>param</code> is
  1426. * <code>null</code>, a default write param will be used.
  1427. *
  1428. * <p> The destination region is specified in the
  1429. * <code>param</code> argument, and will be clipped to the image
  1430. * boundaries and the region supplied to
  1431. * <code>prepareReplacePixels</code>. At least one pixel of the
  1432. * source must not be clipped, or an exception is thrown.
  1433. *
  1434. * <p> If the supplied <code>ImageWriteParam</code> contains
  1435. * optional setting values not supported by this writer (<i>e.g.</i>
  1436. * progressive encoding or any format-specific settings), they
  1437. * will be ignored.
  1438. *
  1439. * <p> This method may only be called after a call to
  1440. * <code>prepareReplacePixels</code>, or else an
  1441. * <code>IllegalStateException</code> will be thrown.
  1442. *
  1443. * <p> The default implementation throws an
  1444. * <code>IllegalStateException</code> if the output is
  1445. * <code>null</code>, and otherwise throws an
  1446. * <code>UnsupportedOperationException</code>.
  1447. *
  1448. * @param raster a <code>Raster</code> containing source
  1449. * pixels.
  1450. * @param param an <code>ImageWriteParam</code>, or
  1451. * <code>null</code> to use a default
  1452. * <code>ImageWriteParam</code>.
  1453. *
  1454. * @exception IllegalStateException if the output has not
  1455. * been set.
  1456. * @exception UnsupportedOperationException if
  1457. * <code>canReplacePixels(imageIndex)</code> returns
  1458. * <code>false</code>.
  1459. * @exception IllegalStateException if there is no previous call to
  1460. * <code>prepareReplacePixels</code> without a matching call to
  1461. * <code>endReplacePixels</code>.
  1462. * @exception UnsupportedOperationException if
  1463. * <code>canWriteRasters</code> returns <code>false</code>.
  1464. * @exception IllegalArgumentException if any of the following are true:
  1465. * <li> <code>raster</code> is <code>null</code>.
  1466. * <li> <code>param</code> is <code>null</code>.
  1467. * <li> the intersected region does not contain at least one pixel.
  1468. * <li> the layout of <code>raster</code> does not match, or this
  1469. * writer cannot convert it to, the existing image layout.
  1470. * </ul>
  1471. * @exception IOException if an I/O error occurs during writing.
  1472. */
  1473. public void replacePixels(Raster raster, ImageWriteParam param)
  1474. throws IOException {
  1475. unsupported();
  1476. }
  1477. /**
  1478. * Terminates a sequence of calls to <code>replacePixels</code>.
  1479. *
  1480. * <p> If <code>canReplacePixels</code> returns
  1481. * <code>false</code>, and
  1482. * <code>UnsupportedOperationException</code> will be thrown.
  1483. *
  1484. * <p> The default implementation throws an
  1485. * <code>IllegalStateException</code> if the output is
  1486. * <code>null</code>, and otherwise throws an
  1487. * <code>UnsupportedOperationException</code>.
  1488. *
  1489. * @exception IllegalStateException if the output has not
  1490. * been set.
  1491. * @exception UnsupportedOperationException if
  1492. * <code>canReplacePixels(imageIndex)</code> returns
  1493. * <code>false</code>.
  1494. * @exception IllegalStateException if there is no previous call
  1495. * to <code>prepareReplacePixels</code> without a matching call to
  1496. * <code>endReplacePixels</code>.
  1497. * @exception IOException if an I/O error occurs during writing.
  1498. */
  1499. public void endReplacePixels() throws IOException {
  1500. unsupported();
  1501. }
  1502. // Abort
  1503. /**
  1504. * Requests that any current write operation be aborted. The
  1505. * contents of the output following the abort will be undefined.
  1506. *
  1507. * <p> Writers should call <code>clearAbortRequest</code> at the
  1508. * beginning of each write operation, and poll the value of
  1509. * <code>abortRequested</code> regularly during the write.
  1510. */
  1511. public synchronized void abort() {
  1512. this.abortFlag = true;
  1513. }
  1514. /**
  1515. * Returns <code>true</code> if a request to abort the current
  1516. * write operation has been made since the writer was instantiated or
  1517. * <code>clearAbortRequest</code> was called.
  1518. *
  1519. * @return <code>true</code> if the current write operation should
  1520. * be aborted.
  1521. *
  1522. * @see #abort
  1523. * @see #clearAbortRequest
  1524. */
  1525. protected synchronized boolean abortRequested() {
  1526. return this.abortFlag;
  1527. }
  1528. /**
  1529. * Clears any previous abort request. After this method has been
  1530. * called, <code>abortRequested</code> will return
  1531. * <code>false</code>.
  1532. *
  1533. * @see #abort
  1534. * @see #abortRequested
  1535. */
  1536. protected synchronized void clearAbortRequest() {
  1537. this.abortFlag = false;
  1538. }
  1539. // Listeners
  1540. /**
  1541. * Adds an <code>IIOWriteWarningListener</code> to the list of
  1542. * registered warning listeners. If <code>listener</code> is
  1543. * <code>null</code>, no exception will be thrown and no action
  1544. * will be taken. Messages sent to the given listener will be
  1545. * localized, if possible, to match the current
  1546. * <code>Locale</code>. If no <code>Locale</code> has been set,
  1547. * warning messages may be localized as the writer sees fit.
  1548. *
  1549. * @param listener an <code>IIOWriteWarningListener</code> to be
  1550. * registered.
  1551. *
  1552. * @see #removeIIOWriteWarningListener
  1553. */
  1554. public void addIIOWriteWarningListener(IIOWriteWarningListener listener) {
  1555. if (listener == null) {
  1556. return;
  1557. }
  1558. warningListeners = ImageReader.addToList(warningListeners, listener);
  1559. warningLocales = ImageReader.addToList(warningLocales, getLocale());
  1560. }
  1561. /**
  1562. * Removes an <code>IIOWriteWarningListener</code> from the list
  1563. * of registered warning listeners. If the listener was not
  1564. * previously registered, or if <code>listener</code> is
  1565. * <code>null</code>, no exception will be thrown and no action
  1566. * will be taken.
  1567. *
  1568. * @param listener an <code>IIOWriteWarningListener</code> to be
  1569. * deregistered.
  1570. *
  1571. * @see #addIIOWriteWarningListener
  1572. */
  1573. public
  1574. void removeIIOWriteWarningListener(IIOWriteWarningListener listener) {
  1575. if (listener == null || warningListeners == null) {
  1576. return;
  1577. }
  1578. int index = warningListeners.indexOf(listener);
  1579. if (index != -1) {
  1580. warningListeners.remove(index);
  1581. warningLocales.remove(index);
  1582. if (warningListeners.size() == 0) {
  1583. warningListeners = null;
  1584. warningLocales = null;
  1585. }
  1586. }
  1587. }
  1588. /**
  1589. * Removes all currently registered
  1590. * <code>IIOWriteWarningListener</code> objects.
  1591. *
  1592. * <p> The default implementation sets the
  1593. * <code>warningListeners</code> and <code>warningLocales</code>
  1594. * instance variables to <code>null</code>.
  1595. */
  1596. public void removeAllIIOWriteWarningListeners() {
  1597. this.warningListeners = null;
  1598. this.warningLocales = null;
  1599. }
  1600. /**
  1601. * Adds an <code>IIOWriteProgressListener</code> to the list of
  1602. * registered progress listeners. If <code>listener</code> is
  1603. * <code>null</code>, no exception will be thrown and no action
  1604. * will be taken.
  1605. *
  1606. * @param listener an <code>IIOWriteProgressListener</code> to be
  1607. * registered.
  1608. *
  1609. * @see #removeIIOWriteProgressListener
  1610. */
  1611. public void
  1612. addIIOWriteProgressListener(IIOWriteProgressListener listener) {
  1613. if (listener == null) {
  1614. return;
  1615. }
  1616. progressListeners = ImageReader.addToList(progressListeners, listener);
  1617. }
  1618. /**
  1619. * Removes an <code>IIOWriteProgressListener</code> from the list
  1620. * of registered progress listeners. If the listener was not
  1621. * previously registered, or if <code>listener</code> is
  1622. * <code>null</code>, no exception will be thrown and no action
  1623. * will be taken.
  1624. *
  1625. * @param listener an <code>IIOWriteProgressListener</code> to be
  1626. * deregistered.
  1627. *
  1628. * @see #addIIOWriteProgressListener
  1629. */
  1630. public void
  1631. removeIIOWriteProgressListener(IIOWriteProgressListener listener) {
  1632. if (listener == null || progressListeners == null) {
  1633. return;
  1634. }
  1635. progressListeners =
  1636. ImageReader.removeFromList(progressListeners, listener);
  1637. }
  1638. /**
  1639. * Removes all currently registered
  1640. * <code>IIOWriteProgressListener</code> objects.
  1641. *
  1642. * <p> The default implementation sets the
  1643. * <code>progressListeners</code> instance variable to
  1644. * <code>null</code>.
  1645. */
  1646. public void removeAllIIOWriteProgressListeners() {
  1647. this.progressListeners = null;
  1648. }
  1649. /**
  1650. * Broadcasts the start of an image write to all registered
  1651. * <code>IIOWriteProgressListener</code>s by calling their
  1652. * <code>imageStarted</code> method. Subclasses may use this
  1653. * method as a convenience.
  1654. *
  1655. * @param imageIndex the index of the image about to be written.
  1656. */
  1657. protected void processImageStarted(int imageIndex) {
  1658. if (progressListeners == null) {
  1659. return;
  1660. }
  1661. int numListeners = progressListeners.size();
  1662. for (int i = 0; i < numListeners; i++) {
  1663. IIOWriteProgressListener listener =
  1664. (IIOWriteProgressListener)progressListeners.get(i);
  1665. listener.imageStarted(this, imageIndex);
  1666. }
  1667. }
  1668. /**
  1669. * Broadcasts the current percentage of image completion to all
  1670. * registered <code>IIOWriteProgressListener</code>s by calling
  1671. * their <code>imageProgress</code> method. Subclasses may use
  1672. * this method as a convenience.
  1673. *
  1674. * @param percentageDone the current percentage of completion,
  1675. * as a <code>float</code>.
  1676. */
  1677. protected void processImageProgress(float percentageDone) {
  1678. if (progressListeners == null) {
  1679. return;
  1680. }
  1681. int numListeners = progressListeners.size();
  1682. for (int i = 0; i < numListeners; i++) {
  1683. IIOWriteProgressListener listener =
  1684. (IIOWriteProgressListener)progressListeners.get(i);
  1685. listener.imageProgress(this, percentageDone);
  1686. }
  1687. }
  1688. /**
  1689. * Broadcasts the completion of an image write to all registered
  1690. * <code>IIOWriteProgressListener</code>s by calling their
  1691. * <code>imageComplete</code> method. Subclasses may use this
  1692. * method as a convenience.
  1693. */
  1694. protected void processImageComplete() {
  1695. if (progressListeners == null) {
  1696. return;
  1697. }
  1698. int numListeners = progressListeners.size();
  1699. for (int i = 0; i < numListeners; i++) {
  1700. IIOWriteProgressListener listener =
  1701. (IIOWriteProgressListener)progressListeners.get(i);
  1702. listener.imageComplete(this);
  1703. }
  1704. }
  1705. /**
  1706. * Broadcasts the start of a thumbnail write to all registered
  1707. * <code>IIOWriteProgressListener</code>s by calling their
  1708. * <code>thumbnailStarted</code> method. Subclasses may use this
  1709. * method as a convenience.
  1710. *
  1711. * @param imageIndex the index of the image associated with the
  1712. * thumbnail.
  1713. * @param thumbnailIndex the index of the thumbnail.
  1714. */
  1715. protected void processThumbnailStarted(int imageIndex,
  1716. int thumbnailIndex) {
  1717. if (progressListeners == null) {
  1718. return;
  1719. }
  1720. int numListeners = progressListeners.size();
  1721. for (int i = 0; i < numListeners; i++) {
  1722. IIOWriteProgressListener listener =
  1723. (IIOWriteProgressListener)progressListeners.get(i);
  1724. listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
  1725. }
  1726. }
  1727. /**
  1728. * Broadcasts the current percentage of thumbnail completion to
  1729. * all registered <code>IIOWriteProgressListener</code>s by calling
  1730. * their <code>thumbnailProgress</code> method. Subclasses may
  1731. * use this method as a convenience.
  1732. *
  1733. * @param percentageDone the current percentage of completion,
  1734. * as a <code>float</code>.
  1735. */
  1736. protected void processThumbnailProgress(float percentageDone) {
  1737. if (progressListeners == null) {
  1738. return;
  1739. }
  1740. int numListeners = progressListeners.size();
  1741. for (int i = 0; i < numListeners; i++) {
  1742. IIOWriteProgressListener listener =
  1743. (IIOWriteProgressListener)progressListeners.get(i);
  1744. listener.thumbnailProgress(this, percentageDone);
  1745. }
  1746. }
  1747. /**
  1748. * Broadcasts the completion of a thumbnail write to all registered
  1749. * <code>IIOWriteProgressListener</code>s by calling their
  1750. * <code>thumbnailComplete</code> method. Subclasses may use this
  1751. * method as a convenience.
  1752. */
  1753. protected void processThumbnailComplete() {
  1754. if (progressListeners == null) {
  1755. return;
  1756. }
  1757. int numListeners = progressListeners.size();
  1758. for (int i = 0; i < numListeners; i++) {
  1759. IIOWriteProgressListener listener =
  1760. (IIOWriteProgressListener)progressListeners.get(i);
  1761. listener.thumbnailComplete(this);
  1762. }
  1763. }
  1764. /**
  1765. * Broadcasts that the write has been aborted to all registered
  1766. * <code>IIOWriteProgressListener</code>s by calling their
  1767. * <code>writeAborted</code> method. Subclasses may use this
  1768. * method as a convenience.
  1769. */
  1770. protected void processWriteAborted() {
  1771. if (progressListeners == null) {
  1772. return;
  1773. }
  1774. int numListeners = progressListeners.size();
  1775. for (int i = 0; i < numListeners; i++) {
  1776. IIOWriteProgressListener listener =
  1777. (IIOWriteProgressListener)progressListeners.get(i);
  1778. listener.writeAborted(this);
  1779. }
  1780. }
  1781. /**
  1782. * Broadcasts a warning message to all registered
  1783. * <code>IIOWriteWarningListener</code>s by calling their
  1784. * <code>warningOccurred</code> method. Subclasses may use this
  1785. * method as a convenience.
  1786. *
  1787. * @param imageIndex the index of the image on which the warning
  1788. * occurred.
  1789. * @param warning the warning message.
  1790. *
  1791. * @exception IllegalArgumentException if <code>warning</code>
  1792. * is <code>null</code>.
  1793. */
  1794. protected void processWarningOccurred(int imageIndex,
  1795. String warning) {
  1796. if (warningListeners == null) {
  1797. return;
  1798. }
  1799. if (warning == null) {
  1800. throw new IllegalArgumentException("warning == null!");
  1801. }
  1802. int numListeners = warningListeners.size();
  1803. for (int i = 0; i < numListeners; i++) {
  1804. IIOWriteWarningListener listener =
  1805. (IIOWriteWarningListener)warningListeners.get(i);
  1806. listener.warningOccurred(this, imageIndex, warning);
  1807. }
  1808. }
  1809. /**
  1810. * Broadcasts a localized warning message to all registered
  1811. * <code>IIOWriteWarningListener</code>s by calling their
  1812. * <code>warningOccurred</code> method with a string taken
  1813. * from a <code>ResourceBundle</code>. Subclasses may use this
  1814. * method as a convenience.
  1815. *
  1816. * @param imageIndex the index of the image on which the warning
  1817. * occurred.
  1818. * @param baseName the base name of a set of
  1819. * <code>ResourceBundle</code>s containing localized warning
  1820. * messages.
  1821. * @param keyword the keyword used to index the warning message
  1822. * within the set of <code>ResourceBundle</code>s.
  1823. *
  1824. * @exception IllegalArgumentException if <code>baseName</code>
  1825. * is <code>null</code>.
  1826. * @exception IllegalArgumentException if <code>keyword</code>
  1827. * is <code>null</code>.
  1828. * @exception IllegalArgumentException if no appropriate
  1829. * <code>ResourceBundle</code> may be located.
  1830. * @exception IllegalArgumentException if the named resource is
  1831. * not found in the located <code>ResourceBundle</code>.
  1832. * @exception IllegalArgumentException if the object retrieved
  1833. * from the <code>ResourceBundle</code> is not a
  1834. * <code>String</code>.
  1835. */
  1836. protected void processWarningOccurred(int imageIndex,
  1837. String baseName,
  1838. String keyword) {
  1839. if (warningListeners == null) {
  1840. return;
  1841. }
  1842. if (baseName == null) {
  1843. throw new IllegalArgumentException("baseName == null!");
  1844. }
  1845. if (keyword == null) {
  1846. throw new IllegalArgumentException("keyword == null!");
  1847. }
  1848. int numListeners = warningListeners.size();
  1849. for (int i = 0; i < numListeners; i++) {
  1850. IIOWriteWarningListener listener =
  1851. (IIOWriteWarningListener)warningListeners.get(i);
  1852. Locale locale = (Locale)warningLocales.get(i);
  1853. if (locale == null) {
  1854. locale = Locale.getDefault();
  1855. }
  1856. /**
  1857. * If an applet supplies an implementation of ImageWriter and
  1858. * resource bundles, then the resource bundle will need to be
  1859. * accessed via the applet class loader. So first try the context
  1860. * class loader to locate the resource bundle.
  1861. * If that throws MissingResourceException, then try the
  1862. * system class loader.
  1863. */
  1864. ClassLoader loader = (ClassLoader)
  1865. java.security.AccessController.doPrivileged(
  1866. new java.security.PrivilegedAction() {
  1867. public Object run() {
  1868. return Thread.currentThread().getContextClassLoader();
  1869. }
  1870. });
  1871. ResourceBundle bundle = null;
  1872. try {
  1873. bundle = ResourceBundle.getBundle(baseName, locale, loader);
  1874. } catch (MissingResourceException mre) {
  1875. try {
  1876. bundle = ResourceBundle.getBundle(baseName, locale);
  1877. } catch (MissingResourceException mre1) {
  1878. throw new IllegalArgumentException("Bundle not found!");
  1879. }
  1880. }
  1881. String warning = null;
  1882. try {
  1883. warning = bundle.getString(keyword);
  1884. } catch (ClassCastException cce) {
  1885. throw new IllegalArgumentException("Resource is not a String!");
  1886. } catch (MissingResourceException mre) {
  1887. throw new IllegalArgumentException("Resource is missing!");
  1888. }
  1889. listener.warningOccurred(this, imageIndex, warning);
  1890. }
  1891. }
  1892. // State management
  1893. /**
  1894. * Restores the <code>ImageWriter</code> to its initial state.
  1895. *
  1896. * <p> The default implementation calls
  1897. * <code>setOutput(null)</code>, <code>setLocale(null)</code>,
  1898. * <code>removeAllIIOWriteWarningListeners()</code>,
  1899. * <code>removeAllIIOWriteProgressListeners()</code>, and
  1900. * <code>clearAbortRequest</code>.
  1901. */
  1902. public void reset() {
  1903. setOutput(null);
  1904. setLocale(null);
  1905. removeAllIIOWriteWarningListeners();
  1906. removeAllIIOWriteProgressListeners();
  1907. clearAbortRequest();
  1908. }
  1909. /**
  1910. * Allows any resources held by this object to be released. The
  1911. * result of calling any other method (other than
  1912. * <code>finalize</code>) subsequent to a call to this method
  1913. * is undefined.
  1914. *
  1915. * <p>It is important for applications to call this method when they
  1916. * know they will no longer be using this <code>ImageWriter</code>.
  1917. * Otherwise, the writer may continue to hold on to resources
  1918. * indefinitely.
  1919. *
  1920. * <p>The default implementation of this method in the superclass does
  1921. * nothing. Subclass implementations should ensure that all resources,
  1922. * especially native resources, are released.
  1923. */
  1924. public void dispose() {
  1925. }
  1926. }