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
26package javax.imageio.spi;
27
28import java.awt.image.RenderedImage;
29import java.io.IOException;
30import javax.imageio.ImageTypeSpecifier;
31import javax.imageio.ImageWriter;
32import 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 */
76public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
436    public String[] getImageReaderSpiNames() {
437        return readerSpiNames == null ?
438            null : readerSpiNames.clone();
439    }
440}
441