Source Code Cross Referenced for ImageCodec.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » codec » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » com.sun.media.jai.codec 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: ImageCodec.java,v $
003:         *
004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * Use is subject to license terms.
007:         *
008:         * $Revision: 1.3 $
009:         * $Date: 2005/12/07 00:25:26 $
010:         * $State: Exp $
011:         */
012:        package com.sun.media.jai.codec;
013:
014:        import java.awt.RenderingHints;
015:        import java.awt.Transparency;
016:        import java.awt.color.ColorSpace;
017:        import java.awt.image.ColorModel;
018:        import java.awt.image.DataBuffer;
019:        import java.awt.image.ComponentColorModel;
020:        import java.awt.image.IndexColorModel;
021:        import java.awt.image.RenderedImage;
022:        import java.awt.image.SampleModel;
023:        import java.io.File;
024:        import java.io.InputStream;
025:        import java.io.IOException;
026:        import java.io.OutputStream;
027:        import java.util.Enumeration;
028:        import java.util.Hashtable;
029:        import java.util.Vector;
030:        import com.sun.media.jai.codecimpl.BMPCodec;
031:        import com.sun.media.jai.codecimpl.FPXCodec;
032:        import com.sun.media.jai.codecimpl.GIFCodec;
033:        import com.sun.media.jai.codecimpl.JPEGCodec;
034:        import com.sun.media.jai.codecimpl.PNGCodec;
035:        import com.sun.media.jai.codecimpl.PNMCodec;
036:        import com.sun.media.jai.codecimpl.TIFFCodec;
037:        import com.sun.media.jai.codecimpl.WBMPCodec;
038:        import com.sun.media.jai.codecimpl.ImagingListenerProxy;
039:        import com.sun.media.jai.codecimpl.util.FloatDoubleColorModel;
040:        import com.sun.media.jai.util.SimpleCMYKColorSpace;
041:
042:        /**
043:         * An abstract class allowing the creation of image decoders and
044:         * encoders.  Instances of <code>ImageCodec</code> may be registered.
045:         * Once a codec has been registered, the format name associated with
046:         * it may be used as the <code>name</code> parameter in the
047:         * <code>createImageEncoder()</code> and <code>createImageDecoder()</code>
048:         * methods.
049:         *
050:         * <p> Additionally, subclasses of <code>ImageCodec</code>
051:         * are able to perform recognition of their particular format,
052:         * wither by inspection of a fixed-length file header or by
053:         * arbitrary access to the source data stream.
054:         *
055:         * <p> Format recognition is performed by two variants of the
056:         * <code>isFormatRecognized()</code> method.  Which variant should be
057:         * called is determined by the output of the codec's
058:         * <codec>getNumHeaderBytes()</code> method, which returns 0 if
059:         * arbitrary access to the stream is required, and otherwise returns
060:         * the number of header bytes required to recognize the format.
061:         * Each subclass of <code>ImageCodec</code> needs to implement only
062:         * one of the two variants.
063:         *
064:         * <p><b> This class is not a committed part of the JAI API.  It may
065:         * be removed or changed in future releases of JAI.</b>
066:         */
067:        public abstract class ImageCodec {
068:
069:            private static Hashtable codecs = new Hashtable();
070:
071:            /** Allow only subclasses to instantiate this class. */
072:            protected ImageCodec() {
073:            }
074:
075:            /**
076:             * Load the JPEG and PNM codecs.
077:             */
078:            static {
079:                registerCodec(new BMPCodec());
080:                registerCodec(new GIFCodec());
081:                registerCodec(new FPXCodec());
082:                registerCodec(new JPEGCodec());
083:                registerCodec(new PNGCodec());
084:                registerCodec(new PNMCodec());
085:                registerCodec(new TIFFCodec());
086:                registerCodec(new WBMPCodec());
087:            }
088:
089:            /**
090:             * Returns the <code>ImageCodec</code> associated with the given
091:             * name.  <code>null</code> is returned if no codec is registered
092:             * with the given name.  Case is not significant.
093:             *
094:             * @param name The name associated with the codec.
095:             * @return The associated <code>ImageCodec</code>, or <code>null</code>.
096:             */
097:            public static ImageCodec getCodec(String name) {
098:                return (ImageCodec) codecs.get(name.toLowerCase());
099:            }
100:
101:            /**
102:             * Associates an <code>ImageCodec</code> with its format name, as
103:             * determined by its <code>getFormatName()</code> method.  Case is
104:             * not significant.  Any codec previously associated with the name
105:             * is discarded.
106:             *
107:             * @param codec The <code>ImageCodec</code> object to be registered.
108:             */
109:            public static void registerCodec(ImageCodec codec) {
110:                codecs.put(codec.getFormatName().toLowerCase(), codec);
111:            }
112:
113:            /**
114:             * Unregisters the <code>ImageCodec</code> object currently
115:             * responsible for handling the named format.  Case is not
116:             * significant.
117:             *
118:             * @param name The name associated with the codec to be removed.
119:             */
120:            public static void unregisterCodec(String name) {
121:                codecs.remove(name.toLowerCase());
122:            }
123:
124:            /**
125:             * Returns an <code>Enumeration</code> of all regstered
126:             * <code>ImageCodec</code> objects.
127:             */
128:            public static Enumeration getCodecs() {
129:                return codecs.elements();
130:            }
131:
132:            /**
133:             * Returns an <code>ImageEncoder</code> object suitable for
134:             * encoding to the supplied <code>OutputStream</code>, using the
135:             * supplied <code>ImageEncoderParam</code> object.
136:             *
137:             * @param name The name associated with the codec.
138:             * @param dst An <code>OutputStream</code> to write to.
139:             * @param param An instance of <code>ImageEncoderParam</code> suitable
140:             *        for use with the named codec, or <code>null</code>.
141:             * @return An instance of <code>ImageEncoder</code>, or <code>null</code>.
142:             */
143:            public static ImageEncoder createImageEncoder(String name,
144:                    OutputStream dst, ImageEncodeParam param) {
145:                ImageCodec codec = getCodec(name);
146:                if (codec == null) {
147:                    return null;
148:                }
149:                return codec.createImageEncoder(dst, param);
150:            }
151:
152:            /**
153:             * Returns an <code>ImageDecoder</code> object suitable for
154:             * decoding from the supplied <code>InputStream</code>, using the
155:             * supplied <code>ImageDecodeParam</code> object.
156:             *
157:             * @param name The name associated with the codec.
158:             * @param src An <code>InputStream</code> to read from.
159:             * @param param An instance of <code>ImageDecodeParam</code> suitable
160:             *        for use with the named codec, or <code>null</code>.
161:             * @return An instance of <code>ImageDecoder</code>, or <code>null</code>.
162:             */
163:            public static ImageDecoder createImageDecoder(String name,
164:                    InputStream src, ImageDecodeParam param) {
165:                ImageCodec codec = getCodec(name);
166:                if (codec == null) {
167:                    return null;
168:                }
169:                return codec.createImageDecoder(src, param);
170:            }
171:
172:            /**
173:             * Returns an <code>ImageDecoder</code> object suitable for
174:             * decoding from the supplied <code>File</code>, using the
175:             * supplied <code>ImageDecodeParam</code> object.
176:             *
177:             * @param name The name associated with the codec.
178:             * @param src A <code>File</code> to read from.
179:             * @param param An instance of <code>ImageDecodeParam</code> suitable
180:             *        for use with the named codec, or <code>null</code>.
181:             * @return An instance of <code>ImageDecoder</code>, or <code>null</code>.
182:             */
183:            public static ImageDecoder createImageDecoder(String name,
184:                    File src, ImageDecodeParam param) throws IOException {
185:                ImageCodec codec = getCodec(name);
186:                if (codec == null) {
187:                    return null;
188:                }
189:                return codec.createImageDecoder(src, param);
190:            }
191:
192:            /**
193:             * Returns an <code>ImageDecoder</code> object suitable for
194:             * decoding from the supplied <code>SeekableStream</code>, using the
195:             * supplied <code>ImageDecodeParam</code> object.
196:             *
197:             * @param name The name associated with the codec.
198:             * @param src A <code>SeekableStream</code> to read from.
199:             * @param param An instance of <code>ImageDecodeParam</code> suitable
200:             *        for use with the named codec, or <code>null</code>.
201:             * @return An instance of <code>ImageDecoder</code>, or <code>null</code>.
202:             */
203:            public static ImageDecoder createImageDecoder(String name,
204:                    SeekableStream src, ImageDecodeParam param) {
205:                ImageCodec codec = getCodec(name);
206:                if (codec == null) {
207:                    return null;
208:                }
209:                return codec.createImageDecoder(src, param);
210:            }
211:
212:            private static String[] vectorToStrings(Vector nameVec) {
213:                int count = nameVec.size();
214:                String[] names = new String[count];
215:                for (int i = 0; i < count; i++) {
216:                    names[i] = (String) nameVec.elementAt(i);
217:                }
218:                return names;
219:            }
220:
221:            /**
222:             * Returns an array of <code>String</code>s indicating the names
223:             * of registered <code>ImageCodec</code>s that may be appropriate
224:             * for reading the given <code>SeekableStream</code>.
225:             *
226:             * <p> If the <code>src</code> <code>SeekableStream</code> does
227:             * not support seeking backwards (that is, its
228:             * <code>canSeekBackwards()</code> method returns
229:             * <code>false</code>) then only <code>FormatRecognizer</code>s
230:             * that require only a fixed-length header will be checked.
231:             *
232:             * <p> If the <code>src</code> stream does not support seeking
233:             * backwards, it must support marking, as determined by its
234:             * <code>markSupported()</code> method.
235:             *
236:             * @param src A <code>SeekableStream</code> which optionally supports
237:             *        seeking backwards.
238:             * @return An array of <code>String</code>s.
239:             *
240:             * @throws IllegalArgumentException if <code>src</code> supports
241:             *         neither seeking backwards nor marking.
242:             */
243:            public static String[] getDecoderNames(SeekableStream src) {
244:                if (!src.canSeekBackwards() && !src.markSupported()) {
245:                    throw new IllegalArgumentException(JaiI18N
246:                            .getString("ImageCodec2"));
247:                }
248:
249:                Enumeration enumeration = codecs.elements();
250:                Vector nameVec = new Vector();
251:
252:                String opName = null;
253:                while (enumeration.hasMoreElements()) {
254:                    ImageCodec codec = (ImageCodec) enumeration.nextElement();
255:
256:                    int bytesNeeded = codec.getNumHeaderBytes();
257:                    if ((bytesNeeded == 0) && !src.canSeekBackwards()) {
258:                        continue;
259:                    }
260:
261:                    try {
262:                        if (bytesNeeded > 0) {
263:                            src.mark(bytesNeeded);
264:                            byte[] header = new byte[bytesNeeded];
265:                            src.readFully(header);
266:                            src.reset();
267:
268:                            if (codec.isFormatRecognized(header)) {
269:                                nameVec.add(codec.getFormatName());
270:                            }
271:                        } else {
272:                            long pointer = src.getFilePointer();
273:                            src.seek(0L);
274:                            if (codec.isFormatRecognized(src)) {
275:                                nameVec.add(codec.getFormatName());
276:                            }
277:                            src.seek(pointer);
278:                        }
279:                    } catch (IOException e) {
280:                        ImagingListenerProxy.errorOccurred(JaiI18N
281:                                .getString("ImageCodec3"), e, ImageCodec.class,
282:                                false);
283:                        //                e.printStackTrace();
284:                    }
285:                }
286:
287:                return vectorToStrings(nameVec);
288:            }
289:
290:            /**
291:             * Returns an array of <code>String</code>s indicating the names
292:             * of registered <code>ImageCodec</code>s that may be appropriate
293:             * for writing the given <code>RenderedImage</code>, using the
294:             * optional <code>ImageEncodeParam</code>, which may be
295:             * <code>null</code>.
296:             *
297:             * @param im A <code>RenderedImage</code> to be encodec.
298:             * @param param An <code>ImageEncodeParam</code>, or null.
299:             * @return An array of <code>String</code>s.
300:             */
301:            public static String[] getEncoderNames(RenderedImage im,
302:                    ImageEncodeParam param) {
303:                Enumeration enumeration = codecs.elements();
304:                Vector nameVec = new Vector();
305:
306:                String opName = null;
307:                while (enumeration.hasMoreElements()) {
308:                    ImageCodec codec = (ImageCodec) enumeration.nextElement();
309:
310:                    if (codec.canEncodeImage(im, param)) {
311:                        nameVec.add(codec.getFormatName());
312:                    }
313:                }
314:
315:                return vectorToStrings(nameVec);
316:            }
317:
318:            /**
319:             * Returns the name of this image format.
320:             *
321:             * @return A <code>String</code> containing the name of the
322:             *         image format supported by this codec.
323:             */
324:            public abstract String getFormatName();
325:
326:            /**
327:             * Returns the number of bytes of header needed to recognize the
328:             * format, or 0 if an arbitrary number of bytes may be needed.
329:             * The default implementation returns 0.
330:             *
331:             * <p> The return value must be a constant for all instances of
332:             * each particular subclass of <code>ImageCodec</code>.
333:             *
334:             * <p> Although it is legal to always return 0, in some cases
335:             * processing may be more efficient if the number of bytes needed
336:             * is known in advance.
337:             */
338:            public int getNumHeaderBytes() {
339:                return 0;
340:            }
341:
342:            /**
343:             * Returns <code>true</code> if the format is recognized in the
344:             * initial portion of a stream.  The header will be passed in as a
345:             * <code>byte</code> array of length <code>getNumHeaderBytes()</code>.
346:             * This method should be called only if <code>getNumHeaderBytes()</code>
347:             * returns a value greater than 0.
348:             *
349:             * <p> The default implementation throws an exception to indicate
350:             * that it should never be called.
351:             *
352:             * @param header An array of <code>byte</code>s containing the input
353:             *        stream header.
354:             * @return <code>true</code> if the format is recognized.
355:             */
356:            public boolean isFormatRecognized(byte[] header) {
357:                throw new RuntimeException(JaiI18N.getString("ImageCodec0"));
358:            }
359:
360:            /**
361:             * Returns <code>true</code> if the format is recognized in the
362:             * input data stream.  This method should be called only if
363:             * <code>getNumHeaderBytesNeeded()</code> returns 0.
364:             *
365:             * <p> The source <code>SeekableStream</code> is guaranteed to
366:             * support seeking backwards, and should be seeked to 0 prior
367:             * to calling this method.
368:             *
369:             * <p> The default implementation throws an exception to indicate
370:             * that it should never be called.
371:             *
372:             * @param src A <code>SeekableStream</code> containing the input
373:             *        data.
374:             * @return <code>true</code> if the format is recognized.
375:             */
376:            public boolean isFormatRecognized(SeekableStream src)
377:                    throws IOException {
378:                throw new RuntimeException(JaiI18N.getString("ImageCodec1"));
379:            }
380:
381:            /**
382:             * Returns a <code>Class</code> object indicating the proper
383:             * subclass of <code>ImageEncodeParam</code> to be used with this
384:             * <code>ImageCodec</code>.  If encoding is not supported by this
385:             * codec, <code>null</code> is returned.  If encoding is
386:             * supported, but a parameter object is not used during encoding,
387:             * Object.class is returned to signal this fact.
388:             */
389:            protected abstract Class getEncodeParamClass();
390:
391:            /**
392:             * Returns a <code>Class</code> object indicating the proper
393:             * subclass of <code>ImageDecodeParam</code> to be used with this
394:             * <code>ImageCodec</code>.  If encoding is not supported by this
395:             * codec, <code>null</code> is returned.  If decoding is
396:             * supported, but a parameter object is not used during decoding,
397:             * Object.class is returned to signal this fact.
398:             */
399:            protected abstract Class getDecodeParamClass();
400:
401:            /**
402:             * In a concrete subclass of <code>ImageCodec</code>, returns an
403:             * implementation of the <code>ImageEncoder</code> interface
404:             * appropriate for that codec.
405:             *
406:             * @param dst An <code>OutputStream</code> to write to.
407:             * @param param An instance of <code>ImageEncoderParam</code>
408:             *        suitable for use with the <code>ImageCodec</code>
409:             *        subclass, or <code>null</code>.
410:             * @return An instance of <code>ImageEncoder</code>.
411:             */
412:            protected abstract ImageEncoder createImageEncoder(
413:                    OutputStream dst, ImageEncodeParam param);
414:
415:            /**
416:             * Returns <code>true</code> if the given image and encoder param
417:             * object are suitable for encoding by this <code>ImageCodec</code>.
418:             * For example, some codecs may only deal with images with a certain
419:             * number of bands; an attempt to encode an image with an unsupported
420:             * number of bands will fail.
421:             *
422:             * @param im a RenderedImage whose ability to be encoded is to be
423:             *        determined.
424:             * @param param a suitable <code>ImageEncodeParam</code> object,
425:             *        or <code>null</code>.
426:             */
427:            public abstract boolean canEncodeImage(RenderedImage im,
428:                    ImageEncodeParam param);
429:
430:            /**
431:             * Returns an implementation of the <code>ImageDecoder</code>
432:             * interface appropriate for that codec.  Subclasses of
433:             * <code>ImageCodec</code> may override this method if they wish
434:             * to accept data directly from an <code>InputStream</code>;
435:             * otherwise, this method will convert the source into a
436:             * backwards-seekable <code>SeekableStream</code> and call the
437:             * appropriate version of <code>createImageDecoder</code> for that
438:             * data type.
439:             *
440:             * <p> Instances of <code>ImageCodec</code> that do not require
441:             * the ability to seek backwards in their source
442:             * <code>SeekableStream</code> should override this method in
443:             * order to avoid the default call to
444:             * <code>SeekableStream.wrapInputStream(src, true)</code>.
445:             *
446:             * @param dst An <code>InputStream</code> to read from.
447:             * @param param An instance of <code>ImageDecodeParam</code>
448:             *        suitable for use with the <code>ImageCodec</code>
449:             *        subclass, or <code>null</code>.
450:             * @return An instance of <code>ImageDecoder</code>.
451:             */
452:            protected ImageDecoder createImageDecoder(InputStream src,
453:                    ImageDecodeParam param) {
454:                SeekableStream stream = SeekableStream.wrapInputStream(src,
455:                        true);
456:                return createImageDecoder(stream, param);
457:            }
458:
459:            /**
460:             * Returns an implementation of the <code>ImageDecoder</code>
461:             * interface appropriate for that codec.  Subclasses of
462:             * <code>ImageCodec</code> may override this method if they wish
463:             * to accept data directly from a <code>File</code>;
464:             * otherwise, this method will convert the source into a
465:             * <code>SeekableStream</code> and call the appropriate
466:             * version of <code>createImageDecoder</code> for that data type.
467:             *
468:             * @param dst A <code>File</code> to read from.
469:             * @param param An instance of <code>ImageDecodeParam</code>
470:             *        suitable for use with the <code>ImageCodec</code>
471:             *        subclass, or <code>null</code>.
472:             * @return An instance of <code>ImageDecoder</code>.
473:             */
474:            protected ImageDecoder createImageDecoder(File src,
475:                    ImageDecodeParam param) throws IOException {
476:                return createImageDecoder(new FileSeekableStream(src), param);
477:            }
478:
479:            /**
480:             * In a concrete subclass of <code>ImageCodec</code>, returns an
481:             * implementation of the <code>ImageDecoder</code> interface
482:             * appropriate for that codec.
483:             *
484:             * @param dst A <code>SeekableStream</code> to read from.
485:             * @param param An instance of <code>ImageDecodeParam</code>
486:             *        suitable for use with the <code>ImageCodec</code>
487:             *        subclass, or <code>null</code>.
488:             * @return An instance of <code>ImageDecoder</code>.
489:             */
490:            protected abstract ImageDecoder createImageDecoder(
491:                    SeekableStream src, ImageDecodeParam param);
492:
493:            // ColorModel utility functions
494:
495:            private static final byte[][] grayIndexCmaps = { null,
496:                    // 1 bit
497:                    { (byte) 0x00, (byte) 0xff },
498:                    // 2 bits
499:                    { (byte) 0x00, (byte) 0x55, (byte) 0xaa, (byte) 0xff },
500:                    null,
501:                    // 4 bits
502:                    { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33,
503:                            (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77,
504:                            (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb,
505:                            (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff } };
506:
507:            /**
508:             * A convenience methods to create an instance of
509:             * <code>IndexColorModel</code> suitable for the given 1-banded
510:             * <code>SampleModel</code>.
511:             *
512:             * @param sm a 1-banded <code>SampleModel</code>.
513:             * @param blackIsZero <code>true</code> if the gray ramp should
514:             *        go from black to white, <code>false</code>otherwise.
515:             */
516:            public static ColorModel createGrayIndexColorModel(SampleModel sm,
517:                    boolean blackIsZero) {
518:                if (sm.getNumBands() != 1) {
519:                    throw new IllegalArgumentException();
520:                }
521:                int sampleSize = sm.getSampleSize(0);
522:
523:                byte[] cmap = null;
524:                if (sampleSize < 8) {
525:                    cmap = grayIndexCmaps[sampleSize];
526:                    if (!blackIsZero) {
527:                        int length = cmap.length;
528:                        byte[] newCmap = new byte[length];
529:                        for (int i = 0; i < length; i++) {
530:                            newCmap[i] = cmap[length - i - 1];
531:                        }
532:                        cmap = newCmap;
533:                    }
534:                } else {
535:                    cmap = new byte[256];
536:                    if (blackIsZero) {
537:                        for (int i = 0; i < 256; i++) {
538:                            cmap[i] = (byte) i;
539:                        }
540:                    } else {
541:                        for (int i = 0; i < 256; i++) {
542:                            cmap[i] = (byte) (255 - i);
543:                        }
544:                    }
545:                }
546:
547:                return new IndexColorModel(sampleSize, cmap.length, cmap, cmap,
548:                        cmap);
549:            }
550:
551:            private static final int[] GrayBits8 = { 8 };
552:            private static final ComponentColorModel colorModelGray8 = new ComponentColorModel(
553:                    ColorSpace.getInstance(ColorSpace.CS_GRAY), GrayBits8,
554:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
555:
556:            private static final int[] GrayAlphaBits8 = { 8, 8 };
557:            private static final ComponentColorModel colorModelGrayAlpha8 = new ComponentColorModel(
558:                    ColorSpace.getInstance(ColorSpace.CS_GRAY), GrayAlphaBits8,
559:                    true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
560:
561:            private static final int[] GrayBits16 = { 16 };
562:            private static final ComponentColorModel colorModelGray16 = new ComponentColorModel(
563:                    ColorSpace.getInstance(ColorSpace.CS_GRAY), GrayBits16,
564:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
565:
566:            private static final int[] GrayAlphaBits16 = { 16, 16 };
567:            private static final ComponentColorModel colorModelGrayAlpha16 = new ComponentColorModel(
568:                    ColorSpace.getInstance(ColorSpace.CS_GRAY),
569:                    GrayAlphaBits16, true, false, Transparency.TRANSLUCENT,
570:                    DataBuffer.TYPE_USHORT);
571:
572:            private static final int[] GrayBits32 = { 32 };
573:            private static final ComponentColorModel colorModelGray32 = new ComponentColorModel(
574:                    ColorSpace.getInstance(ColorSpace.CS_GRAY), GrayBits32,
575:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_INT);
576:
577:            private static final int[] GrayAlphaBits32 = { 32, 32 };
578:            private static final ComponentColorModel colorModelGrayAlpha32 = new ComponentColorModel(
579:                    ColorSpace.getInstance(ColorSpace.CS_GRAY),
580:                    GrayAlphaBits32, true, false, Transparency.TRANSLUCENT,
581:                    DataBuffer.TYPE_INT);
582:
583:            private static final int[] RGBBits8 = { 8, 8, 8 };
584:            private static final ComponentColorModel colorModelRGB8 = new ComponentColorModel(
585:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBBits8,
586:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
587:
588:            private static final int[] RGBABits8 = { 8, 8, 8, 8 };
589:            private static final ComponentColorModel colorModelRGBA8 = new ComponentColorModel(
590:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBABits8,
591:                    true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
592:
593:            private static final int[] RGBBits16 = { 16, 16, 16 };
594:            private static final ComponentColorModel colorModelRGB16 = new ComponentColorModel(
595:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBBits16,
596:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
597:
598:            private static final int[] RGBABits16 = { 16, 16, 16, 16 };
599:            private static final ComponentColorModel colorModelRGBA16 = new ComponentColorModel(
600:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBABits16,
601:                    true, false, Transparency.TRANSLUCENT,
602:                    DataBuffer.TYPE_USHORT);
603:
604:            private static final int[] RGBBits32 = { 32, 32, 32 };
605:            private static final ComponentColorModel colorModelRGB32 = new ComponentColorModel(
606:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBBits32,
607:                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_INT);
608:
609:            private static final int[] RGBABits32 = { 32, 32, 32, 32 };
610:            private static final ComponentColorModel colorModelRGBA32 = new ComponentColorModel(
611:                    ColorSpace.getInstance(ColorSpace.CS_sRGB), RGBABits32,
612:                    true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_INT);
613:
614:            /**
615:             * A convenience method to create an instance of
616:             * <code>ComponentColorModel</code> suitable for use with the
617:             * given <code>SampleModel</code>.  The <code>SampleModel</code>
618:             * should have a data type of <code>DataBuffer.TYPE_BYTE</code>,
619:             * <code>TYPE_USHORT</code>, or <code>TYPE_INT</code> and between
620:             * 1 and 4 bands.  Depending on the number of bands of the
621:             * <code>SampleModel</code>, either a gray, gray+alpha, rgb, or
622:             * rgb+alpha <code>ColorModel</code> is returned.
623:             */
624:            public static ColorModel createComponentColorModel(SampleModel sm) {
625:                int type = sm.getDataType();
626:                int bands = sm.getNumBands();
627:                ComponentColorModel cm = null;
628:
629:                if (type == DataBuffer.TYPE_BYTE) {
630:                    switch (bands) {
631:                    case 1:
632:                        cm = colorModelGray8;
633:                        break;
634:                    case 2:
635:                        cm = colorModelGrayAlpha8;
636:                        break;
637:                    case 3:
638:                        cm = colorModelRGB8;
639:                        break;
640:                    case 4:
641:                        cm = colorModelRGBA8;
642:                        break;
643:                    }
644:                } else if (type == DataBuffer.TYPE_USHORT) {
645:                    switch (bands) {
646:                    case 1:
647:                        cm = colorModelGray16;
648:                        break;
649:                    case 2:
650:                        cm = colorModelGrayAlpha16;
651:                        break;
652:                    case 3:
653:                        cm = colorModelRGB16;
654:                        break;
655:                    case 4:
656:                        cm = colorModelRGBA16;
657:                        break;
658:                    }
659:                } else if (type == DataBuffer.TYPE_INT) {
660:                    switch (bands) {
661:                    case 1:
662:                        cm = colorModelGray32;
663:                        break;
664:                    case 2:
665:                        cm = colorModelGrayAlpha32;
666:                        break;
667:                    case 3:
668:                        cm = colorModelRGB32;
669:                        break;
670:                    case 4:
671:                        cm = colorModelRGBA32;
672:                        break;
673:                    }
674:                } else if (type == DataBuffer.TYPE_FLOAT && bands >= 1
675:                        && bands <= 4) {
676:                    ColorSpace cs = bands <= 2 ? ColorSpace
677:                            .getInstance(ColorSpace.CS_GRAY) : ColorSpace
678:                            .getInstance(ColorSpace.CS_sRGB);
679:                    boolean hasAlpha = bands % 2 == 0;
680:                    cm = new FloatDoubleColorModel(cs, hasAlpha, false,
681:                            hasAlpha ? Transparency.TRANSLUCENT
682:                                    : Transparency.OPAQUE,
683:                            DataBuffer.TYPE_FLOAT);
684:                }
685:
686:                return cm;
687:            }
688:
689:            /**
690:             * A convenience method to create an instance of
691:             * <code>ComponentColorModel</code> suitable for use with the
692:             * given <code>SampleModel</code> and <ColorSpace</code>.  The 
693:             * <code>SampleModel</code>
694:             * should have a data type of <code>DataBuffer.TYPE_BYTE</code>,
695:             * <code>TYPE_USHORT</code>, or <code>TYPE_INT</code> and between
696:             * 1 and 4 bands.  Depending on the number of bands of the
697:             * <code>SampleModel</code>, either a gray, gray+alpha, rgb, or
698:             * rgb+alpha <code>ColorModel</code> is returned.
699:             */
700:            public static ColorModel createComponentColorModel(SampleModel sm,
701:                    ColorSpace cp) {
702:                if (cp == null)
703:                    return createComponentColorModel(sm);
704:                int type = sm.getDataType();
705:                int bands = sm.getNumBands();
706:                ComponentColorModel cm = null;
707:
708:                int[] bits = null;
709:                int transferType = -1;
710:                boolean hasAlpha = (bands % 2 == 0);
711:                if (cp instanceof  SimpleCMYKColorSpace)
712:                    hasAlpha = false;
713:                int transparency = hasAlpha ? Transparency.TRANSLUCENT
714:                        : Transparency.OPAQUE;
715:                if (type == DataBuffer.TYPE_BYTE) {
716:                    transferType = DataBuffer.TYPE_BYTE;
717:                    switch (bands) {
718:                    case 1:
719:                        bits = GrayBits8;
720:                        break;
721:                    case 2:
722:                        bits = GrayAlphaBits8;
723:                        break;
724:                    case 3:
725:                        bits = RGBBits8;
726:                        break;
727:                    case 4:
728:                        bits = RGBABits8;
729:                        break;
730:                    }
731:                } else if (type == DataBuffer.TYPE_USHORT) {
732:                    transferType = DataBuffer.TYPE_USHORT;
733:                    switch (bands) {
734:                    case 1:
735:                        bits = GrayBits16;
736:                        break;
737:                    case 2:
738:                        bits = GrayAlphaBits16;
739:                        break;
740:                    case 3:
741:                        bits = RGBBits16;
742:                        break;
743:                    case 4:
744:                        bits = RGBABits16;
745:                        break;
746:                    }
747:                } else if (type == DataBuffer.TYPE_INT) {
748:                    transferType = DataBuffer.TYPE_INT;
749:                    switch (bands) {
750:                    case 1:
751:                        bits = GrayBits32;
752:                        break;
753:                    case 2:
754:                        bits = GrayAlphaBits32;
755:                        break;
756:                    case 3:
757:                        bits = RGBBits32;
758:                        break;
759:                    case 4:
760:                        bits = RGBABits32;
761:                        break;
762:                    }
763:                }
764:
765:                if (type == DataBuffer.TYPE_FLOAT && bands >= 1 && bands <= 4) {
766:                    cm = new FloatDoubleColorModel(cp, hasAlpha, false,
767:                            transparency, DataBuffer.TYPE_FLOAT);
768:                } else {
769:                    cm = new ComponentColorModel(cp, bits, hasAlpha, false,
770:                            transparency, transferType);
771:                }
772:
773:                return cm;
774:            }
775:
776:            /**
777:             * Tests whether the color indices represent a gray-scale image.
778:             *
779:             * @param r The red channel color indices.
780:             * @param g The green channel color indices.
781:             * @param b The blue channel color indices.
782:             * @return If all the indices have 256 entries, and are identical mappings,
783:             *	       return <code>true</code>; otherwise, return <code>false</code>.
784:             */
785:            public static boolean isIndicesForGrayscale(byte[] r, byte[] g,
786:                    byte[] b) {
787:                if (r.length != g.length || r.length != b.length)
788:                    return false;
789:
790:                int size = r.length;
791:
792:                if (size != 256)
793:                    return false;
794:
795:                for (int i = 0; i < size; i++) {
796:                    byte temp = (byte) i;
797:
798:                    if (r[i] != temp || g[i] != temp || b[i] != temp)
799:                        return false;
800:                }
801:
802:                return true;
803:            }
804:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.