001 /*
002 * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.imageio.spi;
027
028 import java.awt.image.RenderedImage;
029 import java.io.IOException;
030 import javax.imageio.ImageTypeSpecifier;
031 import javax.imageio.ImageWriter;
032 import javax.imageio.stream.ImageOutputStream;
033
034 /**
035 * The service provider interface (SPI) for <code>ImageWriter</code>s.
036 * For more information on service provider classes, see the class comment
037 * for the <code>IIORegistry</code> class.
038 *
039 * <p> Each <code>ImageWriterSpi</code> provides several types of information
040 * about the <code>ImageWriter</code> class with which it is associated.
041 *
042 * <p> The name of the vendor who defined the SPI class and a
043 * brief description of the class are available via the
044 * <code>getVendorName</code>, <code>getDescription</code>,
045 * and <code>getVersion</code> methods.
046 * These methods may be internationalized to provide locale-specific
047 * output. These methods are intended mainly to provide short,
048 * human-writable information that might be used to organize a pop-up
049 * menu or other list.
050 *
051 * <p> Lists of format names, file suffixes, and MIME types associated
052 * with the service may be obtained by means of the
053 * <code>getFormatNames</code>, <code>getFileSuffixes</code>, and
054 * <code>getMIMEType</code> methods. These methods may be used to
055 * identify candidate <code>ImageWriter</code>s for writing a
056 * particular file or stream based on manual format selection, file
057 * naming, or MIME associations.
058 *
059 * <p> A more reliable way to determine which <code>ImageWriter</code>s
060 * are likely to be able to parse a particular data stream is provided
061 * by the <code>canEncodeImage</code> method. This methods allows the
062 * service provider to inspect the actual image contents.
063 *
064 * <p> Finally, an instance of the <code>ImageWriter</code> class
065 * associated with this service provider may be obtained by calling
066 * the <code>createWriterInstance</code> method. Any heavyweight
067 * initialization, such as the loading of native libraries or creation
068 * of large tables, should be deferred at least until the first
069 * invocation of this method.
070 *
071 * @see IIORegistry
072 * @see javax.imageio.ImageTypeSpecifier
073 * @see javax.imageio.ImageWriter
074 *
075 * @version 0.5
076 */
077 public abstract class ImageWriterSpi extends ImageReaderWriterSpi {
078
079 /**
080 * A single-element array, initially containing
081 * <code>ImageInputStream.class</code>, to be returned from
082 * <code>getInputTypes</code>.
083 */
084 public static final Class[] STANDARD_OUTPUT_TYPE = { ImageOutputStream.class };
085
086 /**
087 * An array of <code>Class</code> objects to be returned from
088 * <code>getOutputTypes</code>, initially <code>null</code>.
089 */
090 protected Class[] outputTypes = null;
091
092 /**
093 * An array of strings to be returned from
094 * <code>getImageReaderSpiNames</code>, initially
095 * <code>null</code>.
096 */
097 protected String[] readerSpiNames = null;
098
099 /**
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, String version,
193 String[] names, String[] suffixes, String[] MIMETypes,
194 String writerClassName, Class[] outputTypes,
195 String[] readerSpiNames,
196 boolean supportsStandardStreamMetadataFormat,
197 String nativeStreamMetadataFormatName,
198 String nativeStreamMetadataFormatClassName,
199 String[] extraStreamMetadataFormatNames,
200 String[] extraStreamMetadataFormatClassNames,
201 boolean supportsStandardImageMetadataFormat,
202 String nativeImageMetadataFormatName,
203 String nativeImageMetadataFormatClassName,
204 String[] extraImageMetadataFormatNames,
205 String[] extraImageMetadataFormatClassNames) {
206 super (vendorName, version, names, suffixes, MIMETypes,
207 writerClassName, supportsStandardStreamMetadataFormat,
208 nativeStreamMetadataFormatName,
209 nativeStreamMetadataFormatClassName,
210 extraStreamMetadataFormatNames,
211 extraStreamMetadataFormatClassNames,
212 supportsStandardImageMetadataFormat,
213 nativeImageMetadataFormatName,
214 nativeImageMetadataFormatClassName,
215 extraImageMetadataFormatNames,
216 extraImageMetadataFormatClassNames);
217
218 if (outputTypes == null) {
219 throw new IllegalArgumentException("outputTypes == null!");
220 }
221 if (outputTypes.length == 0) {
222 throw new IllegalArgumentException(
223 "outputTypes.length == 0!");
224 }
225 this .outputTypes = (Class[]) outputTypes.clone();
226 // If length == 0, leave it null
227 if (readerSpiNames != null && readerSpiNames.length > 0) {
228 this .readerSpiNames = (String[]) readerSpiNames.clone();
229 }
230 }
231
232 /**
233 * Returns <code>true</code> if the format that this writer
234 * outputs preserves pixel data bit-accurately. The default
235 * implementation returns <code>true</code>.
236 *
237 * @return <code>true</code> if the format preserves full pixel
238 * accuracy.
239 */
240 public boolean isFormatLossless() {
241 return true;
242 }
243
244 /**
245 * Returns an array of <code>Class</code> objects indicating what
246 * types of objects may be used as arguments to the writer's
247 * <code>setOutput</code> method.
248 *
249 * <p> For most writers, which only output to an
250 * <code>ImageOutputStream</code>, a single-element array
251 * containing <code>ImageOutputStream.class</code> should be
252 * returned.
253 *
254 * @return a non-<code>null</code> array of
255 * <code>Class</code>objects of length at least 1.
256 */
257 public Class[] getOutputTypes() {
258 return (Class[]) outputTypes.clone();
259 }
260
261 /**
262 * Returns <code>true</code> if the <code>ImageWriter</code>
263 * implementation associated with this service provider is able to
264 * encode an image with the given layout. The layout
265 * (<i>i.e.</i>, the image's <code>SampleModel</code> and
266 * <code>ColorModel</code>) is described by an
267 * <code>ImageTypeSpecifier</code> object.
268 *
269 * <p> A return value of <code>true</code> is not an absolute
270 * guarantee of successful encoding; the encoding process may still
271 * produce errors due to factors such as I/O errors, inconsistent
272 * or malformed data structures, etc. The intent is that a
273 * reasonable inspection of the basic structure of the image be
274 * performed in order to determine if it is within the scope of
275 * the encoding format. For example, a service provider for a
276 * format that can only encode greyscale would return
277 * <code>false</code> if handed an RGB <code>BufferedImage</code>.
278 * Similarly, a service provider for a format that can encode
279 * 8-bit RGB imagery might refuse to encode an image with an
280 * associated alpha channel.
281 *
282 * <p> Different <code>ImageWriter</code>s, and thus service
283 * providers, may choose to be more or less strict. For example,
284 * they might accept an image with premultiplied alpha even though
285 * it will have to be divided out of each pixel, at some loss of
286 * precision, in order to be stored.
287 *
288 * @param type an <code>ImageTypeSpecifier</code> specifying the
289 * layout of the image to be written.
290 *
291 * @return <code>true</code> if this writer is likely to be able
292 * to encode images with the given layout.
293 *
294 * @exception IllegalArgumentException if <code>type</code>
295 * is <code>null</code>.
296 */
297 public abstract boolean canEncodeImage(ImageTypeSpecifier type);
298
299 /**
300 * Returns <code>true</code> if the <code>ImageWriter</code>
301 * implementation associated with this service provider is able to
302 * encode the given <code>RenderedImage</code> instance. Note
303 * that this includes instances of
304 * <code>java.awt.image.BufferedImage</code>.
305 *
306 * <p> See the discussion for
307 * <code>canEncodeImage(ImageTypeSpecifier)</code> for information
308 * on the semantics of this method.
309 *
310 * @param im an instance of <code>RenderedImage</code> to be encoded.
311 *
312 * @return <code>true</code> if this writer is likely to be able
313 * to encode this image.
314 *
315 * @exception IllegalArgumentException if <code>im</code>
316 * is <code>null</code>.
317 */
318 public boolean canEncodeImage(RenderedImage im) {
319 return canEncodeImage(ImageTypeSpecifier
320 .createFromRenderedImage(im));
321 }
322
323 /**
324 * Returns an instance of the <code>ImageWriter</code>
325 * implementation associated with this service provider.
326 * The returned object will initially be in an initial state as if
327 * its <code>reset</code> method had been called.
328 *
329 * <p> The default implementation simply returns
330 * <code>createWriterInstance(null)</code>.
331 *
332 * @return an <code>ImageWriter</code> instance.
333 *
334 * @exception IOException if an error occurs during loading,
335 * or initialization of the writer class, or during instantiation
336 * or initialization of the writer object.
337 */
338 public ImageWriter createWriterInstance() throws IOException {
339 return createWriterInstance(null);
340 }
341
342 /**
343 * Returns an instance of the <code>ImageWriter</code>
344 * implementation associated with this service provider.
345 * The returned object will initially be in an initial state
346 * as if its <code>reset</code> method had been called.
347 *
348 * <p> An <code>Object</code> may be supplied to the plug-in at
349 * construction time. The nature of the object is entirely
350 * plug-in specific.
351 *
352 * <p> Typically, a plug-in will implement this method using code
353 * such as <code>return new MyImageWriter(this)</code>.
354 *
355 * @param extension a plug-in specific extension object, which may
356 * be <code>null</code>.
357 *
358 * @return an <code>ImageWriter</code> instance.
359 *
360 * @exception IOException if the attempt to instantiate
361 * the writer fails.
362 * @exception IllegalArgumentException if the
363 * <code>ImageWriter</code>'s constructor throws an
364 * <code>IllegalArgumentException</code> to indicate that the
365 * extension object is unsuitable.
366 */
367 public abstract ImageWriter createWriterInstance(Object extension)
368 throws IOException;
369
370 /**
371 * Returns <code>true</code> if the <code>ImageWriter</code> object
372 * passed in is an instance of the <code>ImageWriter</code>
373 * associated with this service provider.
374 *
375 * @param writer an <code>ImageWriter</code> instance.
376 *
377 * @return <code>true</code> if <code>writer</code> is recognized
378 *
379 * @exception IllegalArgumentException if <code>writer</code> is
380 * <code>null</code>.
381 */
382 public boolean isOwnWriter(ImageWriter writer) {
383 if (writer == null) {
384 throw new IllegalArgumentException("writer == null!");
385 }
386 String name = writer.getClass().getName();
387 return name.equals(pluginClassName);
388 }
389
390 /**
391 * Returns an array of <code>String</code>s containing all the
392 * fully qualified names of all the <code>ImageReaderSpi</code>
393 * classes that can understand the internal metadata
394 * representation used by the <code>ImageWriter</code> associated
395 * with this service provider, or <code>null</code> if there are
396 * no such <code>ImageReaders</code> specified. If a
397 * non-<code>null</code> value is returned, it must have non-zero
398 * length.
399 *
400 * <p> The first item in the array must be the name of the service
401 * provider for the "preferred" reader, as it will be used to
402 * instantiate the <code>ImageReader</code> returned by
403 * <code>ImageIO.getImageReader(ImageWriter)</code>.
404 *
405 * <p> This mechanism may be used to obtain
406 * <code>ImageReaders</code> that will generated non-pixel
407 * meta-data (see <code>IIOExtraDataInfo</code>) in a structure
408 * understood by an <code>ImageWriter</code>. By reading the
409 * image and obtaining this data from one of the
410 * <code>ImageReaders</code> obtained with this method and passing
411 * it on to the <code>ImageWriter</code>, a client program can
412 * read an image, modify it in some way, and write it back out
413 * preserving all meta-data, without having to understand anything
414 * about the internal structure of the meta-data, or even about
415 * the image format.
416 *
417 * @return an array of <code>String</code>s of length at least 1
418 * containing names of <code>ImageReaderSpi</code>s, or
419 * <code>null</code>.
420 *
421 * @see javax.imageio.ImageIO#getImageReader(ImageWriter)
422 * @see ImageReaderSpi#getImageWriterSpiNames()
423 */
424 public String[] getImageReaderSpiNames() {
425 return readerSpiNames == null ? null
426 : (String[]) readerSpiNames.clone();
427 }
428 }
|