1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Rustem V. Rafikov
19 * @version $Revision: 1.3 $
20 */
21
22package javax.imageio;
23
24import java.awt.Dimension;
25import java.awt.Rectangle;
26import java.awt.image.BufferedImage;
27import java.awt.image.Raster;
28import java.awt.image.RenderedImage;
29import java.io.IOException;
30import java.security.AccessController;
31import java.security.PrivilegedAction;
32import java.util.ArrayList;
33import java.util.List;
34import java.util.Locale;
35import java.util.MissingResourceException;
36import java.util.ResourceBundle;
37
38import javax.imageio.event.IIOWriteProgressListener;
39import javax.imageio.event.IIOWriteWarningListener;
40import javax.imageio.metadata.IIOMetadata;
41import javax.imageio.spi.ImageWriterSpi;
42
43/**
44 * The ImageWriter class is an abstract class for encoding images. ImageWriter
45 * objects are instantiated by the service provider interface, ImageWriterSpi
46 * class, for the specific format. ImageWriterSpi class should be registered
47 * with the IIORegistry, which uses them for format recognition and presentation
48 * of available format readers and writers.
49 *
50 * @since Android 1.0
51 */
52public abstract class ImageWriter implements ImageTranscoder {
53
54    /**
55     * The available locales.
56     */
57    protected Locale[] availableLocales;
58
59    /**
60     * The locale.
61     */
62    protected Locale locale;
63
64    /**
65     * The originating provider.
66     */
67    protected ImageWriterSpi originatingProvider;
68
69    /**
70     * The output.
71     */
72    protected Object output;
73
74    /**
75     * The progress listeners.
76     */
77    protected List<IIOWriteProgressListener> progressListeners;
78
79    /**
80     * The warning listeners.
81     */
82    protected List<IIOWriteWarningListener> warningListeners;
83
84    /**
85     * The warning locales.
86     */
87    protected List<Locale> warningLocales;
88
89    // Indicates that abort operation is requested
90    // Abort mechanism should be thread-safe
91    /** The aborted. */
92    private boolean aborted;
93
94    /**
95     * Instantiates a new ImageWriter.
96     *
97     * @param originatingProvider
98     *            the ImageWriterSpi which instantiates this ImageWriter.
99     */
100    protected ImageWriter(ImageWriterSpi originatingProvider) {
101        this.originatingProvider = originatingProvider;
102    }
103
104    public abstract IIOMetadata convertStreamMetadata(IIOMetadata iioMetadata,
105            ImageWriteParam imageWriteParam);
106
107    public abstract IIOMetadata convertImageMetadata(IIOMetadata iioMetadata,
108            ImageTypeSpecifier imageTypeSpecifier, ImageWriteParam imageWriteParam);
109
110    /**
111     * Gets the ImageWriterSpi which instantiated this ImageWriter.
112     *
113     * @return the ImageWriterSpi.
114     */
115    public ImageWriterSpi getOriginatingProvider() {
116        return originatingProvider;
117    }
118
119    /**
120     * Processes the start of an image read by calling their imageStarted method
121     * of registered IIOWriteProgressListeners.
122     *
123     * @param imageIndex
124     *            the image index.
125     */
126    protected void processImageStarted(int imageIndex) {
127        if (null != progressListeners) {
128            for (IIOWriteProgressListener listener : progressListeners) {
129                listener.imageStarted(this, imageIndex);
130            }
131        }
132    }
133
134    /**
135     * Processes the current percentage of image completion by calling
136     * imageProgress method of registered IIOWriteProgressListener.
137     *
138     * @param percentageDone
139     *            the percentage done.
140     */
141    protected void processImageProgress(float percentageDone) {
142        if (null != progressListeners) {
143            for (IIOWriteProgressListener listener : progressListeners) {
144                listener.imageProgress(this, percentageDone);
145            }
146        }
147    }
148
149    /**
150     * Processes image completion by calling imageComplete method of registered
151     * IIOWriteProgressListeners.
152     */
153    protected void processImageComplete() {
154        if (null != progressListeners) {
155            for (IIOWriteProgressListener listener : progressListeners) {
156                listener.imageComplete(this);
157            }
158        }
159    }
160
161    /**
162     * Processes a warning message by calling warningOccurred method of
163     * registered IIOWriteWarningListeners.
164     *
165     * @param imageIndex
166     *            the image index.
167     * @param warning
168     *            the warning.
169     */
170    protected void processWarningOccurred(int imageIndex, String warning) {
171        if (null == warning) {
172            throw new NullPointerException("warning message should not be NULL");
173        }
174        if (null != warningListeners) {
175            for (IIOWriteWarningListener listener : warningListeners) {
176                listener.warningOccurred(this, imageIndex, warning);
177            }
178        }
179    }
180
181    /**
182     * Processes a warning message by calling warningOccurred method of
183     * registered IIOWriteWarningListeners with string from ResourceBundle.
184     *
185     * @param imageIndex
186     *            the image index.
187     * @param bundle
188     *            the name of ResourceBundle.
189     * @param key
190     *            the keyword.
191     */
192    protected void processWarningOccurred(int imageIndex, String bundle, String key) {
193        if (warningListeners != null) { // Don't check the parameters
194            return;
195        }
196
197        if (bundle == null) {
198            throw new IllegalArgumentException("baseName == null!");
199        }
200        if (key == null) {
201            throw new IllegalArgumentException("keyword == null!");
202        }
203
204        // Get the context class loader and try to locate the bundle with it
205        // first
206        ClassLoader contextClassloader = AccessController
207                .doPrivileged(new PrivilegedAction<ClassLoader>() {
208                    public ClassLoader run() {
209                        return Thread.currentThread().getContextClassLoader();
210                    }
211                });
212
213        // Iterate through both listeners and locales
214        int n = warningListeners.size();
215        for (int i = 0; i < n; i++) {
216            IIOWriteWarningListener listener = warningListeners.get(i);
217            Locale locale = warningLocales.get(i);
218
219            // Now try to get the resource bundle
220            ResourceBundle rb;
221            try {
222                rb = ResourceBundle.getBundle(bundle, locale, contextClassloader);
223            } catch (MissingResourceException e) {
224                try {
225                    rb = ResourceBundle.getBundle(bundle, locale);
226                } catch (MissingResourceException e1) {
227                    throw new IllegalArgumentException("Bundle not found!");
228                }
229            }
230
231            try {
232                String warning = rb.getString(key);
233                listener.warningOccurred(this, imageIndex, warning);
234            } catch (MissingResourceException e) {
235                throw new IllegalArgumentException("Resource is missing!");
236            } catch (ClassCastException e) {
237                throw new IllegalArgumentException("Resource is not a String!");
238            }
239        }
240    }
241
242    /**
243     * Sets the specified Object to the output of this ImageWriter.
244     *
245     * @param output
246     *            the Object which represents destination, it can be
247     *            ImageOutputStream or other objects.
248     */
249    public void setOutput(Object output) {
250        if (output != null) {
251            ImageWriterSpi spi = getOriginatingProvider();
252            if (null != spi) {
253                Class[] outTypes = spi.getOutputTypes();
254                boolean supported = false;
255                for (Class<?> element : outTypes) {
256                    if (element.isInstance(output)) {
257                        supported = true;
258                        break;
259                    }
260                }
261                if (!supported) {
262                    throw new IllegalArgumentException("output " + output + " is not supported");
263                }
264            }
265        }
266        this.output = output;
267    }
268
269    /**
270     * Writes a completed image stream that contains the specified image,
271     * default metadata, and thumbnails to the output.
272     *
273     * @param image
274     *            the specified image to be written.
275     * @throws IOException
276     *             if an I/O exception has occurred during writing.
277     */
278    public void write(IIOImage image) throws IOException {
279        write(null, image, null);
280    }
281
282    /**
283     * Writes a completed image stream that contains the specified rendered
284     * image, default metadata, and thumbnails to the output.
285     *
286     * @param image
287     *            the specified RenderedImage to be written.
288     * @throws IOException
289     *             if an I/O exception has occurred during writing.
290     */
291    public void write(RenderedImage image) throws IOException {
292        write(null, new IIOImage(image, null, null), null);
293    }
294
295    /**
296     * Writes a completed image stream that contains the specified image,
297     * metadata and thumbnails to the output.
298     *
299     * @param streamMetadata
300     *            the stream metadata, or null.
301     * @param image
302     *            the specified image to be written, if canWriteRaster() method
303     *            returns false, then Image must contain only RenderedImage.
304     * @param param
305     *            the ImageWriteParam, or null.
306     * @throws IOException
307     *             if an error occurs during writing.
308     */
309    public abstract void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param)
310            throws IOException;
311
312    /**
313     * Disposes of any resources.
314     */
315    public void dispose() {
316        // def impl. does nothing according to the spec.
317    }
318
319    /**
320     * Requests an abort operation for current writing operation.
321     */
322    public synchronized void abort() {
323        aborted = true;
324    }
325
326    /**
327     * Checks whether or not a request to abort the current write operation has
328     * been made successfully.
329     *
330     * @return true, if the request to abort the current write operation has
331     *         been made successfully, false otherwise.
332     */
333    protected synchronized boolean abortRequested() {
334        return aborted;
335    }
336
337    /**
338     * Clears all previous abort request, and abortRequested returns false after
339     * calling this method.
340     */
341    protected synchronized void clearAbortRequest() {
342        aborted = false;
343    }
344
345    /**
346     * Adds the IIOWriteProgressListener listener.
347     *
348     * @param listener
349     *            the IIOWriteProgressListener listener.
350     */
351    public void addIIOWriteProgressListener(IIOWriteProgressListener listener) {
352        if (listener == null) {
353            return;
354        }
355
356        if (progressListeners == null) {
357            progressListeners = new ArrayList<IIOWriteProgressListener>();
358        }
359
360        progressListeners.add(listener);
361    }
362
363    /**
364     * Adds the IIOWriteWarningListener.
365     *
366     * @param listener
367     *            the IIOWriteWarningListener listener.
368     */
369    public void addIIOWriteWarningListener(IIOWriteWarningListener listener) {
370        if (listener == null) {
371            return;
372        }
373
374        if (warningListeners == null) {
375            warningListeners = new ArrayList<IIOWriteWarningListener>();
376            warningLocales = new ArrayList<Locale>();
377        }
378
379        warningListeners.add(listener);
380        warningLocales.add(getLocale());
381    }
382
383    /**
384     * Gets the output object that was set by setOutput method.
385     *
386     * @return the output object such as ImageOutputStream, or null if it is not
387     *         set.
388     */
389    public Object getOutput() {
390        return output;
391    }
392
393    /**
394     * Check output return false.
395     *
396     * @return true, if successful.
397     */
398    private final boolean checkOutputReturnFalse() {
399        if (getOutput() == null) {
400            throw new IllegalStateException("getOutput() == null!");
401        }
402        return false;
403    }
404
405    /**
406     * Unsupported operation.
407     */
408    private final void unsupportedOperation() {
409        if (getOutput() == null) {
410            throw new IllegalStateException("getOutput() == null!");
411        }
412        throw new UnsupportedOperationException("Unsupported write variant!");
413    }
414
415    /**
416     * Returns true if a new empty image can be inserted at the specified index.
417     *
418     * @param imageIndex
419     *            the specified index of image.
420     * @return true if a new empty image can be inserted at the specified index,
421     *         false otherwise.
422     * @throws IOException
423     *             Signals that an I/O exception has occurred.
424     */
425    public boolean canInsertEmpty(int imageIndex) throws IOException {
426        return checkOutputReturnFalse();
427    }
428
429    /**
430     * Returns true if a new image can be inserted at the specified index.
431     *
432     * @param imageIndex
433     *            the specified index of image.
434     * @return true if a new image can be inserted at the specified index, false
435     *         otherwise.
436     * @throws IOException
437     *             Signals that an I/O exception has occurred.
438     */
439    public boolean canInsertImage(int imageIndex) throws IOException {
440        return checkOutputReturnFalse();
441    }
442
443    /**
444     * Returns true if the image with the specified index can be removed.
445     *
446     * @param imageIndex
447     *            the specified index of image.
448     * @return true if the image with the specified index can be removed, false
449     *         otherwise.
450     * @throws IOException
451     *             Signals that an I/O exception has occurred.
452     */
453    public boolean canRemoveImage(int imageIndex) throws IOException {
454        return checkOutputReturnFalse();
455    }
456
457    /**
458     * Returns true if metadata of the image with the specified index can be
459     * replaced.
460     *
461     * @param imageIndex
462     *            the specified image index.
463     * @return true if metadata of the image with the specified index can be
464     *         replaced, false otherwise.
465     * @throws IOException
466     *             if an I/O exception has occurred.
467     */
468    public boolean canReplaceImageMetadata(int imageIndex) throws IOException {
469        return checkOutputReturnFalse();
470    }
471
472    /**
473     * Returns true if pixels of the image with the specified index can be
474     * replaced by the replacePixels methods.
475     *
476     * @param imageIndex
477     *            the image's index.
478     * @return true if pixels of the image with the specified index can be
479     *         replaced by the replacePixels methods, false otherwise.
480     * @throws IOException
481     *             Signals that an I/O exception has occurred.
482     */
483    public boolean canReplacePixels(int imageIndex) throws IOException {
484        return checkOutputReturnFalse();
485    }
486
487    /**
488     * Returns true if the stream metadata presented in the output can be
489     * removed.
490     *
491     * @return true if the stream metadata presented in the output can be
492     *         removed, false otherwise.
493     * @throws IOException
494     *             if an I/O exception has occurred.
495     */
496    public boolean canReplaceStreamMetadata() throws IOException {
497        return checkOutputReturnFalse();
498    }
499
500    /**
501     * Returns true if the writing of a complete image stream which contains a
502     * single image is supported with undefined pixel values and associated
503     * metadata and thumbnails to the output.
504     *
505     * @return true if the writing of a complete image stream which contains a
506     *         single image is supported, false otherwise.
507     * @throws IOException
508     *             if an I/O exception has occurred.
509     */
510    public boolean canWriteEmpty() throws IOException {
511        return checkOutputReturnFalse();
512    }
513
514    /**
515     * Returns true if the methods which taken an IIOImageParameter can deal
516     * with a Raster source image.
517     *
518     * @return true if the methods which taken an IIOImageParameter can deal
519     *         with a Raster source image, false otherwise.
520     */
521    public boolean canWriteRasters() {
522        return false;
523    }
524
525    /**
526     * Returns true if the writer can add an image to stream that already
527     * contains header information.
528     *
529     * @return if the writer can add an image to stream that already contains
530     *         header information, false otherwise.
531     */
532    public boolean canWriteSequence() {
533        return false;
534    }
535
536    /**
537     * Ends the insertion of a new image.
538     *
539     * @throws IOException
540     *             if an I/O exception has occurred.
541     */
542    public void endInsertEmpty() throws IOException {
543        unsupportedOperation();
544    }
545
546    /**
547     * Ends the replace pixels operation.
548     *
549     * @throws IOException
550     *             if an I/O exception has occurred.
551     */
552    public void endReplacePixels() throws IOException {
553        unsupportedOperation();
554    }
555
556    /**
557     * Ends an empty write operation.
558     *
559     * @throws IOException
560     *             if an I/O exception has occurred.
561     */
562    public void endWriteEmpty() throws IOException {
563        unsupportedOperation();
564    }
565
566    /**
567     * Ends the sequence of write operations.
568     *
569     * @throws IOException
570     *             if an I/O exception has occurred.
571     */
572    public void endWriteSequence() throws IOException {
573        unsupportedOperation();
574    }
575
576    /**
577     * Gets an array of available locales.
578     *
579     * @return an of array available locales.
580     */
581    public Locale[] getAvailableLocales() {
582        if (availableLocales == null) {
583            return null;
584        }
585
586        return availableLocales.clone();
587    }
588
589    /**
590     * Gets an IIOMetadata object that contains default values for encoding an
591     * image with the specified type.
592     *
593     * @param imageType
594     *            the ImageTypeSpecifier.
595     * @param param
596     *            the ImageWriteParam.
597     * @return the IIOMetadata object.
598     */
599    public abstract IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
600            ImageWriteParam param);
601
602    /**
603     * Gets an IIOMetadata object that contains default values for encoding a
604     * stream of images.
605     *
606     * @param param
607     *            the ImageWriteParam.
608     * @return the IIOMetadata object.
609     */
610    public abstract IIOMetadata getDefaultStreamMetadata(ImageWriteParam param);
611
612    /**
613     * Gets the current locale of this ImageWriter.
614     *
615     * @return the current locale of this ImageWriter.
616     */
617    public Locale getLocale() {
618        return locale;
619    }
620
621    /**
622     * Gets the default write param. Gets a new ImageWriteParam object for this
623     * ImageWriter with the current Locale.
624     *
625     * @return a new ImageWriteParam object for this ImageWriter.
626     */
627    public ImageWriteParam getDefaultWriteParam() {
628        return new ImageWriteParam(getLocale());
629    }
630
631    /**
632     * Gets the number of thumbnails supported by the format being written with
633     * supported image type, image write parameters, stream, and image metadata
634     * objects.
635     *
636     * @param imageType
637     *            the ImageTypeSpecifier.
638     * @param param
639     *            the image's parameters.
640     * @param streamMetadata
641     *            the stream metadata.
642     * @param imageMetadata
643     *            the image metadata.
644     * @return the number of thumbnails supported.
645     */
646    public int getNumThumbnailsSupported(ImageTypeSpecifier imageType, ImageWriteParam param,
647            IIOMetadata streamMetadata, IIOMetadata imageMetadata) {
648        return 0;
649    }
650
651    /**
652     * Gets the preferred thumbnail sizes. Gets an array of Dimensions with the
653     * sizes for thumbnail images as they are encoded in the output file or
654     * stream.
655     *
656     * @param imageType
657     *            the ImageTypeSpecifier.
658     * @param param
659     *            the ImageWriteParam.
660     * @param streamMetadata
661     *            the stream metadata.
662     * @param imageMetadata
663     *            the image metadata.
664     * @return the preferred thumbnail sizes.
665     */
666    public Dimension[] getPreferredThumbnailSizes(ImageTypeSpecifier imageType,
667            ImageWriteParam param, IIOMetadata streamMetadata, IIOMetadata imageMetadata) {
668        return null;
669    }
670
671    /**
672     * Prepares insertion of an empty image by requesting the insertion of a new
673     * image into an existing image stream.
674     *
675     * @param imageIndex
676     *            the image index.
677     * @param imageType
678     *            the image type.
679     * @param width
680     *            the width of the image.
681     * @param height
682     *            the height of the image.
683     * @param imageMetadata
684     *            the image metadata, or null.
685     * @param thumbnails
686     *            the array thumbnails for this image, or null.
687     * @param param
688     *            the ImageWriteParam, or null.
689     * @throws IOException
690     *             if an I/O exception has occurred.
691     */
692    public void prepareInsertEmpty(int imageIndex, ImageTypeSpecifier imageType, int width,
693            int height, IIOMetadata imageMetadata, List<? extends BufferedImage> thumbnails,
694            ImageWriteParam param) throws IOException {
695        unsupportedOperation();
696    }
697
698    /**
699     * Prepares the writer to call the replacePixels method for the specified
700     * region.
701     *
702     * @param imageIndex
703     *            the image's index.
704     * @param region
705     *            the specified region.
706     * @throws IOException
707     *             if an I/O exception has occurred.
708     */
709    public void prepareReplacePixels(int imageIndex, Rectangle region) throws IOException {
710        unsupportedOperation();
711    }
712
713    /**
714     * Prepares the writer for writing an empty image by beginning the process
715     * of writing a complete image stream that contains a single image with
716     * undefined pixel values, metadata and thumbnails, to the output.
717     *
718     * @param streamMetadata
719     *            the stream metadata.
720     * @param imageType
721     *            the image type.
722     * @param width
723     *            the width of the image.
724     * @param height
725     *            the height of the image.
726     * @param imageMetadata
727     *            the image's metadata, or null.
728     * @param thumbnails
729     *            the image's thumbnails, or null.
730     * @param param
731     *            the image's parameters, or null.
732     * @throws IOException
733     *             if an I/O exception has occurred.
734     */
735    public void prepareWriteEmpty(IIOMetadata streamMetadata, ImageTypeSpecifier imageType,
736            int width, int height, IIOMetadata imageMetadata,
737            List<? extends BufferedImage> thumbnails, ImageWriteParam param) throws IOException {
738        unsupportedOperation();
739    }
740
741    /**
742     * Prepares a stream to accept calls of writeToSequence method using the
743     * metadata object.
744     *
745     * @param streamMetadata
746     *            the stream metadata.
747     * @throws IOException
748     *             if an I/O exception has occurred.
749     */
750    public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException {
751        unsupportedOperation();
752    }
753
754    /**
755     * Processes the completion of a thumbnail read by calling their
756     * thumbnailComplete method of registered IIOWriteProgressListeners.
757     */
758    protected void processThumbnailComplete() {
759        if (progressListeners != null) {
760            for (IIOWriteProgressListener listener : progressListeners) {
761                listener.thumbnailComplete(this);
762            }
763        }
764    }
765
766    /**
767     * Processes the current percentage of thumbnail completion by calling their
768     * thumbnailProgress method of registered IIOWriteProgressListeners.
769     *
770     * @param percentageDone
771     *            the percentage done.
772     */
773    protected void processThumbnailProgress(float percentageDone) {
774        if (progressListeners != null) {
775            for (IIOWriteProgressListener listener : progressListeners) {
776                listener.thumbnailProgress(this, percentageDone);
777            }
778        }
779    }
780
781    /**
782     * Processes the start of a thumbnail read by calling thumbnailStarted
783     * method of registered IIOWriteProgressListeners.
784     *
785     * @param imageIndex
786     *            the image index.
787     * @param thumbnailIndex
788     *            the thumbnail index.
789     */
790    protected void processThumbnailStarted(int imageIndex, int thumbnailIndex) {
791        if (progressListeners != null) {
792            for (IIOWriteProgressListener listener : progressListeners) {
793                listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
794            }
795        }
796    }
797
798    /**
799     * Processes that the writing has been aborted by calling writeAborted
800     * method of registered IIOWriteProgressListeners.
801     */
802    protected void processWriteAborted() {
803        if (progressListeners != null) {
804            for (IIOWriteProgressListener listener : progressListeners) {
805                listener.writeAborted(this);
806            }
807        }
808    }
809
810    /**
811     * Removes the all IIOWriteProgressListener listeners.
812     */
813    public void removeAllIIOWriteProgressListeners() {
814        progressListeners = null;
815    }
816
817    /**
818     * Removes the all IIOWriteWarningListener listeners.
819     */
820    public void removeAllIIOWriteWarningListeners() {
821        warningListeners = null;
822        warningLocales = null;
823    }
824
825    /**
826     * Removes the specified IIOWriteProgressListener listener.
827     *
828     * @param listener
829     *            the registered IIOWriteProgressListener to be removed.
830     */
831    public void removeIIOWriteProgressListener(IIOWriteProgressListener listener) {
832        if (progressListeners != null && listener != null) {
833            if (progressListeners.remove(listener) && progressListeners.isEmpty()) {
834                progressListeners = null;
835            }
836        }
837    }
838
839    /**
840     * Removes the specified IIOWriteWarningListener listener.
841     *
842     * @param listener
843     *            the registered IIOWriteWarningListener listener to be removed.
844     */
845    public void removeIIOWriteWarningListener(IIOWriteWarningListener listener) {
846        if (warningListeners == null || listener == null) {
847            return;
848        }
849
850        int idx = warningListeners.indexOf(listener);
851        if (idx > -1) {
852            warningListeners.remove(idx);
853            warningLocales.remove(idx);
854
855            if (warningListeners.isEmpty()) {
856                warningListeners = null;
857                warningLocales = null;
858            }
859        }
860    }
861
862    /**
863     * Removes the image with the specified index from the stream.
864     *
865     * @param imageIndex
866     *            the image's index.
867     * @throws IOException
868     *             if an I/O exception has occurred.
869     */
870    public void removeImage(int imageIndex) throws IOException {
871        unsupportedOperation();
872    }
873
874    /**
875     * Replaces image metadata of the image with specified index.
876     *
877     * @param imageIndex
878     *            the image's index.
879     * @param imageMetadata
880     *            the image metadata.
881     * @throws IOException
882     *             if an I/O exception has occurred.
883     */
884    public void replaceImageMetadata(int imageIndex, IIOMetadata imageMetadata) throws IOException {
885        unsupportedOperation();
886    }
887
888    /**
889     * Replaces a part of an image presented in the output with the specified
890     * RenderedImage.
891     *
892     * @param image
893     *            the RenderedImage.
894     * @param param
895     *            the ImageWriteParam.
896     * @throws IOException
897     *             if an I/O exception has occurred.
898     */
899    public void replacePixels(RenderedImage image, ImageWriteParam param) throws IOException {
900        unsupportedOperation();
901    }
902
903    /**
904     * Replaces a part of an image presented in the output with the specified
905     * Raster.
906     *
907     * @param raster
908     *            the Raster.
909     * @param param
910     *            the ImageWriteParam.
911     * @throws IOException
912     *             if an I/O exception has occurred.
913     */
914    public void replacePixels(Raster raster, ImageWriteParam param) throws IOException {
915        unsupportedOperation();
916    }
917
918    /**
919     * Replaces the stream metadata of the output with new IIOMetadata.
920     *
921     * @param streamMetadata
922     *            the new stream metadata.
923     * @throws IOException
924     *             if an I/O exception has occurred.
925     */
926    public void replaceStreamMetadata(IIOMetadata streamMetadata) throws IOException {
927        unsupportedOperation();
928    }
929
930    /**
931     * Sets the locale of this ImageWriter.
932     *
933     * @param locale
934     *            the new locale.
935     */
936    public void setLocale(Locale locale) {
937        if (locale == null) {
938            this.locale = null;
939            return;
940        }
941
942        Locale[] locales = getAvailableLocales();
943        boolean validLocale = false;
944        if (locales != null) {
945            for (int i = 0; i < locales.length; i++) {
946                if (locale.equals(locales[i])) {
947                    validLocale = true;
948                    break;
949                }
950            }
951        }
952
953        if (validLocale) {
954            this.locale = locale;
955        } else {
956            throw new IllegalArgumentException("Invalid locale!");
957        }
958    }
959
960    /**
961     * Resets this ImageWriter.
962     */
963    public void reset() {
964        setOutput(null);
965        setLocale(null);
966        removeAllIIOWriteWarningListeners();
967        removeAllIIOWriteProgressListeners();
968        clearAbortRequest();
969    }
970
971    /**
972     * Inserts image into existing output stream.
973     *
974     * @param imageIndex
975     *            the image index where an image will be written.
976     * @param image
977     *            the specified image to be written.
978     * @param param
979     *            the ImageWriteParam, or null.
980     * @throws IOException
981     *             if an I/O exception has occurred.
982     */
983    public void writeInsert(int imageIndex, IIOImage image, ImageWriteParam param)
984            throws IOException {
985        unsupportedOperation();
986    }
987
988    /**
989     * Writes the specified image to the sequence.
990     *
991     * @param image
992     *            the image to be written.
993     * @param param
994     *            the ImageWriteParam, or null.
995     * @throws IOException
996     *             if an I/O exception has occurred during writing.
997     */
998    public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException {
999        unsupportedOperation();
1000    }
1001}
1002