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