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