Source Code Cross Referenced for TIFFBaseJPEGCompressor.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » imageioimpl » plugins » tiff » 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.imageioimpl.plugins.tiff 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: TIFFBaseJPEGCompressor.java,v $
003:         *
004:         * 
005:         * Copyright (c) 2006 Sun Microsystems, Inc. All  Rights Reserved.
006:         * 
007:         * Redistribution and use in source and binary forms, with or without
008:         * modification, are permitted provided that the following conditions
009:         * are met: 
010:         * 
011:         * - Redistribution of source code must retain the above copyright 
012:         *   notice, this  list of conditions and the following disclaimer.
013:         * 
014:         * - Redistribution in binary form must reproduce the above copyright
015:         *   notice, this list of conditions and the following disclaimer in 
016:         *   the documentation and/or other materials provided with the
017:         *   distribution.
018:         * 
019:         * Neither the name of Sun Microsystems, Inc. or the names of 
020:         * contributors may be used to endorse or promote products derived 
021:         * from this software without specific prior written permission.
022:         * 
023:         * This software is provided "AS IS," without a warranty of any 
024:         * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025:         * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026:         * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027:         * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028:         * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029:         * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030:         * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031:         * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032:         * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033:         * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034:         * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035:         * POSSIBILITY OF SUCH DAMAGES. 
036:         * 
037:         * You acknowledge that this software is not designed or intended for 
038:         * use in the design, construction, operation or maintenance of any 
039:         * nuclear facility. 
040:         *
041:         * $Revision: 1.5 $
042:         * $Date: 2007/09/01 00:27:20 $
043:         * $State: Exp $
044:         */
045:        package com.sun.media.imageioimpl.plugins.tiff;
046:
047:        import com.sun.media.imageio.plugins.tiff.TIFFCompressor;
048:        import java.awt.Point;
049:        import java.awt.Transparency;
050:        import java.awt.color.ColorSpace;
051:        import java.awt.image.BufferedImage;
052:        import java.awt.image.ColorModel;
053:        import java.awt.image.ComponentColorModel;
054:        import java.awt.image.DataBuffer;
055:        import java.awt.image.DataBufferByte;
056:        import java.awt.image.PixelInterleavedSampleModel;
057:        import java.awt.image.Raster;
058:        import java.awt.image.SampleModel;
059:        import java.awt.image.WritableRaster;
060:        import java.io.IOException;
061:        import java.io.ByteArrayOutputStream;
062:        import java.util.ArrayList;
063:        import java.util.Arrays;
064:        import java.util.List;
065:        import java.util.Iterator;
066:        import javax.imageio.IIOException;
067:        import javax.imageio.IIOImage;
068:        import javax.imageio.ImageIO;
069:        import javax.imageio.ImageReader;
070:        import javax.imageio.ImageWriteParam;
071:        import javax.imageio.ImageWriter;
072:        import javax.imageio.metadata.IIOInvalidTreeException;
073:        import javax.imageio.metadata.IIOMetadata;
074:        import javax.imageio.metadata.IIOMetadataNode;
075:        import javax.imageio.spi.ImageWriterSpi;
076:        import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
077:        import javax.imageio.stream.ImageOutputStream;
078:        import javax.imageio.stream.MemoryCacheImageOutputStream;
079:        import org.w3c.dom.Node;
080:
081:        /**
082:         * Base class for all possible forms of JPEG compression in TIFF.
083:         */
084:        public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor {
085:
086:            private static final boolean DEBUG = false; // XXX false for release.
087:
088:            // Stream metadata format.
089:            protected static final String STREAM_METADATA_NAME = "javax_imageio_jpeg_stream_1.0";
090:
091:            // Image metadata format.
092:            protected static final String IMAGE_METADATA_NAME = "javax_imageio_jpeg_image_1.0";
093:
094:            // ImageWriteParam passed in.
095:            private ImageWriteParam param = null;
096:
097:            /**
098:             * ImageWriteParam for JPEG writer.
099:             * May be initialized by {@link #initJPEGWriter()}.
100:             */
101:            protected JPEGImageWriteParam JPEGParam = null;
102:
103:            /**
104:             * The JPEG writer.
105:             * May be initialized by {@link #initJPEGWriter()}.
106:             */
107:            protected ImageWriter JPEGWriter = null;
108:
109:            /**
110:             * Whether to write abbreviated JPEG streams (default == false).
111:             * A subclass which sets this to <code>true</code> should also
112:             * initialized {@link #JPEGStreamMetadata}.
113:             */
114:            protected boolean writeAbbreviatedStream = false;
115:
116:            /**
117:             * Stream metadata equivalent to a tables-only stream such as in
118:             * the <code>JPEGTables</code>. Default value is <code>null</code>.
119:             * This should be set by any subclass which sets
120:             * {@link writeAbbreviatedStream} to <code>true</code>.
121:             */
122:            protected IIOMetadata JPEGStreamMetadata = null;
123:
124:            // A pruned image metadata object containing only essential nodes.
125:            private IIOMetadata JPEGImageMetadata = null;
126:
127:            // Whether the codecLib native JPEG writer is being used.
128:            private boolean usingCodecLib;
129:
130:            // Array-based output stream.
131:            private IIOByteArrayOutputStream baos;
132:
133:            /**
134:             * Removes nonessential nodes from a JPEG native image metadata tree.
135:             * All nodes derived from JPEG marker segments other than DHT, DQT,
136:             * SOF, SOS segments are removed unless <code>pruneTables</code> is
137:             * <code>true</code> in which case the nodes derived from the DHT and
138:             * DQT marker segments are also removed.
139:             *
140:             * @param tree A <tt>javax_imageio_jpeg_image_1.0</tt> tree.
141:             * @param pruneTables Whether to prune Huffman and quantization tables.
142:             * @throws IllegalArgumentException if <code>tree</code> is
143:             * <code>null</code> or is not the root of a JPEG native image
144:             * metadata tree.
145:             */
146:            private static void pruneNodes(Node tree, boolean pruneTables) {
147:                if (tree == null) {
148:                    throw new IllegalArgumentException("tree == null!");
149:                }
150:                if (!tree.getNodeName().equals(IMAGE_METADATA_NAME)) {
151:                    throw new IllegalArgumentException("root node name is not "
152:                            + IMAGE_METADATA_NAME + "!");
153:                }
154:                if (DEBUG) {
155:                    System.out.println("pruneNodes(" + tree + "," + pruneTables
156:                            + ")");
157:                }
158:
159:                // Create list of required nodes.
160:                List wantedNodes = new ArrayList();
161:                wantedNodes.addAll(Arrays.asList(new String[] { "JPEGvariety",
162:                        "markerSequence", "sof", "componentSpec", "sos",
163:                        "scanComponentSpec" }));
164:
165:                // Add Huffman and quantization table nodes if not pruning tables.
166:                if (!pruneTables) {
167:                    wantedNodes.add("dht");
168:                    wantedNodes.add("dhtable");
169:                    wantedNodes.add("dqt");
170:                    wantedNodes.add("dqtable");
171:                }
172:
173:                IIOMetadataNode iioTree = (IIOMetadataNode) tree;
174:
175:                List nodes = getAllNodes(iioTree, null);
176:                int numNodes = nodes.size();
177:
178:                for (int i = 0; i < numNodes; i++) {
179:                    Node node = (Node) nodes.get(i);
180:                    if (!wantedNodes.contains(node.getNodeName())) {
181:                        if (DEBUG) {
182:                            System.out
183:                                    .println("Removing " + node.getNodeName());
184:                        }
185:                        node.getParentNode().removeChild(node);
186:                    }
187:                }
188:            }
189:
190:            private static List getAllNodes(IIOMetadataNode root, List nodes) {
191:                if (nodes == null)
192:                    nodes = new ArrayList();
193:
194:                if (root.hasChildNodes()) {
195:                    Node sibling = root.getFirstChild();
196:                    while (sibling != null) {
197:                        nodes.add(sibling);
198:                        nodes = getAllNodes((IIOMetadataNode) sibling, nodes);
199:                        sibling = sibling.getNextSibling();
200:                    }
201:                }
202:
203:                return nodes;
204:            }
205:
206:            public TIFFBaseJPEGCompressor(String compressionType,
207:                    int compressionTagValue, boolean isCompressionLossless,
208:                    ImageWriteParam param) {
209:                super (compressionType, compressionTagValue,
210:                        isCompressionLossless);
211:
212:                this .param = param;
213:            }
214:
215:            /**
216:             * A <code>ByteArrayOutputStream</code> which allows writing to an
217:             * <code>ImageOutputStream</code>.
218:             */
219:            private static class IIOByteArrayOutputStream extends
220:                    ByteArrayOutputStream {
221:                IIOByteArrayOutputStream() {
222:                    super ();
223:                }
224:
225:                IIOByteArrayOutputStream(int size) {
226:                    super (size);
227:                }
228:
229:                public synchronized void writeTo(ImageOutputStream ios)
230:                        throws IOException {
231:                    ios.write(buf, 0, count);
232:                }
233:            }
234:
235:            /**
236:             * Initializes the JPEGWriter and JPEGParam instance variables.
237:             * This method must be called before encode() is invoked.
238:             *
239:             * @param supportsStreamMetadata Whether the JPEG writer must
240:             * support JPEG native stream metadata, i.e., be capable of writing
241:             * abbreviated streams.
242:             * @param supportsImageMetadata Whether the JPEG writer must
243:             * support JPEG native image metadata.
244:             */
245:            protected void initJPEGWriter(boolean supportsStreamMetadata,
246:                    boolean supportsImageMetadata) {
247:                // Reset the writer to null if it does not match preferences.
248:                if (this .JPEGWriter != null
249:                        && (supportsStreamMetadata || supportsImageMetadata)) {
250:                    ImageWriterSpi spi = this .JPEGWriter
251:                            .getOriginatingProvider();
252:                    if (supportsStreamMetadata) {
253:                        String smName = spi.getNativeStreamMetadataFormatName();
254:                        if (smName == null
255:                                || !smName.equals(STREAM_METADATA_NAME)) {
256:                            this .JPEGWriter = null;
257:                        }
258:                    }
259:                    if (this .JPEGWriter != null && supportsImageMetadata) {
260:                        String imName = spi.getNativeImageMetadataFormatName();
261:                        if (imName == null
262:                                || !imName.equals(IMAGE_METADATA_NAME)) {
263:                            this .JPEGWriter = null;
264:                        }
265:                    }
266:                }
267:
268:                // Set the writer.
269:                if (this .JPEGWriter == null) {
270:                    Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
271:
272:                    while (iter.hasNext()) {
273:                        // Get a writer.
274:                        ImageWriter writer = (ImageWriter) iter.next();
275:
276:                        // Verify its metadata support level.
277:                        if (supportsStreamMetadata || supportsImageMetadata) {
278:                            ImageWriterSpi spi = writer
279:                                    .getOriginatingProvider();
280:                            if (supportsStreamMetadata) {
281:                                String smName = spi
282:                                        .getNativeStreamMetadataFormatName();
283:                                if (smName == null
284:                                        || !smName.equals(STREAM_METADATA_NAME)) {
285:                                    // Try the next one.
286:                                    continue;
287:                                }
288:                            }
289:                            if (supportsImageMetadata) {
290:                                String imName = spi
291:                                        .getNativeImageMetadataFormatName();
292:                                if (imName == null
293:                                        || !imName.equals(IMAGE_METADATA_NAME)) {
294:                                    // Try the next one.
295:                                    continue;
296:                                }
297:                            }
298:                        }
299:
300:                        // Set the writer.
301:                        this .JPEGWriter = writer;
302:                        break;
303:                    }
304:
305:                    if (this .JPEGWriter == null) {
306:                        // XXX The exception thrown should really be an IIOException.
307:                        throw new IllegalStateException(
308:                                "No appropriate JPEG writers found!");
309:                    }
310:                }
311:
312:                this .usingCodecLib = JPEGWriter.getClass().getName()
313:                        .startsWith("com.sun.media");
314:                if (DEBUG)
315:                    System.out.println("usingCodecLib = " + usingCodecLib);
316:
317:                // Initialize the ImageWriteParam.
318:                if (this .JPEGParam == null) {
319:                    if (param != null && param instanceof  JPEGImageWriteParam) {
320:                        JPEGParam = (JPEGImageWriteParam) param;
321:                    } else {
322:                        JPEGParam = new JPEGImageWriteParam(
323:                                writer != null ? writer.getLocale() : null);
324:                        if (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
325:                            JPEGParam
326:                                    .setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
327:                            JPEGParam.setCompressionQuality(param
328:                                    .getCompressionQuality());
329:                        }
330:                    }
331:                }
332:            }
333:
334:            /**
335:             * Retrieves image metadata with non-core nodes removed.
336:             */
337:            private IIOMetadata getImageMetadata(boolean pruneTables)
338:                    throws IIOException {
339:                if (DEBUG) {
340:                    System.out.println("getImageMetadata(" + pruneTables + ")");
341:                }
342:                if (JPEGImageMetadata == null
343:                        && IMAGE_METADATA_NAME.equals(JPEGWriter
344:                                .getOriginatingProvider()
345:                                .getNativeImageMetadataFormatName())) {
346:                    TIFFImageWriter tiffWriter = (TIFFImageWriter) this .writer;
347:
348:                    // Get default image metadata.
349:                    JPEGImageMetadata = JPEGWriter.getDefaultImageMetadata(
350:                            tiffWriter.imageType, JPEGParam);
351:
352:                    // Get the DOM tree.
353:                    Node tree = JPEGImageMetadata
354:                            .getAsTree(IMAGE_METADATA_NAME);
355:
356:                    // Remove unwanted marker segments.
357:                    try {
358:                        pruneNodes(tree, pruneTables);
359:                    } catch (IllegalArgumentException e) {
360:                        throw new IIOException("Error pruning unwanted nodes",
361:                                e);
362:                    }
363:
364:                    // Set the DOM back into the metadata.
365:                    try {
366:                        JPEGImageMetadata
367:                                .setFromTree(IMAGE_METADATA_NAME, tree);
368:                    } catch (IIOInvalidTreeException e) {
369:                        // XXX This should really be a warning that image data
370:                        // segments will be written with tables despite the
371:                        // present of JPEGTables field.
372:                        throw new IIOException(
373:                                "Cannot set pruned image metadata!", e);
374:                    }
375:                }
376:
377:                return JPEGImageMetadata;
378:            }
379:
380:            public final int encode(byte[] b, int off, int width, int height,
381:                    int[] bitsPerSample, int scanlineStride) throws IOException {
382:                if (this .JPEGWriter == null) {
383:                    throw new IIOException(
384:                            "JPEG writer has not been initialized!");
385:                }
386:                if (!((bitsPerSample.length == 3 && bitsPerSample[0] == 8
387:                        && bitsPerSample[1] == 8 && bitsPerSample[2] == 8) || (bitsPerSample.length == 1 && bitsPerSample[0] == 8))) {
388:                    throw new IIOException(
389:                            "Can only JPEG compress 8- and 24-bit images!");
390:                }
391:
392:                // Set the stream.
393:                ImageOutputStream ios;
394:                long initialStreamPosition; // usingCodecLib && !writeAbbreviatedStream
395:                if (usingCodecLib && !writeAbbreviatedStream) {
396:                    ios = stream;
397:                    initialStreamPosition = stream.getStreamPosition();
398:                } else {
399:                    // If not using codecLib then the stream has to be wrapped as
400:                    // 1) the core Java Image I/O JPEG ImageWriter flushes the
401:                    // stream at the end of each write() and this causes problems
402:                    // for the TIFF writer, or 2) the codecLib JPEG ImageWriter
403:                    // is using a stream on the native side which cannot be reset.
404:                    if (baos == null) {
405:                        baos = new IIOByteArrayOutputStream();
406:                    } else {
407:                        baos.reset();
408:                    }
409:                    ios = new MemoryCacheImageOutputStream(baos);
410:                    initialStreamPosition = 0L;
411:                }
412:                JPEGWriter.setOutput(ios);
413:
414:                // Create a DataBuffer.
415:                DataBufferByte dbb;
416:                if (off == 0 || usingCodecLib) {
417:                    dbb = new DataBufferByte(b, b.length);
418:                } else {
419:                    //
420:                    // Workaround for bug in core Java Image I/O JPEG
421:                    // ImageWriter which cannot handle non-zero offsets.
422:                    //
423:                    int bytesPerSegment = scanlineStride * height;
424:                    byte[] btmp = new byte[bytesPerSegment];
425:                    System.arraycopy(b, off, btmp, 0, bytesPerSegment);
426:                    dbb = new DataBufferByte(btmp, bytesPerSegment);
427:                    off = 0;
428:                }
429:
430:                // Set up the ColorSpace.
431:                int[] offsets;
432:                ColorSpace cs;
433:                if (bitsPerSample.length == 3) {
434:                    offsets = new int[] { off, off + 1, off + 2 };
435:                    cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
436:                } else {
437:                    offsets = new int[] { off };
438:                    cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
439:                }
440:
441:                // Create the ColorModel.
442:                ColorModel cm = new ComponentColorModel(cs, false, false,
443:                        Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
444:
445:                // Create the SampleModel.
446:                SampleModel sm = new PixelInterleavedSampleModel(
447:                        DataBuffer.TYPE_BYTE, width, height,
448:                        bitsPerSample.length, scanlineStride, offsets);
449:
450:                // Create the WritableRaster.
451:                WritableRaster wras = Raster.createWritableRaster(sm, dbb,
452:                        new Point(0, 0));
453:
454:                // Create the BufferedImage.
455:                BufferedImage bi = new BufferedImage(cm, wras, false, null);
456:
457:                // Get the pruned JPEG image metadata (may be null).
458:                IIOMetadata imageMetadata = getImageMetadata(writeAbbreviatedStream);
459:
460:                // Compress the image into the output stream.
461:                int compDataLength;
462:                if (usingCodecLib && !writeAbbreviatedStream) {
463:                    // Write complete JPEG stream
464:                    JPEGWriter.write(null,
465:                            new IIOImage(bi, null, imageMetadata), JPEGParam);
466:
467:                    compDataLength = (int) (stream.getStreamPosition() - initialStreamPosition);
468:                } else {
469:                    if (writeAbbreviatedStream) {
470:                        // Write abbreviated JPEG stream
471:
472:                        // First write the tables-only data.
473:                        JPEGWriter.prepareWriteSequence(JPEGStreamMetadata);
474:                        ios.flush();
475:
476:                        // Rewind to the beginning of the byte array.
477:                        baos.reset();
478:
479:                        // Write the abbreviated image data.
480:                        IIOImage image = new IIOImage(bi, null, imageMetadata);
481:                        JPEGWriter.writeToSequence(image, JPEGParam);
482:                        JPEGWriter.endWriteSequence();
483:                    } else {
484:                        // Write complete JPEG stream
485:                        JPEGWriter.write(null, new IIOImage(bi, null,
486:                                imageMetadata), JPEGParam);
487:                    }
488:
489:                    compDataLength = baos.size();
490:                    baos.writeTo(stream);
491:                    baos.reset();
492:                }
493:
494:                return compDataLength;
495:            }
496:
497:            protected void finalize() throws Throwable {
498:                super.finalize();
499:                if (JPEGWriter != null) {
500:                    JPEGWriter.dispose();
501:                }
502:            }
503:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.