1 /* 2 * Copyright (c) 1999, 2001, 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 }