001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Rustem V. Rafikov
019: * @version $Revision: 1.3 $
020: */package javax.imageio;
021:
022: import java.awt.Dimension;
023: import java.awt.Rectangle;
024: import java.awt.image.BufferedImage;
025: import java.awt.image.Raster;
026: import java.awt.image.RenderedImage;
027: import java.io.IOException;
028: import java.security.AccessController;
029: import java.security.PrivilegedAction;
030: import java.util.ArrayList;
031: import java.util.List;
032: import java.util.Locale;
033: import java.util.MissingResourceException;
034: import java.util.ResourceBundle;
035:
036: import javax.imageio.event.IIOWriteProgressListener;
037: import javax.imageio.event.IIOWriteWarningListener;
038: import javax.imageio.metadata.IIOMetadata;
039: import javax.imageio.spi.ImageWriterSpi;
040:
041: public abstract class ImageWriter implements ImageTranscoder {
042:
043: protected Locale[] availableLocales;
044: protected Locale locale;
045: protected ImageWriterSpi originatingProvider;
046: protected Object output;
047: protected List<IIOWriteProgressListener> progressListeners;
048: protected List<IIOWriteWarningListener> warningListeners;
049: protected List<Locale> warningLocales;
050:
051: // Indicates that abort operation is requested
052: // Abort mechanism should be thread-safe
053: private boolean aborted;
054:
055: protected ImageWriter(ImageWriterSpi originatingProvider) {
056: this .originatingProvider = originatingProvider;
057: }
058:
059: public abstract IIOMetadata convertStreamMetadata(
060: IIOMetadata iioMetadata, ImageWriteParam imageWriteParam);
061:
062: public abstract IIOMetadata convertImageMetadata(
063: IIOMetadata iioMetadata,
064: ImageTypeSpecifier imageTypeSpecifier,
065: ImageWriteParam imageWriteParam);
066:
067: public ImageWriterSpi getOriginatingProvider() {
068: return originatingProvider;
069: }
070:
071: protected void processImageStarted(int imageIndex) {
072: if (null != progressListeners) {
073: for (IIOWriteProgressListener listener : progressListeners) {
074: listener.imageStarted(this , imageIndex);
075: }
076: }
077: }
078:
079: protected void processImageProgress(float percentageDone) {
080: if (null != progressListeners) {
081: for (IIOWriteProgressListener listener : progressListeners) {
082: listener.imageProgress(this , percentageDone);
083: }
084: }
085: }
086:
087: protected void processImageComplete() {
088: if (null != progressListeners) {
089: for (IIOWriteProgressListener listener : progressListeners) {
090: listener.imageComplete(this );
091: }
092: }
093: }
094:
095: protected void processWarningOccurred(int imageIndex, String warning) {
096: if (null == warning) {
097: throw new NullPointerException(
098: "warning message should not be NULL");
099: }
100: if (null != warningListeners) {
101: for (IIOWriteWarningListener listener : warningListeners) {
102: listener.warningOccurred(this , imageIndex, warning);
103: }
104: }
105: }
106:
107: protected void processWarningOccurred(int imageIndex,
108: String bundle, String key) {
109: if (warningListeners != null) { // Don't check the parameters
110: return;
111: }
112:
113: if (bundle == null) {
114: throw new IllegalArgumentException("baseName == null!");
115: }
116: if (key == null) {
117: throw new IllegalArgumentException("keyword == null!");
118: }
119:
120: // Get the context class loader and try to locate the bundle with it first
121: ClassLoader contextClassloader = AccessController
122: .doPrivileged(new PrivilegedAction<ClassLoader>() {
123: public ClassLoader run() {
124: return Thread.currentThread()
125: .getContextClassLoader();
126: }
127: });
128:
129: // Iterate through both listeners and locales
130: int n = warningListeners.size();
131: for (int i = 0; i < n; i++) {
132: IIOWriteWarningListener listener = warningListeners.get(i);
133: Locale locale = warningLocales.get(i);
134:
135: // Now try to get the resource bundle
136: ResourceBundle rb;
137: try {
138: rb = ResourceBundle.getBundle(bundle, locale,
139: contextClassloader);
140: } catch (MissingResourceException e) {
141: try {
142: rb = ResourceBundle.getBundle(bundle, locale);
143: } catch (MissingResourceException e1) {
144: throw new IllegalArgumentException(
145: "Bundle not found!");
146: }
147: }
148:
149: try {
150: String warning = rb.getString(key);
151: listener.warningOccurred(this , imageIndex, warning);
152: } catch (MissingResourceException e) {
153: throw new IllegalArgumentException(
154: "Resource is missing!");
155: } catch (ClassCastException e) {
156: throw new IllegalArgumentException(
157: "Resource is not a String!");
158: }
159: }
160: }
161:
162: public void setOutput(Object output) {
163: if (output != null) {
164: ImageWriterSpi spi = getOriginatingProvider();
165: if (null != spi) {
166: Class[] outTypes = spi.getOutputTypes();
167: boolean supported = false;
168: for (Class<?> element : outTypes) {
169: if (element.isInstance(output)) {
170: supported = true;
171: break;
172: }
173: }
174: if (!supported) {
175: throw new IllegalArgumentException("output "
176: + output + " is not supported");
177: }
178: }
179: }
180: this .output = output;
181: }
182:
183: public void write(IIOImage image) throws IOException {
184: write(null, image, null);
185: }
186:
187: public void write(RenderedImage image) throws IOException {
188: write(null, new IIOImage(image, null, null), null);
189: }
190:
191: /**
192: * @throws IllegalStateException - if the output has not been set.
193: * @throws UnsupportedOperationException - if image contains a Raster and canWriteRasters returns false.
194: * @throws IllegalArgumentException - if image is null.
195: * @throws IOException - if an error occurs during writing.
196: *
197: * if !canWriteRaster() then Image must contain only RenderedImage
198:
199: * @param streamMetadata <code>null</code> for default stream metadata
200: * @param image
201: * @param param <code>null</code> for default params
202: */
203: public abstract void write(IIOMetadata streamMetadata,
204: IIOImage image, ImageWriteParam param) throws IOException;
205:
206: public void dispose() {
207: // def impl. does nothing according to the spec.
208: }
209:
210: public synchronized void abort() {
211: aborted = true;
212: }
213:
214: protected synchronized boolean abortRequested() {
215: return aborted;
216: }
217:
218: protected synchronized void clearAbortRequest() {
219: aborted = false;
220: }
221:
222: public void addIIOWriteProgressListener(
223: IIOWriteProgressListener listener) {
224: if (listener == null) {
225: return;
226: }
227:
228: if (progressListeners == null) {
229: progressListeners = new ArrayList<IIOWriteProgressListener>();
230: }
231:
232: progressListeners.add(listener);
233: }
234:
235: public void addIIOWriteWarningListener(
236: IIOWriteWarningListener listener) {
237: if (listener == null) {
238: return;
239: }
240:
241: if (warningListeners == null) {
242: warningListeners = new ArrayList<IIOWriteWarningListener>();
243: warningLocales = new ArrayList<Locale>();
244: }
245:
246: warningListeners.add(listener);
247: warningLocales.add(getLocale());
248: }
249:
250: public Object getOutput() {
251: return output;
252: }
253:
254: private final boolean checkOutputReturnFalse() {
255: if (getOutput() == null) {
256: throw new IllegalStateException("getOutput() == null!");
257: }
258: return false;
259: }
260:
261: private final void unsupportedOperation() {
262: if (getOutput() == null) {
263: throw new IllegalStateException("getOutput() == null!");
264: }
265: throw new UnsupportedOperationException(
266: "Unsupported write variant!");
267: }
268:
269: public boolean canInsertEmpty(int imageIndex) throws IOException {
270: return checkOutputReturnFalse();
271: }
272:
273: public boolean canInsertImage(int imageIndex) throws IOException {
274: return checkOutputReturnFalse();
275: }
276:
277: public boolean canRemoveImage(int imageIndex) throws IOException {
278: return checkOutputReturnFalse();
279: }
280:
281: public boolean canReplaceImageMetadata(int imageIndex)
282: throws IOException {
283: return checkOutputReturnFalse();
284: }
285:
286: public boolean canReplacePixels(int imageIndex) throws IOException {
287: return checkOutputReturnFalse();
288: }
289:
290: public boolean canReplaceStreamMetadata() throws IOException {
291: return checkOutputReturnFalse();
292: }
293:
294: public boolean canWriteEmpty() throws IOException {
295: return checkOutputReturnFalse();
296: }
297:
298: public boolean canWriteRasters() {
299: return false;
300: }
301:
302: public boolean canWriteSequence() {
303: return false;
304: }
305:
306: public void endInsertEmpty() throws IOException {
307: unsupportedOperation();
308: }
309:
310: public void endReplacePixels() throws IOException {
311: unsupportedOperation();
312: }
313:
314: public void endWriteEmpty() throws IOException {
315: unsupportedOperation();
316: }
317:
318: public void endWriteSequence() throws IOException {
319: unsupportedOperation();
320: }
321:
322: public Locale[] getAvailableLocales() {
323: if (availableLocales == null) {
324: return null;
325: }
326:
327: return availableLocales.clone();
328: }
329:
330: public abstract IIOMetadata getDefaultImageMetadata(
331: ImageTypeSpecifier imageType, ImageWriteParam param);
332:
333: public abstract IIOMetadata getDefaultStreamMetadata(
334: ImageWriteParam param);
335:
336: public Locale getLocale() {
337: return locale;
338: }
339:
340: public ImageWriteParam getDefaultWriteParam() {
341: return new ImageWriteParam(getLocale());
342: }
343:
344: public int getNumThumbnailsSupported(ImageTypeSpecifier imageType,
345: ImageWriteParam param, IIOMetadata streamMetadata,
346: IIOMetadata imageMetadata) {
347: return 0;
348: }
349:
350: public Dimension[] getPreferredThumbnailSizes(
351: ImageTypeSpecifier imageType, ImageWriteParam param,
352: IIOMetadata streamMetadata, IIOMetadata imageMetadata) {
353: return null;
354: }
355:
356: public void prepareInsertEmpty(int imageIndex,
357: ImageTypeSpecifier imageType, int width, int height,
358: IIOMetadata imageMetadata,
359: List<? extends BufferedImage> thumbnails,
360: ImageWriteParam param) throws IOException {
361: unsupportedOperation();
362: }
363:
364: public void prepareReplacePixels(int imageIndex, Rectangle region)
365: throws IOException {
366: unsupportedOperation();
367: }
368:
369: public void prepareWriteEmpty(IIOMetadata streamMetadata,
370: ImageTypeSpecifier imageType, int width, int height,
371: IIOMetadata imageMetadata,
372: List<? extends BufferedImage> thumbnails,
373: ImageWriteParam param) throws IOException {
374: unsupportedOperation();
375: }
376:
377: public void prepareWriteSequence(IIOMetadata streamMetadata)
378: throws IOException {
379: unsupportedOperation();
380: }
381:
382: protected void processThumbnailComplete() {
383: if (progressListeners != null) {
384: for (IIOWriteProgressListener listener : progressListeners) {
385: listener.thumbnailComplete(this );
386: }
387: }
388: }
389:
390: protected void processThumbnailProgress(float percentageDone) {
391: if (progressListeners != null) {
392: for (IIOWriteProgressListener listener : progressListeners) {
393: listener.thumbnailProgress(this , percentageDone);
394: }
395: }
396: }
397:
398: protected void processThumbnailStarted(int imageIndex,
399: int thumbnailIndex) {
400: if (progressListeners != null) {
401: for (IIOWriteProgressListener listener : progressListeners) {
402: listener.thumbnailStarted(this , imageIndex,
403: thumbnailIndex);
404: }
405: }
406: }
407:
408: protected void processWriteAborted() {
409: if (progressListeners != null) {
410: for (IIOWriteProgressListener listener : progressListeners) {
411: listener.writeAborted(this );
412: }
413: }
414: }
415:
416: public void removeAllIIOWriteProgressListeners() {
417: progressListeners = null;
418: }
419:
420: public void removeAllIIOWriteWarningListeners() {
421: warningListeners = null;
422: warningLocales = null;
423: }
424:
425: public void removeIIOWriteProgressListener(
426: IIOWriteProgressListener listener) {
427: if (progressListeners != null && listener != null) {
428: if (progressListeners.remove(listener)
429: && progressListeners.isEmpty()) {
430: progressListeners = null;
431: }
432: }
433: }
434:
435: public void removeIIOWriteWarningListener(
436: IIOWriteWarningListener listener) {
437: if (warningListeners == null || listener == null) {
438: return;
439: }
440:
441: int idx = warningListeners.indexOf(listener);
442: if (idx > -1) {
443: warningListeners.remove(idx);
444: warningLocales.remove(idx);
445:
446: if (warningListeners.isEmpty()) {
447: warningListeners = null;
448: warningLocales = null;
449: }
450: }
451: }
452:
453: public void removeImage(int imageIndex) throws IOException {
454: unsupportedOperation();
455: }
456:
457: public void replaceImageMetadata(int imageIndex,
458: IIOMetadata imageMetadata) throws IOException {
459: unsupportedOperation();
460: }
461:
462: public void replacePixels(RenderedImage image, ImageWriteParam param)
463: throws IOException {
464: unsupportedOperation();
465: }
466:
467: public void replacePixels(Raster raster, ImageWriteParam param)
468: throws IOException {
469: unsupportedOperation();
470: }
471:
472: public void replaceStreamMetadata(IIOMetadata streamMetadata)
473: throws IOException {
474: unsupportedOperation();
475: }
476:
477: public void setLocale(Locale locale) {
478: if (locale == null) {
479: this .locale = null;
480: return;
481: }
482:
483: Locale[] locales = getAvailableLocales();
484: boolean validLocale = false;
485: if (locales != null) {
486: for (int i = 0; i < locales.length; i++) {
487: if (locale.equals(locales[i])) {
488: validLocale = true;
489: break;
490: }
491: }
492: }
493:
494: if (validLocale) {
495: this .locale = locale;
496: } else {
497: throw new IllegalArgumentException("Invalid locale!");
498: }
499: }
500:
501: public void reset() {
502: setOutput(null);
503: setLocale(null);
504: removeAllIIOWriteWarningListeners();
505: removeAllIIOWriteProgressListeners();
506: clearAbortRequest();
507: }
508:
509: public void writeInsert(int imageIndex, IIOImage image,
510: ImageWriteParam param) throws IOException {
511: unsupportedOperation();
512: }
513:
514: public void writeToSequence(IIOImage image, ImageWriteParam param)
515: throws IOException {
516: unsupportedOperation();
517: }
518: }
|