1. /*
  2. * @(#)ImageWriterSpi.java 1.37 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.imageio.spi;
  8. import java.awt.image.RenderedImage;
  9. import java.io.IOException;
  10. import javax.imageio.ImageTypeSpecifier;
  11. import javax.imageio.ImageWriter;
  12. import javax.imageio.stream.ImageOutputStream;
  13. /**
  14. * The service provider interface (SPI) for <code>ImageWriter</code>s.
  15. * For more information on service provider classes, see the class comment
  16. * for the <code>IIORegistry</code> class.
  17. *
  18. * <p> Each <code>ImageWriterSpi</code> provides several types of information
  19. * about the <code>ImageWriter</code> class with which it is associated.
  20. *
  21. * <p> The name of the vendor who defined the SPI class and a
  22. * brief description of the class are available via the
  23. * <code>getVendorName</code>, <code>getDescription</code>,
  24. * and <code>getVersion</code> methods.
  25. * These methods may be internationalized to provide locale-specific
  26. * output. These methods are intended mainly to provide short,
  27. * human-writable information that might be used to organize a pop-up
  28. * menu or other list.
  29. *
  30. * <p> Lists of format names, file suffixes, and MIME types associated
  31. * with the service may be obtained by means of the
  32. * <code>getFormatNames</code>, <code>getFileSuffixes</code>, and
  33. * <code>getMIMEType</code> methods. These methods may be used to
  34. * identify candidate <code>ImageWriter</code>s for writing a
  35. * particular file or stream based on manual format selection, file
  36. * naming, or MIME associations.
  37. *
  38. * <p> A more reliable way to determine which <code>ImageWriter</code>s
  39. * are likely to be able to parse a particular data stream is provided
  40. * by the <code>canEncodeImage</code> method. This methods allows the
  41. * service provider to inspect the actual image contents.
  42. *
  43. * <p> Finally, an instance of the <code>ImageWriter</code> class
  44. * associated with this service provider may be obtained by calling
  45. * the <code>createWriterInstance</code> method. Any heavyweight
  46. * initialization, such as the loading of native libraries or creation
  47. * of large tables, should be deferred at least until the first
  48. * invocation of this method.
  49. *
  50. * @see IIORegistry
  51. * @see javax.imageio.ImageTypeSpecifier
  52. * @see javax.imageio.ImageWriter
  53. *
  54. * @version 0.5
  55. */
  56. public abstract class ImageWriterSpi extends ImageReaderWriterSpi {
  57. /**
  58. * A single-element array, initially containing
  59. * <code>ImageInputStream.class</code>, to be returned from
  60. * <code>getInputTypes</code>.
  61. */
  62. public static final Class[] STANDARD_OUTPUT_TYPE =
  63. { ImageOutputStream.class };
  64. /**
  65. * An array of <code>Class</code> objects to be returned from
  66. * <code>getOutputTypes</code>, initially <code>null</code>.
  67. */
  68. protected Class[] outputTypes = null;
  69. /**
  70. * An array of strings to be returned from
  71. * <code>getImageReaderSpiNames</code>, initially
  72. * <code>null</code>.
  73. */
  74. protected String[] readerSpiNames = null;
  75. /**
  76. * The <code>Class</code> of the writer, initially
  77. * <code>null</code>.
  78. */
  79. private Class writerClass = null;
  80. /**
  81. * Constructs a blank <code>ImageWriterSpi</code>. It is up to
  82. * the subclass to initialize instance variables and/or override
  83. * method implementations in order to provide working versions of
  84. * all methods.
  85. */
  86. protected ImageWriterSpi() {
  87. }
  88. /**
  89. * Constructs an <code>ImageWriterSpi</code> with a given
  90. * set of values.
  91. *
  92. * @param vendorName the vendor name, as a non-<code>null</code>
  93. * <code>String</code>.
  94. * @param version a version identifier, as a non-<code>null</code>
  95. * <code>String</code>.
  96. * @param names a non-<code>null</code> array of
  97. * <code>String</code>s indicating the format names. At least one
  98. * entry must be present.
  99. * @param suffixes an array of <code>String</code>s indicating the
  100. * common file suffixes. If no suffixes are defined,
  101. * <code>null</code> should be supplied. An array of length 0
  102. * will be normalized to <code>null</code>.
  103. * @param MIMETypes an array of <code>String</code>s indicating
  104. * the format's MIME types. If no suffixes are defined,
  105. * <code>null</code> should be supplied. An array of length 0
  106. * will be normalized to <code>null</code>.
  107. * @param writerClassName the fully-qualified name of the
  108. * associated <code>ImageWriterSpi</code> class, as a
  109. * non-<code>null</code> <code>String</code>.
  110. * @param outputTypes an array of <code>Class</code> objects of
  111. * length at least 1 indicating the legal output types.
  112. * @param readerSpiNames an array <code>String</code>s of length
  113. * at least 1 naming the classes of all associated
  114. * <code>ImageReader</code>s, or <code>null</code>. An array of
  115. * length 0 is normalized to <code>null</code>.
  116. * @param supportsStandardStreamMetadataFormat a
  117. * <code>boolean</code> that indicates whether a stream metadata
  118. * object can use trees described by the standard metadata format.
  119. * @param nativeStreamMetadataFormatName a
  120. * <code>String</code>, or <code>null</code>, to be returned from
  121. * <code>getNativeStreamMetadataFormatName</code>.
  122. * @param nativeStreamMetadataFormatClassName a
  123. * <code>String</code>, or <code>null</code>, to be used to instantiate
  124. * a metadata format object to be returned from
  125. * <code>getNativeStreamMetadataFormat</code>.
  126. * @param extraStreamMetadataFormatNames an array of
  127. * <code>String</code>s, or <code>null</code>, to be returned from
  128. * <code>getExtraStreamMetadataFormatNames</code>. An array of length
  129. * 0 is normalized to <code>null</code>.
  130. * @param extraStreamMetadataFormatClassNames an array of
  131. * <code>String</code>s, or <code>null</code>, to be used to instantiate
  132. * a metadata format object to be returned from
  133. * <code>getStreamMetadataFormat</code>. An array of length
  134. * 0 is normalized to <code>null</code>.
  135. * @param supportsStandardImageMetadataFormat a
  136. * <code>boolean</code> that indicates whether an image metadata
  137. * object can use trees described by the standard metadata format.
  138. * @param nativeImageMetadataFormatName a
  139. * <code>String</code>, or <code>null</code>, to be returned from
  140. * <code>getNativeImageMetadataFormatName</code>.
  141. * @param nativeImageMetadataFormatClassName a
  142. * <code>String</code>, or <code>null</code>, to be used to instantiate
  143. * a metadata format object to be returned from
  144. * <code>getNativeImageMetadataFormat</code>.
  145. * @param extraImageMetadataFormatNames an array of
  146. * <code>String</code>s to be returned from
  147. * <code>getExtraImageMetadataFormatNames</code>. An array of length 0
  148. * is normalized to <code>null</code>.
  149. * @param extraImageMetadataFormatClassNames an array of
  150. * <code>String</code>s, or <code>null</code>, to be used to instantiate
  151. * a metadata format object to be returned from
  152. * <code>getImageMetadataFormat</code>. An array of length
  153. * 0 is normalized to <code>null</code>.
  154. *
  155. * @exception IllegalArgumentException if <code>vendorName</code>
  156. * is <code>null</code>.
  157. * @exception IllegalArgumentException if <code>version</code>
  158. * is <code>null</code>.
  159. * @exception IllegalArgumentException if <code>names</code>
  160. * is <code>null</code> or has length 0.
  161. * @exception IllegalArgumentException if <code>writerClassName</code>
  162. * is <code>null</code>.
  163. * @exception IllegalArgumentException if <code>outputTypes</code>
  164. * is <code>null</code> or has length 0.
  165. */
  166. public ImageWriterSpi(String vendorName,
  167. String version,
  168. String[] names,
  169. String[] suffixes,
  170. String[] MIMETypes,
  171. String writerClassName,
  172. Class[] outputTypes,
  173. String[] readerSpiNames,
  174. boolean supportsStandardStreamMetadataFormat,
  175. String nativeStreamMetadataFormatName,
  176. String nativeStreamMetadataFormatClassName,
  177. String[] extraStreamMetadataFormatNames,
  178. String[] extraStreamMetadataFormatClassNames,
  179. boolean supportsStandardImageMetadataFormat,
  180. String nativeImageMetadataFormatName,
  181. String nativeImageMetadataFormatClassName,
  182. String[] extraImageMetadataFormatNames,
  183. String[] extraImageMetadataFormatClassNames) {
  184. super(vendorName, version,
  185. names, suffixes, MIMETypes, writerClassName,
  186. supportsStandardStreamMetadataFormat,
  187. nativeStreamMetadataFormatName,
  188. nativeStreamMetadataFormatClassName,
  189. extraStreamMetadataFormatNames,
  190. extraStreamMetadataFormatClassNames,
  191. supportsStandardImageMetadataFormat,
  192. nativeImageMetadataFormatName,
  193. nativeImageMetadataFormatClassName,
  194. extraImageMetadataFormatNames,
  195. extraImageMetadataFormatClassNames);
  196. if (outputTypes == null) {
  197. throw new IllegalArgumentException
  198. ("outputTypes == null!");
  199. }
  200. if (outputTypes.length == 0) {
  201. throw new IllegalArgumentException
  202. ("outputTypes.length == 0!");
  203. }
  204. this.outputTypes = (Class[])outputTypes.clone();
  205. // If length == 0, leave it null
  206. if (readerSpiNames != null && readerSpiNames.length > 0) {
  207. this.readerSpiNames = (String[])readerSpiNames.clone();
  208. }
  209. }
  210. /**
  211. * Returns <code>true</code> if the format that this writer
  212. * outputs preserves pixel data bit-accurately. The default
  213. * implementation returns <code>true</code>.
  214. *
  215. * @return <code>true</code> if the format preserves full pixel
  216. * accuracy.
  217. */
  218. public boolean isFormatLossless() {
  219. return true;
  220. }
  221. /**
  222. * Returns an array of <code>Class</code> objects indicating what
  223. * types of objects may be used as arguments to the writer's
  224. * <code>setOutput</code> method.
  225. *
  226. * <p> For most writers, which only output to an
  227. * <code>ImageOutputStream</code>, a single-element array
  228. * containing <code>ImageOutputStream.class</code> should be
  229. * returned.
  230. *
  231. * @return a non-<code>null</code> array of
  232. * <code>Class</code>objects of length at least 1.
  233. */
  234. public Class[] getOutputTypes() {
  235. return (Class[])outputTypes.clone();
  236. }
  237. /**
  238. * Returns <code>true</code> if the <code>ImageWriter</code>
  239. * implementation associated with this service provider is able to
  240. * encode an image with the given layout. The layout
  241. * (<i>i.e.</i>, the image's <code>SampleModel</code> and
  242. * <code>ColorModel</code>) is described by an
  243. * <code>ImageTypeSpecifier</code> object.
  244. *
  245. * <p> A return value of <code>true</code> is not an absolute
  246. * guarantee of successful encoding; the encoding process may still
  247. * produce errors due to factors such as I/O errors, inconsistent
  248. * or malformed data structures, etc. The intent is that a
  249. * reasonable inspection of the basic structure of the image be
  250. * performed in order to determine if it is within the scope of
  251. * the encoding format. For example, a service provider for a
  252. * format that can only encode greyscale would return
  253. * <code>false</code> if handed an RGB <code>BufferedImage</code>.
  254. * Similarly, a service provider for a format that can encode
  255. * 8-bit RGB imagery might refuse to encode an image with an
  256. * associated alpha channel.
  257. *
  258. * <p> Different <code>ImageWriter</code>s, and thus service
  259. * providers, may choose to be more or less strict. For example,
  260. * they might accept an image with premultiplied alpha even though
  261. * it will have to be divided out of each pixel, at some loss of
  262. * precision, in order to be stored.
  263. *
  264. * @param type an <code>ImageTypeSpecifier</code> specifying the
  265. * layout of the image to be written.
  266. *
  267. * @return <code>true</code> if this writer is likely to be able
  268. * to encode images with the given layout.
  269. *
  270. * @exception IllegalArgumentException if <code>type</code>
  271. * is <code>null</code>.
  272. */
  273. public abstract boolean canEncodeImage(ImageTypeSpecifier type);
  274. /**
  275. * Returns <code>true</code> if the <code>ImageWriter</code>
  276. * implementation associated with this service provider is able to
  277. * encode the given <code>RenderedImage</code> instance. Note
  278. * that this includes instances of
  279. * <code>java.awt.image.BufferedImage</code>.
  280. *
  281. * <p> See the discussion for
  282. * <code>canEncodeImage(ImageTypeSpecifier)</code> for information
  283. * on the semantics of this method.
  284. *
  285. * @param im an instance of <code>RenderedImage</code> to be encoded.
  286. *
  287. * @return <code>true</code> if this writer is likely to be able
  288. * to encode this image.
  289. *
  290. * @exception IllegalArgumentException if <code>im</code>
  291. * is <code>null</code>.
  292. */
  293. public boolean canEncodeImage(RenderedImage im) {
  294. return canEncodeImage(ImageTypeSpecifier.createFromRenderedImage(im));
  295. }
  296. /**
  297. * Returns an instance of the <code>ImageWriter</code>
  298. * implementation associated with this service provider.
  299. * The returned object will initially be in an initial state as if
  300. * its <code>reset</code> method had been called.
  301. *
  302. * <p> The default implementation simply returns
  303. * <code>createWriterInstance(null)</code>.
  304. *
  305. * @return an <code>ImageWriter</code> instance.
  306. *
  307. * @exception IOException if an error occurs during loading,
  308. * or initialization of the writer class, or during instantiation
  309. * or initialization of the writer object.
  310. */
  311. public ImageWriter createWriterInstance() throws IOException {
  312. return createWriterInstance(null);
  313. }
  314. /**
  315. * Returns an instance of the <code>ImageWriter</code>
  316. * implementation associated with this service provider.
  317. * The returned object will initially be in an initial state
  318. * as if its <code>reset</code> method had been called.
  319. *
  320. * <p> An <code>Object</code> may be supplied to the plug-in at
  321. * construction time. The nature of the object is entirely
  322. * plug-in specific.
  323. *
  324. * <p> Typically, a plug-in will implement this method using code
  325. * such as <code>return new MyImageWriter(this)</code>.
  326. *
  327. * @param extension a plug-in specific extension object, which may
  328. * be <code>null</code>.
  329. *
  330. * @return an <code>ImageWriter</code> instance.
  331. *
  332. * @exception IOException if the attempt to instantiate
  333. * the writer fails.
  334. * @exception IllegalArgumentException if the
  335. * <code>ImageWriter</code>'s constructor throws an
  336. * <code>IllegalArgumentException</code> to indicate that the
  337. * extension object is unsuitable.
  338. */
  339. public abstract ImageWriter createWriterInstance(Object extension)
  340. throws IOException;
  341. /**
  342. * Returns <code>true</code> if the <code>ImageWriter</code> object
  343. * passed in is an instance of the <code>ImageWriter</code>
  344. * associated with this service provider.
  345. *
  346. * @param writer an <code>ImageWriter</code> instance.
  347. *
  348. * @return <code>true</code> if <code>writer</code> is recognized
  349. *
  350. * @exception IllegalArgumentException if <code>writer</code> is
  351. * <code>null</code>.
  352. */
  353. public boolean isOwnWriter(ImageWriter writer) {
  354. if (writer == null) {
  355. throw new IllegalArgumentException("writer == null!");
  356. }
  357. String name = writer.getClass().getName();
  358. return name.equals(pluginClassName);
  359. }
  360. /**
  361. * Returns an array of <code>String</code>s containing all the
  362. * fully qualified names of all the <code>ImageReaderSpi</code>
  363. * classes that can understand the internal metadata
  364. * representation used by the <code>ImageWriter</code> associated
  365. * with this service provider, or <code>null</code> if there are
  366. * no such <code>ImageReaders</code> specified. If a
  367. * non-<code>null</code> value is returned, it must have non-zero
  368. * length.
  369. *
  370. * <p> The first item in the array must be the name of the service
  371. * provider for the "preferred" reader, as it will be used to
  372. * instantiate the <code>ImageReader</code> returned by
  373. * <code>ImageIO.getImageReader(ImageWriter)</code>.
  374. *
  375. * <p> This mechanism may be used to obtain
  376. * <code>ImageReaders</code> that will generated non-pixel
  377. * meta-data (see <code>IIOExtraDataInfo</code>) in a structure
  378. * understood by an <code>ImageWriter</code>. By reading the
  379. * image and obtaining this data from one of the
  380. * <code>ImageReaders</code> obtained with this method and passing
  381. * it on to the <code>ImageWriter</code>, a client program can
  382. * read an image, modify it in some way, and write it back out
  383. * preserving all meta-data, without having to understand anything
  384. * about the internal structure of the meta-data, or even about
  385. * the image format.
  386. *
  387. * @return an array of <code>String</code>s of length at least 1
  388. * containing names of <code>ImageReaderSpi</code>s, or
  389. * <code>null</code>.
  390. *
  391. * @see javax.imageio.ImageIO#getImageReader(ImageWriter)
  392. * @see ImageReaderSpi#getImageWriterSpiNames()
  393. */
  394. public String[] getImageReaderSpiNames() {
  395. return readerSpiNames == null ?
  396. null : (String[])readerSpiNames.clone();
  397. }
  398. }