View Javadoc
1   /*
2    * Copyright (c) 1999, 2013, 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</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>ImageOutputStream.class</code>, to be returned from
81       * <code>getOutputTypes</code>.
82       * @deprecated Instead of using this field, directly create
83       * the equivalent array <code>{ ImageOutputStream.class }</code>.
84       */
85      @Deprecated
86      public static final Class[] STANDARD_OUTPUT_TYPE =
87          { ImageOutputStream.class };
88  
89      /**
90       * An array of <code>Class</code> objects to be returned from
91       * <code>getOutputTypes</code>, initially <code>null</code>.
92       */
93      protected Class[] outputTypes = null;
94  
95      /**
96       * An array of strings to be returned from
97       * <code>getImageReaderSpiNames</code>, initially
98       * <code>null</code>.
99       */
100     protected String[] readerSpiNames = null;
101 
102     /**
103      * The <code>Class</code> of the writer, initially
104      * <code>null</code>.
105      */
106     private Class writerClass = null;
107 
108     /**
109      * Constructs a blank <code>ImageWriterSpi</code>.  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      */
114     protected ImageWriterSpi() {
115     }
116 
117     /**
118      * Constructs an <code>ImageWriterSpi</code> with a given
119      * set of values.
120      *
121      * @param vendorName the vendor name, as a non-<code>null</code>
122      * <code>String</code>.
123      * @param version a version identifier, as a non-<code>null</code>
124      * <code>String</code>.
125      * @param names a non-<code>null</code> array of
126      * <code>String</code>s indicating the format names.  At least one
127      * entry must be present.
128      * @param suffixes an array of <code>String</code>s indicating the
129      * common file suffixes.  If no suffixes are defined,
130      * <code>null</code> should be supplied.  An array of length 0
131      * will be normalized to <code>null</code>.
132      * @param MIMETypes an array of <code>String</code>s indicating
133      * the format's MIME types.  If no suffixes are defined,
134      * <code>null</code> should be supplied.  An array of length 0
135      * will be normalized to <code>null</code>.
136      * @param writerClassName the fully-qualified name of the
137      * associated <code>ImageWriterSpi</code> class, as a
138      * non-<code>null</code> <code>String</code>.
139      * @param outputTypes an array of <code>Class</code> objects of
140      * length at least 1 indicating the legal output types.
141      * @param readerSpiNames an array <code>String</code>s of length
142      * at least 1 naming the classes of all associated
143      * <code>ImageReader</code>s, or <code>null</code>.  An array of
144      * length 0 is normalized to <code>null</code>.
145      * @param supportsStandardStreamMetadataFormat a
146      * <code>boolean</code> that indicates whether a stream metadata
147      * object can use trees described by the standard metadata format.
148      * @param nativeStreamMetadataFormatName a
149      * <code>String</code>, or <code>null</code>, to be returned from
150      * <code>getNativeStreamMetadataFormatName</code>.
151      * @param nativeStreamMetadataFormatClassName a
152      * <code>String</code>, or <code>null</code>, to be used to instantiate
153      * a metadata format object to be returned from
154      * <code>getNativeStreamMetadataFormat</code>.
155      * @param extraStreamMetadataFormatNames an array of
156      * <code>String</code>s, or <code>null</code>, to be returned from
157      * <code>getExtraStreamMetadataFormatNames</code>.  An array of length
158      * 0 is normalized to <code>null</code>.
159      * @param extraStreamMetadataFormatClassNames an array of
160      * <code>String</code>s, or <code>null</code>, to be used to instantiate
161      * a metadata format object to be returned from
162      * <code>getStreamMetadataFormat</code>.  An array of length
163      * 0 is normalized to <code>null</code>.
164      * @param supportsStandardImageMetadataFormat a
165      * <code>boolean</code> that indicates whether an image metadata
166      * object can use trees described by the standard metadata format.
167      * @param nativeImageMetadataFormatName a
168      * <code>String</code>, or <code>null</code>, to be returned from
169      * <code>getNativeImageMetadataFormatName</code>.
170      * @param nativeImageMetadataFormatClassName a
171      * <code>String</code>, or <code>null</code>, to be used to instantiate
172      * a metadata format object to be returned from
173      * <code>getNativeImageMetadataFormat</code>.
174      * @param extraImageMetadataFormatNames an array of
175      * <code>String</code>s to be returned from
176      * <code>getExtraImageMetadataFormatNames</code>.  An array of length 0
177      * is normalized to <code>null</code>.
178      * @param extraImageMetadataFormatClassNames an array of
179      * <code>String</code>s, or <code>null</code>, to be used to instantiate
180      * a metadata format object to be returned from
181      * <code>getImageMetadataFormat</code>.  An array of length
182      * 0 is normalized to <code>null</code>.
183      *
184      * @exception IllegalArgumentException if <code>vendorName</code>
185      * is <code>null</code>.
186      * @exception IllegalArgumentException if <code>version</code>
187      * is <code>null</code>.
188      * @exception IllegalArgumentException if <code>names</code>
189      * is <code>null</code> or has length 0.
190      * @exception IllegalArgumentException if <code>writerClassName</code>
191      * is <code>null</code>.
192      * @exception IllegalArgumentException if <code>outputTypes</code>
193      * is <code>null</code> or has length 0.
194      */
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 = (String[])readerSpiNames.clone();
242         }
243     }
244 
245     /**
246      * Returns <code>true</code> if the format that this writer
247      * outputs preserves pixel data bit-accurately.  The default
248      * implementation returns <code>true</code>.
249      *
250      * @return <code>true</code> if the format preserves full pixel
251      * accuracy.
252      */
253     public boolean isFormatLossless() {
254         return true;
255     }
256 
257     /**
258      * Returns an array of <code>Class</code> objects indicating what
259      * types of objects may be used as arguments to the writer's
260      * <code>setOutput</code> method.
261      *
262      * <p> For most writers, which only output to an
263      * <code>ImageOutputStream</code>, a single-element array
264      * containing <code>ImageOutputStream.class</code> should be
265      * returned.
266      *
267      * @return a non-<code>null</code> array of
268      * <code>Class</code>objects of length at least 1.
269      */
270     public Class[] getOutputTypes() {
271         return (Class[])outputTypes.clone();
272     }
273 
274     /**
275      * Returns <code>true</code> if the <code>ImageWriter</code>
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</code> and
279      * <code>ColorModel</code>) is described by an
280      * <code>ImageTypeSpecifier</code> object.
281      *
282      * <p> A return value of <code>true</code> 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</code> if handed an RGB <code>BufferedImage</code>.
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</code>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</code> specifying the
302      * layout of the image to be written.
303      *
304      * @return <code>true</code> if this writer is likely to be able
305      * to encode images with the given layout.
306      *
307      * @exception IllegalArgumentException if <code>type</code>
308      * is <code>null</code>.
309      */
310     public abstract boolean canEncodeImage(ImageTypeSpecifier type);
311 
312     /**
313      * Returns <code>true</code> if the <code>ImageWriter</code>
314      * implementation associated with this service provider is able to
315      * encode the given <code>RenderedImage</code> instance.  Note
316      * that this includes instances of
317      * <code>java.awt.image.BufferedImage</code>.
318      *
319      * <p> See the discussion for
320      * <code>canEncodeImage(ImageTypeSpecifier)</code> for information
321      * on the semantics of this method.
322      *
323      * @param im an instance of <code>RenderedImage</code> to be encoded.
324      *
325      * @return <code>true</code> if this writer is likely to be able
326      * to encode this image.
327      *
328      * @exception IllegalArgumentException if <code>im</code>
329      * is <code>null</code>.
330      */
331     public boolean canEncodeImage(RenderedImage im) {
332         return canEncodeImage(ImageTypeSpecifier.createFromRenderedImage(im));
333     }
334 
335     /**
336      * Returns an instance of the <code>ImageWriter</code>
337      * implementation associated with this service provider.
338      * The returned object will initially be in an initial state as if
339      * its <code>reset</code> method had been called.
340      *
341      * <p> The default implementation simply returns
342      * <code>createWriterInstance(null)</code>.
343      *
344      * @return an <code>ImageWriter</code> 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      */
350     public ImageWriter createWriterInstance() throws IOException {
351         return createWriterInstance(null);
352     }
353 
354     /**
355      * Returns an instance of the <code>ImageWriter</code>
356      * implementation associated with this service provider.
357      * The returned object will initially be in an initial state
358      * as if its <code>reset</code> method had been called.
359      *
360      * <p> An <code>Object</code> 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)</code>.
366      *
367      * @param extension a plug-in specific extension object, which may
368      * be <code>null</code>.
369      *
370      * @return an <code>ImageWriter</code> instance.
371      *
372      * @exception IOException if the attempt to instantiate
373      * the writer fails.
374      * @exception IllegalArgumentException if the
375      * <code>ImageWriter</code>'s constructor throws an
376      * <code>IllegalArgumentException</code> to indicate that the
377      * extension object is unsuitable.
378      */
379     public abstract ImageWriter createWriterInstance(Object extension)
380         throws IOException;
381 
382     /**
383      * Returns <code>true</code> if the <code>ImageWriter</code> object
384      * passed in is an instance of the <code>ImageWriter</code>
385      * associated with this service provider.
386      *
387      * @param writer an <code>ImageWriter</code> instance.
388      *
389      * @return <code>true</code> if <code>writer</code> is recognized
390      *
391      * @exception IllegalArgumentException if <code>writer</code> is
392      * <code>null</code>.
393      */
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</code>s containing all the
404      * fully qualified names of all the <code>ImageReaderSpi</code>
405      * classes that can understand the internal metadata
406      * representation used by the <code>ImageWriter</code> associated
407      * with this service provider, or <code>null</code> if there are
408      * no such <code>ImageReaders</code> specified.  If a
409      * non-<code>null</code> 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</code> returned by
415      * <code>ImageIO.getImageReader(ImageWriter)</code>.
416      *
417      * <p> This mechanism may be used to obtain
418      * <code>ImageReaders</code> that will generated non-pixel
419      * meta-data (see <code>IIOExtraDataInfo</code>) in a structure
420      * understood by an <code>ImageWriter</code>.  By reading the
421      * image and obtaining this data from one of the
422      * <code>ImageReaders</code> obtained with this method and passing
423      * it on to the <code>ImageWriter</code>, 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</code>s of length at least 1
430      * containing names of <code>ImageReaderSpi</code>s, or
431      * <code>null</code>.
432      *
433      * @see javax.imageio.ImageIO#getImageReader(ImageWriter)
434      * @see ImageReaderSpi#getImageWriterSpiNames()
435      */
436     public String[] getImageReaderSpiNames() {
437         return readerSpiNames == null ?
438             null : (String[])readerSpiNames.clone();
439     }
440 }