1 /*
2  * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * 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}s.
36  * For more information on service provider classes, see the class comment
37  * for the {@code IIORegistry} class.
38  *
39  * <p> Each {@code ImageWriterSpi} provides several types of information
40  * about the {@code ImageWriter} 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 getDescription},
45  * and {@code getVersion} 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 getFileSuffixes}, and
54  * {@code getMIMEType} methods.  These methods may be used to
55  * identify candidate {@code ImageWriter}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}s
60  * are likely to be able to parse a particular data stream is provided
61  * by the {@code canEncodeImage} method.  This methods allows the
62  * service provider to inspect the actual image contents.
63  *
64  * <p> Finally, an instance of the {@code ImageWriter} class
65  * associated with this service provider may be obtained by calling
66  * the {@code createWriterInstance} 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 ImageOutputStream.class}, to be returned from
81      * {@code getOutputTypes}.
82      * @deprecated Instead of using this field, directly create
83      * the equivalent array {@code { ImageOutputStream.class }}.
84      */
85     @Deprecated
86     public static final Class<?>[] STANDARD_OUTPUT_TYPE =
87         { ImageOutputStream.class };
88 
89     /**
90      * An array of {@code Class} objects to be returned from
91      * {@code getOutputTypes}, initially {@code null}.
92      */
93     protected Class<?>[] outputTypes = null;
94 
95     /**
96      * An array of strings to be returned from
97      * {@code getImageReaderSpiNames}, initially
98      * {@code null}.
99      */
100     protected String[] readerSpiNames = null;
101 
102     /**
103      * The {@code Class} of the writer, initially
104      * {@code null}.
105      */
106     private Class<?> writerClass = null;
107 
108     /**
109      * Constructs a blank {@code ImageWriterSpi}.  It is up to
110      * the subclass to initialize instance variables and/or override
111      * method implementations in order to provide working versions of
112      * all methods.
113      */
ImageWriterSpi()114     protected ImageWriterSpi() {
115     }
116 
117     /**
118      * Constructs an {@code ImageWriterSpi} with a given
119      * set of values.
120      *
121      * @param vendorName the vendor name, as a non-{@code null}
122      * {@code String}.
123      * @param version a version identifier, as a non-{@code null}
124      * {@code String}.
125      * @param names a non-{@code null} array of
126      * {@code String}s indicating the format names.  At least one
127      * entry must be present.
128      * @param suffixes an array of {@code String}s indicating the
129      * common file suffixes.  If no suffixes are defined,
130      * {@code null} should be supplied.  An array of length 0
131      * will be normalized to {@code null}.
132      * @param MIMETypes an array of {@code String}s indicating
133      * the format's MIME types.  If no suffixes are defined,
134      * {@code null} should be supplied.  An array of length 0
135      * will be normalized to {@code null}.
136      * @param writerClassName the fully-qualified name of the
137      * associated {@code ImageWriterSpi} class, as a
138      * non-{@code null String}.
139      * @param outputTypes an array of {@code Class} objects of
140      * length at least 1 indicating the legal output types.
141      * @param readerSpiNames an array {@code String}s of length
142      * at least 1 naming the classes of all associated
143      * {@code ImageReader}s, or {@code null}.  An array of
144      * length 0 is normalized to {@code null}.
145      * @param supportsStandardStreamMetadataFormat a
146      * {@code boolean} that indicates whether a stream metadata
147      * object can use trees described by the standard metadata format.
148      * @param nativeStreamMetadataFormatName a
149      * {@code String}, or {@code null}, to be returned from
150      * {@code getNativeStreamMetadataFormatName}.
151      * @param nativeStreamMetadataFormatClassName a
152      * {@code String}, or {@code null}, to be used to instantiate
153      * a metadata format object to be returned from
154      * {@code getNativeStreamMetadataFormat}.
155      * @param extraStreamMetadataFormatNames an array of
156      * {@code String}s, or {@code null}, to be returned from
157      * {@code getExtraStreamMetadataFormatNames}.  An array of length
158      * 0 is normalized to {@code null}.
159      * @param extraStreamMetadataFormatClassNames an array of
160      * {@code String}s, or {@code null}, to be used to instantiate
161      * a metadata format object to be returned from
162      * {@code getStreamMetadataFormat}.  An array of length
163      * 0 is normalized to {@code null}.
164      * @param supportsStandardImageMetadataFormat a
165      * {@code boolean} that indicates whether an image metadata
166      * object can use trees described by the standard metadata format.
167      * @param nativeImageMetadataFormatName a
168      * {@code String}, or {@code null}, to be returned from
169      * {@code getNativeImageMetadataFormatName}.
170      * @param nativeImageMetadataFormatClassName a
171      * {@code String}, or {@code null}, to be used to instantiate
172      * a metadata format object to be returned from
173      * {@code getNativeImageMetadataFormat}.
174      * @param extraImageMetadataFormatNames an array of
175      * {@code String}s to be returned from
176      * {@code getExtraImageMetadataFormatNames}.  An array of length 0
177      * is normalized to {@code null}.
178      * @param extraImageMetadataFormatClassNames an array of
179      * {@code String}s, or {@code null}, to be used to instantiate
180      * a metadata format object to be returned from
181      * {@code getImageMetadataFormat}.  An array of length
182      * 0 is normalized to {@code null}.
183      *
184      * @exception IllegalArgumentException if {@code vendorName}
185      * is {@code null}.
186      * @exception IllegalArgumentException if {@code version}
187      * is {@code null}.
188      * @exception IllegalArgumentException if {@code names}
189      * is {@code null} or has length 0.
190      * @exception IllegalArgumentException if {@code writerClassName}
191      * is {@code null}.
192      * @exception IllegalArgumentException if {@code outputTypes}
193      * is {@code null} or has length 0.
194      */
ImageWriterSpi(String vendorName, String version, String[] names, String[] suffixes, String[] MIMETypes, String writerClassName, Class<?>[] outputTypes, String[] readerSpiNames, boolean supportsStandardStreamMetadataFormat, String nativeStreamMetadataFormatName, String nativeStreamMetadataFormatClassName, String[] extraStreamMetadataFormatNames, String[] extraStreamMetadataFormatClassNames, boolean supportsStandardImageMetadataFormat, String nativeImageMetadataFormatName, String nativeImageMetadataFormatClassName, String[] extraImageMetadataFormatNames, String[] extraImageMetadataFormatClassNames)195     public ImageWriterSpi(String vendorName,
196                           String version,
197                           String[] names,
198                           String[] suffixes,
199                           String[] MIMETypes,
200                           String writerClassName,
201                           Class<?>[] outputTypes,
202                           String[] readerSpiNames,
203                           boolean supportsStandardStreamMetadataFormat,
204                           String nativeStreamMetadataFormatName,
205                           String nativeStreamMetadataFormatClassName,
206                           String[] extraStreamMetadataFormatNames,
207                           String[] extraStreamMetadataFormatClassNames,
208                           boolean supportsStandardImageMetadataFormat,
209                           String nativeImageMetadataFormatName,
210                           String nativeImageMetadataFormatClassName,
211                           String[] extraImageMetadataFormatNames,
212                           String[] extraImageMetadataFormatClassNames) {
213         super(vendorName, version,
214               names, suffixes, MIMETypes, writerClassName,
215               supportsStandardStreamMetadataFormat,
216               nativeStreamMetadataFormatName,
217               nativeStreamMetadataFormatClassName,
218               extraStreamMetadataFormatNames,
219               extraStreamMetadataFormatClassNames,
220               supportsStandardImageMetadataFormat,
221               nativeImageMetadataFormatName,
222               nativeImageMetadataFormatClassName,
223               extraImageMetadataFormatNames,
224               extraImageMetadataFormatClassNames);
225 
226         if (outputTypes == null) {
227             throw new IllegalArgumentException
228                 ("outputTypes == null!");
229         }
230         if (outputTypes.length == 0) {
231             throw new IllegalArgumentException
232                 ("outputTypes.length == 0!");
233         }
234 
235         this.outputTypes = (outputTypes == STANDARD_OUTPUT_TYPE) ?
236             new Class<?>[] { ImageOutputStream.class } :
237             outputTypes.clone();
238 
239         // If length == 0, leave it null
240         if (readerSpiNames != null && readerSpiNames.length > 0) {
241             this.readerSpiNames = readerSpiNames.clone();
242         }
243     }
244 
245     /**
246      * Returns {@code true} if the format that this writer
247      * outputs preserves pixel data bit-accurately.  The default
248      * implementation returns {@code true}.
249      *
250      * @return {@code true} if the format preserves full pixel
251      * accuracy.
252      */
isFormatLossless()253     public boolean isFormatLossless() {
254         return true;
255     }
256 
257     /**
258      * Returns an array of {@code Class} objects indicating what
259      * types of objects may be used as arguments to the writer's
260      * {@code setOutput} method.
261      *
262      * <p> For most writers, which only output to an
263      * {@code ImageOutputStream}, a single-element array
264      * containing {@code ImageOutputStream.class} should be
265      * returned.
266      *
267      * @return a non-{@code null} array of
268      * {@code Class} objects of length at least 1.
269      */
getOutputTypes()270     public Class<?>[] getOutputTypes() {
271         return outputTypes.clone();
272     }
273 
274     /**
275      * Returns {@code true} if the {@code ImageWriter}
276      * implementation associated with this service provider is able to
277      * encode an image with the given layout.  The layout
278      * (<i>i.e.</i>, the image's {@code SampleModel} and
279      * {@code ColorModel}) is described by an
280      * {@code ImageTypeSpecifier} object.
281      *
282      * <p> A return value of {@code true} is not an absolute
283      * guarantee of successful encoding; the encoding process may still
284      * produce errors due to factors such as I/O errors, inconsistent
285      * or malformed data structures, etc.  The intent is that a
286      * reasonable inspection of the basic structure of the image be
287      * performed in order to determine if it is within the scope of
288      * the encoding format.  For example, a service provider for a
289      * format that can only encode greyscale would return
290      * {@code false} if handed an RGB {@code BufferedImage}.
291      * Similarly, a service provider for a format that can encode
292      * 8-bit RGB imagery might refuse to encode an image with an
293      * associated alpha channel.
294      *
295      * <p> Different {@code ImageWriter}s, and thus service
296      * providers, may choose to be more or less strict.  For example,
297      * they might accept an image with premultiplied alpha even though
298      * it will have to be divided out of each pixel, at some loss of
299      * precision, in order to be stored.
300      *
301      * @param type an {@code ImageTypeSpecifier} specifying the
302      * layout of the image to be written.
303      *
304      * @return {@code true} if this writer is likely to be able
305      * to encode images with the given layout.
306      *
307      * @exception IllegalArgumentException if {@code type}
308      * is {@code null}.
309      */
canEncodeImage(ImageTypeSpecifier type)310     public abstract boolean canEncodeImage(ImageTypeSpecifier type);
311 
312     /**
313      * Returns {@code true} if the {@code ImageWriter}
314      * implementation associated with this service provider is able to
315      * encode the given {@code RenderedImage} instance.  Note
316      * that this includes instances of
317      * {@code java.awt.image.BufferedImage}.
318      *
319      * <p> See the discussion for
320      * {@code canEncodeImage(ImageTypeSpecifier)} for information
321      * on the semantics of this method.
322      *
323      * @param im an instance of {@code RenderedImage} to be encoded.
324      *
325      * @return {@code true} if this writer is likely to be able
326      * to encode this image.
327      *
328      * @exception IllegalArgumentException if {@code im}
329      * is {@code null}.
330      */
canEncodeImage(RenderedImage im)331     public boolean canEncodeImage(RenderedImage im) {
332         return canEncodeImage(ImageTypeSpecifier.createFromRenderedImage(im));
333     }
334 
335     /**
336      * Returns an instance of the {@code ImageWriter}
337      * implementation associated with this service provider.
338      * The returned object will initially be in an initial state as if
339      * its {@code reset} method had been called.
340      *
341      * <p> The default implementation simply returns
342      * {@code createWriterInstance(null)}.
343      *
344      * @return an {@code ImageWriter} instance.
345      *
346      * @exception IOException if an error occurs during loading,
347      * or initialization of the writer class, or during instantiation
348      * or initialization of the writer object.
349      */
createWriterInstance()350     public ImageWriter createWriterInstance() throws IOException {
351         return createWriterInstance(null);
352     }
353 
354     /**
355      * Returns an instance of the {@code ImageWriter}
356      * implementation associated with this service provider.
357      * The returned object will initially be in an initial state
358      * as if its {@code reset} method had been called.
359      *
360      * <p> An {@code Object} may be supplied to the plug-in at
361      * construction time.  The nature of the object is entirely
362      * plug-in specific.
363      *
364      * <p> Typically, a plug-in will implement this method using code
365      * such as {@code return new MyImageWriter(this)}.
366      *
367      * @param extension a plug-in specific extension object, which may
368      * be {@code null}.
369      *
370      * @return an {@code ImageWriter} instance.
371      *
372      * @exception IOException if the attempt to instantiate
373      * the writer fails.
374      * @exception IllegalArgumentException if the
375      * {@code ImageWriter}'s constructor throws an
376      * {@code IllegalArgumentException} to indicate that the
377      * extension object is unsuitable.
378      */
createWriterInstance(Object extension)379     public abstract ImageWriter createWriterInstance(Object extension)
380         throws IOException;
381 
382     /**
383      * Returns {@code true} if the {@code ImageWriter} object
384      * passed in is an instance of the {@code ImageWriter}
385      * associated with this service provider.
386      *
387      * @param writer an {@code ImageWriter} instance.
388      *
389      * @return {@code true} if {@code writer} is recognized
390      *
391      * @exception IllegalArgumentException if {@code writer} is
392      * {@code null}.
393      */
isOwnWriter(ImageWriter writer)394     public boolean isOwnWriter(ImageWriter writer) {
395         if (writer == null) {
396             throw new IllegalArgumentException("writer == null!");
397         }
398         String name = writer.getClass().getName();
399         return name.equals(pluginClassName);
400     }
401 
402     /**
403      * Returns an array of {@code String}s containing all the
404      * fully qualified names of all the {@code ImageReaderSpi}
405      * classes that can understand the internal metadata
406      * representation used by the {@code ImageWriter} associated
407      * with this service provider, or {@code null} if there are
408      * no such {@code ImageReaders} specified.  If a
409      * non-{@code null} value is returned, it must have non-zero
410      * length.
411      *
412      * <p> The first item in the array must be the name of the service
413      * provider for the "preferred" reader, as it will be used to
414      * instantiate the {@code ImageReader} returned by
415      * {@code ImageIO.getImageReader(ImageWriter)}.
416      *
417      * <p> This mechanism may be used to obtain
418      * {@code ImageReaders} that will generated non-pixel
419      * meta-data (see {@code IIOExtraDataInfo}) in a structure
420      * understood by an {@code ImageWriter}.  By reading the
421      * image and obtaining this data from one of the
422      * {@code ImageReaders} obtained with this method and passing
423      * it on to the {@code ImageWriter}, a client program can
424      * read an image, modify it in some way, and write it back out
425      * preserving all meta-data, without having to understand anything
426      * about the internal structure of the meta-data, or even about
427      * the image format.
428      *
429      * @return an array of {@code String}s of length at least 1
430      * containing names of {@code ImageReaderSpi}s, or
431      * {@code null}.
432      *
433      * @see javax.imageio.ImageIO#getImageReader(ImageWriter)
434      * @see ImageReaderSpi#getImageWriterSpiNames()
435      */
getImageReaderSpiNames()436     public String[] getImageReaderSpiNames() {
437         return readerSpiNames == null ?
438             null : readerSpiNames.clone();
439     }
440 }
441