Source Code Cross Referenced for TIFFOldJPEGDecompressor.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: TIFFOldJPEGDecompressor.java,v $
003:         *
004:         * 
005:         * Copyright (c) 2005 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.4 $
042:         * $Date: 2007/09/14 01:14:56 $
043:         * $State: Exp $
044:         */
045:        package com.sun.media.imageioimpl.plugins.tiff;
046:
047:        import java.awt.Point;
048:        import java.awt.image.BufferedImage;
049:        import java.io.IOException;
050:        import java.io.ByteArrayInputStream;
051:        import java.io.ByteArrayOutputStream;
052:        import java.util.Iterator;
053:        import javax.imageio.IIOException;
054:        import javax.imageio.ImageIO;
055:        import javax.imageio.ImageReader;
056:        import javax.imageio.ImageReadParam;
057:        import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
058:        import javax.imageio.plugins.jpeg.JPEGImageReadParam;
059:        import javax.imageio.plugins.jpeg.JPEGQTable;
060:        import javax.imageio.stream.MemoryCacheImageInputStream;
061:        import javax.imageio.stream.ImageInputStream;
062:        import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
063:        import com.sun.media.imageio.plugins.tiff.TIFFDecompressor;
064:        import com.sun.media.imageio.plugins.tiff.TIFFField;
065:
066:        /**
067:         * <code>TIFFDecompressor</code> for "Old JPEG" compression.
068:         */
069:        public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor {
070:
071:            private static final boolean DEBUG = false; // XXX 'false' for release
072:
073:            // Start of Image
074:            // private static final int SOI = 0xD8; // now defined in superclass
075:
076:            // Define Huffman Tables
077:            private static final int DHT = 0xC4;
078:
079:            // Define Quantisation Tables
080:            private static final int DQT = 0xDB;
081:
082:            // Define Restart Interval
083:            private static final int DRI = 0xDD;
084:
085:            // Baseline DCT
086:            private static final int SOF0 = 0xC0;
087:
088:            // Start of Scan
089:            private static final int SOS = 0xDA;
090:
091:            // End of Image
092:            // private static final int EOI = 0xD9; // now defined in superclass
093:
094:            // Whether the decompressor has been initialized.
095:            private boolean isInitialized = false;
096:
097:            //
098:            // Instance variables set by the initialize() method.
099:            //
100:            // Offset to a complete, contiguous JPEG stream.
101:            private Long JPEGStreamOffset = null;
102:            // Offset to the SOF marker.
103:            private int SOFPosition = -1;
104:            // Value of the SOS marker.
105:            private byte[] SOSMarker = null;
106:
107:            // Horizontal chroma subsampling factor.
108:            private int subsamplingX = 2;
109:
110:            // Vertical chroma subsampling factor.
111:            private int subsamplingY = 2;
112:
113:            public TIFFOldJPEGDecompressor() {
114:            }
115:
116:            //
117:            // Intialize instance variables according to an analysis of the
118:            // TIFF field content. See bug 4929147 for test image information.
119:            //
120:            // Case 1: Image contains a single strip or tile and the offset to
121:            //         that strip or tile points to an SOI marker.
122:            //
123:            //         Example:
124:            //         "Visionshape Inc. Compression Software, version 2.5"
125:            //         ColorTiffWithBarcode.tif
126:            //         Color2.tif (pages 2-5 (indexes 1-4)
127:            //         color3.tif (pages 2-5 (indexes 1-4)
128:            //
129:            //         "Kofax standard Multi-Page TIFF Storage Filter v2.01.000"
130:            //         01.tif (pages 1 and 3(indexes 0 and 2))
131:            //
132:            //         Instance variables set: JPEGStreamOffset
133:            //
134:            // Case 2: Image contains a single strip or tile and a
135:            //         JPEGInterchangeFormat field is present but the
136:            //         JPEGInterchangeFormatLength is erroneously missing.
137:            //
138:            //         Example:
139:            //         "Kofax standard Multi-Page TIFF Storage Filter v2.01.000"
140:            //         01.tif (pages 1 and 3(indexes 0 and 2))
141:            //         (but this example also satisfies case 1)
142:            //
143:            //         Instance variables set: JPEGStreamOffset
144:            //
145:            // Case 3: Image contains a single strip or tile, the
146:            //         JPEGInterchangeFormat and JPEGInterchangeFormatLength
147:            //         fields are both present, the value of JPEGInterchangeFormat
148:            //         is less than the offset to the strip or tile, and the sum
149:            //         of the values of JPEGInterchangeFormat and
150:            //         JPEGInterchangeFormatLength is greater than the offset to
151:            //         the strip or tile.
152:            //
153:            //         Instance variables set: JPEGStreamOffset
154:            //
155:            //         Example:
156:            //         "HP IL v1.1"
157:            //         smallliz.tif from libtiff test data.
158:            //
159:            //         Instance variables set: JPEGStreamOffset
160:            //
161:            // Cases 4-5 apply if none of cases 1-3 applies or the image has multiple
162:            // strips or tiles.
163:            //
164:            // Case 4: JPEGInterchangeFormat and JPEGInterchangeFormatLength are
165:            //         present, the value of JPEGInterchangeFormatLength is at least 2,
166:            //         and the sum of the values of these two fields is at most the
167:            //         value of the offset to the first strip or tile.
168:            //
169:            //         Instance variables set: tables, SOFPosition, SOSMarker
170:            //
171:            //         Example:
172:            //         "Oi/GFS, writer v00.06.00P, (c) Wang Labs, Inc. 1990, 1991"
173:            //         03.tif (pages 1 and 3(indexes 0 and 2))
174:            //
175:            //         "Oi/GFS, writer v00.06.02"
176:            //         Color2.tif (page 1 (index 0))
177:            //         color3.tif (page 1 (index 0))
178:            //
179:            // Case 5: If none of the foregoing cases apply. For this case the
180:            //         JPEGQTables, JPEGACTables, and JPEGDCTables must be valid.
181:            //
182:            //         Instance variables set: tables, SOFPosition, SOSMarker
183:            //
184:            //         Example:
185:            //         "NeXT"
186:            //         zackthecat.tif from libtiff test data.
187:            //
188:            private synchronized void initialize() throws IOException {
189:                if (isInitialized) {
190:                    return;
191:                }
192:
193:                // Get the TIFF metadata object.
194:                TIFFImageMetadata tim = (TIFFImageMetadata) metadata;
195:
196:                // Get the JPEGInterchangeFormat field.
197:                TIFFField JPEGInterchangeFormatField = tim
198:                        .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT);
199:
200:                // Get the tile or strip offsets.
201:                TIFFField segmentOffsetField = tim
202:                        .getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS);
203:                if (segmentOffsetField == null) {
204:                    segmentOffsetField = tim
205:                            .getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
206:                    if (segmentOffsetField == null) {
207:                        segmentOffsetField = JPEGInterchangeFormatField;
208:                    }
209:                }
210:                long[] segmentOffsets = segmentOffsetField.getAsLongs();
211:
212:                // Determine whether the image has more than one strip or tile.
213:                boolean isTiled = segmentOffsets.length > 1;
214:
215:                if (!isTiled) {
216:                    //
217:                    // If the image has only a single strip or tile and it looks
218:                    // as if a complete JPEG stream is present then set the value
219:                    // of JPEGStreamOffset to the offset of the JPEG stream;
220:                    // otherwise leave JPEGStreamOffset set to null.
221:                    //
222:
223:                    stream.seek(offset);
224:                    stream.mark();
225:                    if (stream.read() == 0xff && stream.read() == SOI) {
226:                        // Tile or strip offset points to SOI.
227:                        JPEGStreamOffset = new Long(offset);
228:
229:                        // Set initialization flag and return.
230:                        if (DEBUG)
231:                            System.out.println("OLD JPEG CASE 1");
232:                        ((TIFFImageReader) reader)
233:                                .forwardWarningMessage("SOI marker detected at start of strip or tile.");
234:                        isInitialized = true;
235:                        stream.reset();
236:                        return;
237:                    }
238:                    stream.reset();
239:
240:                    if (JPEGInterchangeFormatField != null) {
241:                        // Get the value of JPEGInterchangeFormat.
242:                        long jpegInterchangeOffset = JPEGInterchangeFormatField
243:                                .getAsLong(0);
244:
245:                        // Check that the value of JPEGInterchangeFormat points to SOI.
246:                        stream.mark();
247:                        stream.seek(jpegInterchangeOffset);
248:                        if (stream.read() == 0xff && stream.read() == SOI)
249:                            // JPEGInterchangeFormat offset points to SOI.
250:                            JPEGStreamOffset = new Long(jpegInterchangeOffset);
251:                        else
252:                            ((TIFFImageReader) reader)
253:                                    .forwardWarningMessage("JPEGInterchangeFormat does not point to SOI");
254:                        stream.reset();
255:
256:                        // Get the JPEGInterchangeFormatLength field.
257:                        TIFFField JPEGInterchangeFormatLengthField = tim
258:                                .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
259:
260:                        if (JPEGInterchangeFormatLengthField == null) {
261:                            if (DEBUG)
262:                                System.out.println("OLD JPEG CASE 2");
263:                            ((TIFFImageReader) reader)
264:                                    .forwardWarningMessage("JPEGInterchangeFormatLength field is missing");
265:                        } else {
266:                            // Get the JPEGInterchangeFormatLength field's value.
267:                            long jpegInterchangeLength = JPEGInterchangeFormatLengthField
268:                                    .getAsLong(0);
269:
270:                            if (jpegInterchangeOffset < segmentOffsets[0]
271:                                    && (jpegInterchangeOffset + jpegInterchangeLength) > segmentOffsets[0]) {
272:                                if (DEBUG)
273:                                    System.out.println("OLD JPEG CASE 3");
274:                            } else {
275:                                if (DEBUG)
276:                                    System.out.println("OLD JPEG CASE 3A");
277:                                ((TIFFImageReader) reader)
278:                                        .forwardWarningMessage("JPEGInterchangeFormatLength field value is invalid");
279:                            }
280:                        }
281:
282:                        // Return if JPEGInterchangeFormat pointed to SOI.
283:                        if (JPEGStreamOffset != null) {
284:                            isInitialized = true;
285:                            return;
286:                        }
287:                    }
288:                }
289:
290:                // Get the subsampling factors.
291:                TIFFField YCbCrSubsamplingField = tim
292:                        .getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING);
293:                if (YCbCrSubsamplingField != null) {
294:                    subsamplingX = YCbCrSubsamplingField.getAsChars()[0];
295:                    subsamplingY = YCbCrSubsamplingField.getAsChars()[1];
296:                }
297:
298:                //
299:                // Initialize the 'tables' instance variable either for later
300:                // use in prepending to individual abbreviated strips or tiles.
301:                //
302:                if (JPEGInterchangeFormatField != null) {
303:                    // Get the value of JPEGInterchangeFormat.
304:                    long jpegInterchangeOffset = JPEGInterchangeFormatField
305:                            .getAsLong(0);
306:
307:                    // Get the JPEGInterchangeFormatLength field.
308:                    TIFFField JPEGInterchangeFormatLengthField = tim
309:                            .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
310:
311:                    if (JPEGInterchangeFormatLengthField != null) {
312:                        // Get the JPEGInterchangeFormatLength field's value.
313:                        long jpegInterchangeLength = JPEGInterchangeFormatLengthField
314:                                .getAsLong(0);
315:
316:                        if (jpegInterchangeLength >= 2
317:                                && jpegInterchangeOffset
318:                                        + jpegInterchangeLength <= segmentOffsets[0]) {
319:                            // Determine the length excluding any terminal EOI marker
320:                            // and allocate table memory.
321:                            stream.mark();
322:                            stream.seek(jpegInterchangeOffset
323:                                    + jpegInterchangeLength - 2);
324:                            if (stream.read() == 0xff && stream.read() == EOI) {
325:                                this .tables = new byte[(int) (jpegInterchangeLength - 2)];
326:                            } else {
327:                                this .tables = new byte[(int) jpegInterchangeLength];
328:                            }
329:                            stream.reset();
330:
331:                            // Read the tables.
332:                            stream.mark();
333:                            stream.seek(jpegInterchangeOffset);
334:                            stream.readFully(tables);
335:                            stream.reset();
336:
337:                            if (DEBUG)
338:                                System.out.println("OLD JPEG CASE 4");
339:                            ((TIFFImageReader) reader)
340:                                    .forwardWarningMessage("Incorrect JPEG interchange format: using JPEGInterchangeFormat offset to derive tables.");
341:                        } else {
342:                            ((TIFFImageReader) reader)
343:                                    .forwardWarningMessage("JPEGInterchangeFormat+JPEGInterchangeFormatLength > offset to first strip or tile.");
344:                        }
345:                    }
346:                }
347:
348:                if (this .tables == null) {
349:                    //
350:                    // Create tables-only stream in tables[] consisting of
351:                    // SOI+DQTs+DHTs
352:                    //
353:
354:                    ByteArrayOutputStream baos = new ByteArrayOutputStream();//XXX length
355:
356:                    // Save stream length;
357:                    long streamLength = stream.length();
358:
359:                    // SOI
360:                    baos.write(0xff);
361:                    baos.write(SOI);
362:
363:                    // Quantization Tables
364:                    TIFFField f = tim
365:                            .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES);
366:                    if (f == null) {
367:                        throw new IIOException("JPEGQTables field missing!");
368:                    }
369:                    long[] off = f.getAsLongs();
370:
371:                    for (int i = 0; i < off.length; i++) {
372:                        baos.write(0xff); // Marker ID
373:                        baos.write(DQT);
374:
375:                        char markerLength = (char) 67;
376:                        baos.write((markerLength >>> 8) & 0xff); // Length
377:                        baos.write(markerLength & 0xff);
378:
379:                        baos.write(i); // Table ID and precision
380:
381:                        byte[] qtable = new byte[64];
382:                        if (streamLength != -1 && off[i] > streamLength) {
383:                            throw new IIOException(
384:                                    "JPEGQTables offset for index " + i
385:                                            + " is not in the stream!");
386:                        }
387:                        stream.seek(off[i]);
388:                        stream.readFully(qtable);
389:
390:                        baos.write(qtable); // Table data
391:                    }
392:
393:                    // Huffman Tables (k == 0 ? DC : AC).
394:                    for (int k = 0; k < 2; k++) {
395:                        int tableTagNumber = k == 0 ? BaselineTIFFTagSet.TAG_JPEG_DC_TABLES
396:                                : BaselineTIFFTagSet.TAG_JPEG_AC_TABLES;
397:                        f = tim.getTIFFField(tableTagNumber);
398:                        String fieldName = tableTagNumber == BaselineTIFFTagSet.TAG_JPEG_DC_TABLES ? "JPEGDCTables"
399:                                : "JPEGACTables";
400:
401:                        if (f == null) {
402:                            throw new IIOException(fieldName
403:                                    + " field missing!");
404:                        }
405:                        off = f.getAsLongs();
406:
407:                        for (int i = 0; i < off.length; i++) {
408:                            baos.write(0xff); // Marker ID
409:                            baos.write(DHT);
410:
411:                            byte[] blengths = new byte[16];
412:                            if (streamLength != -1 && off[i] > streamLength) {
413:                                throw new IIOException(fieldName
414:                                        + " offset for index " + i
415:                                        + " is not in the stream!");
416:                            }
417:                            stream.seek(off[i]);
418:                            stream.readFully(blengths);
419:                            int numCodes = 0;
420:                            for (int j = 0; j < 16; j++) {
421:                                numCodes += blengths[j] & 0xff;
422:                            }
423:
424:                            char markerLength = (char) (19 + numCodes);
425:
426:                            baos.write((markerLength >>> 8) & 0xff); // Length
427:                            baos.write(markerLength & 0xff);
428:
429:                            baos.write(i | (k << 4)); // Table ID and type
430:
431:                            baos.write(blengths); // Number of codes
432:
433:                            byte[] bcodes = new byte[numCodes];
434:                            stream.readFully(bcodes);
435:                            baos.write(bcodes); // Codes
436:                        }
437:                    }
438:
439:                    // SOF0
440:                    baos.write((byte) 0xff); // Marker identifier
441:                    baos.write((byte) SOF0);
442:                    short sval = (short) (8 + 3 * samplesPerPixel); // Length
443:                    baos.write((byte) ((sval >>> 8) & 0xff));
444:                    baos.write((byte) (sval & 0xff));
445:                    baos.write((byte) 8); // Data precision
446:                    sval = (short) srcHeight; // Tile/strip height
447:                    baos.write((byte) ((sval >>> 8) & 0xff));
448:                    baos.write((byte) (sval & 0xff));
449:                    sval = (short) srcWidth; // Tile/strip width
450:                    baos.write((byte) ((sval >>> 8) & 0xff));
451:                    baos.write((byte) (sval & 0xff));
452:                    baos.write((byte) samplesPerPixel); // Number of components
453:                    if (samplesPerPixel == 1) {
454:                        baos.write((byte) 1); // Component ID
455:                        baos.write((byte) 0x11); // Subsampling factor
456:                        baos.write((byte) 0); // Quantization table ID
457:                    } else { // 3
458:                        for (int i = 0; i < 3; i++) {
459:                            baos.write((byte) (i + 1)); // Component ID
460:                            baos
461:                                    .write((i != 0) ? (byte) 0x11
462:                                            : (byte) (((subsamplingX & 0x0f) << 4) | (subsamplingY & 0x0f)));
463:
464:                            baos.write((byte) i); // Quantization table ID
465:                        }
466:                    }
467:                    ;
468:
469:                    // DRI (optional).
470:                    f = tim
471:                            .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_RESTART_INTERVAL);
472:                    if (f != null) {
473:                        char restartInterval = f.getAsChars()[0];
474:
475:                        if (restartInterval != 0) {
476:                            baos.write((byte) 0xff); // Marker identifier
477:                            baos.write((byte) DRI);
478:
479:                            sval = 4;
480:                            baos.write((byte) ((sval >>> 8) & 0xff)); // Length
481:                            baos.write((byte) (sval & 0xff));
482:
483:                            // RestartInterval
484:                            baos.write((byte) ((restartInterval >>> 8) & 0xff));
485:                            baos.write((byte) (restartInterval & 0xff));
486:                        }
487:                    }
488:
489:                    tables = baos.toByteArray();
490:
491:                    if (DEBUG)
492:                        System.out.println("OLD JPEG CASE 5");
493:                }
494:
495:                //
496:                // Check for presence of SOF marker and save its position.
497:                //
498:                int idx = 0;
499:                int idxMax = tables.length - 1;
500:                while (idx < idxMax) {
501:                    if ((tables[idx] & 0xff) == 0xff
502:                            && (tables[idx + 1] & 0xff) == SOF0) {
503:                        SOFPosition = idx;
504:                        break;
505:                    }
506:                    idx++;
507:                }
508:
509:                //
510:                // If no SOF marker, add one.
511:                //
512:                if (SOFPosition == -1) {
513:                    byte[] tmpTables = new byte[tables.length + 10 + 3
514:                            * samplesPerPixel];
515:                    System.arraycopy(tables, 0, tmpTables, 0, tables.length);
516:                    int tmpOffset = tables.length;
517:                    SOFPosition = tables.length;
518:                    tables = tmpTables;
519:
520:                    tables[tmpOffset++] = (byte) 0xff; // Marker identifier
521:                    tables[tmpOffset++] = (byte) SOF0;
522:                    short sval = (short) (8 + 3 * samplesPerPixel); // Length
523:                    tables[tmpOffset++] = (byte) ((sval >>> 8) & 0xff);
524:                    tables[tmpOffset++] = (byte) (sval & 0xff);
525:                    tables[tmpOffset++] = (byte) 8; // Data precision
526:                    sval = (short) srcHeight; // Tile/strip height
527:                    tables[tmpOffset++] = (byte) ((sval >>> 8) & 0xff);
528:                    tables[tmpOffset++] = (byte) (sval & 0xff);
529:                    sval = (short) srcWidth; // Tile/strip width
530:                    tables[tmpOffset++] = (byte) ((sval >>> 8) & 0xff);
531:                    tables[tmpOffset++] = (byte) (sval & 0xff);
532:                    tables[tmpOffset++] = (byte) samplesPerPixel; // Number of components
533:                    if (samplesPerPixel == 1) {
534:                        tables[tmpOffset++] = (byte) 1; // Component ID
535:                        tables[tmpOffset++] = (byte) 0x11; // Subsampling factor
536:                        tables[tmpOffset++] = (byte) 0; // Quantization table ID
537:                    } else { // 3
538:                        for (int i = 0; i < 3; i++) {
539:                            tables[tmpOffset++] = (byte) (i + 1); // Component ID
540:                            tables[tmpOffset++] = (i != 0) ? (byte) 0x11
541:                                    : (byte) (((subsamplingX & 0x0f) << 4) | (subsamplingY & 0x0f));
542:
543:                            tables[tmpOffset++] = (byte) i; // Quantization table ID
544:                        }
545:                    }
546:                    ;
547:                }
548:
549:                //
550:                // Initialize SOSMarker.
551:                //
552:                stream.mark();
553:                stream.seek(segmentOffsets[0]);
554:                if (stream.read() == 0xff && stream.read() == SOS) {
555:                    //
556:                    // If the first segment starts with an SOS marker save it.
557:                    //
558:                    int SOSLength = (stream.read() << 8) | stream.read();
559:                    SOSMarker = new byte[SOSLength + 2];
560:                    SOSMarker[0] = (byte) 0xff;
561:                    SOSMarker[1] = (byte) SOS;
562:                    SOSMarker[2] = (byte) ((SOSLength & 0xff00) >> 8);
563:                    SOSMarker[3] = (byte) (SOSLength & 0xff);
564:                    stream.readFully(SOSMarker, 4, SOSLength - 2);
565:                } else {
566:                    //
567:                    // Manufacture an SOS marker.
568:                    //
569:                    SOSMarker = new byte[2 + 6 + 2 * samplesPerPixel];
570:                    int SOSMarkerIndex = 0;
571:                    SOSMarker[SOSMarkerIndex++] = (byte) 0xff; // Marker identifier
572:                    SOSMarker[SOSMarkerIndex++] = (byte) SOS;
573:                    short sval = (short) (6 + 2 * samplesPerPixel); // Length
574:                    SOSMarker[SOSMarkerIndex++] = (byte) ((sval >>> 8) & 0xff);
575:                    SOSMarker[SOSMarkerIndex++] = (byte) (sval & 0xff);
576:                    // Number of components in scan
577:                    SOSMarker[SOSMarkerIndex++] = (byte) samplesPerPixel;
578:                    if (samplesPerPixel == 1) {
579:                        SOSMarker[SOSMarkerIndex++] = (byte) 1; // Component ID
580:                        SOSMarker[SOSMarkerIndex++] = (byte) 0; // Huffman table ID
581:                    } else { // 3
582:                        for (int i = 0; i < 3; i++) {
583:                            SOSMarker[SOSMarkerIndex++] = (byte) (i + 1); // Component ID
584:                            SOSMarker[SOSMarkerIndex++] = (byte) ((i << 4) | i); // Huffman table IDs
585:                        }
586:                    }
587:                    ;
588:                    SOSMarker[SOSMarkerIndex++] = (byte) 0;
589:                    SOSMarker[SOSMarkerIndex++] = (byte) 0x3f;
590:                    SOSMarker[SOSMarkerIndex++] = (byte) 0;
591:                }
592:                stream.reset();
593:
594:                // Set initialization flag.
595:                isInitialized = true;
596:            }
597:
598:            //
599:            // The strategy for reading cases 1-3 is to treat the data as a complete
600:            // JPEG interchange stream located at JPEGStreamOffset.
601:            //
602:            // The strategy for cases 4-5 is to concatenate a tables stream created
603:            // in initialize() with the entropy coded data in each strip or tile.
604:            //
605:            public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel,
606:                    int scanlineStride) throws IOException {
607:
608:                initialize();
609:
610:                TIFFImageMetadata tim = (TIFFImageMetadata) metadata;
611:
612:                if (JPEGStreamOffset != null) {
613:                    stream.seek(JPEGStreamOffset.longValue());
614:                    JPEGReader.setInput(stream, false, true);
615:                } else {
616:                    // Determine buffer length and allocate.
617:                    int tableLength = tables.length;
618:                    int bufLength = tableLength + SOSMarker.length + byteCount
619:                            + 2; // 2 for EOI.
620:                    byte[] buf = new byte[bufLength];
621:                    if (tables != null) {
622:                        System.arraycopy(tables, 0, buf, 0, tableLength);
623:                    }
624:                    int bufOffset = tableLength;
625:
626:                    // Update the SOF dimensions.
627:                    short sval = (short) srcHeight; // Tile/strip height
628:                    buf[SOFPosition + 5] = (byte) ((sval >>> 8) & 0xff);
629:                    buf[SOFPosition + 6] = (byte) (sval & 0xff);
630:                    sval = (short) srcWidth; // Tile/strip width
631:                    buf[SOFPosition + 7] = (byte) ((sval >>> 8) & 0xff);
632:                    buf[SOFPosition + 8] = (byte) (sval & 0xff);
633:
634:                    // Seek to data.
635:                    stream.seek(offset);
636:
637:                    // Add SOS marker if data segment does not start with one.
638:                    byte[] twoBytes = new byte[2];
639:                    stream.readFully(twoBytes);
640:                    if (!((twoBytes[0] & 0xff) == 0xff && (twoBytes[1] & 0xff) == SOS)) {
641:                        // Segment does not start with SOS marker;
642:                        // use the pre-calculated SOS marker.
643:                        System.arraycopy(SOSMarker, 0, buf, bufOffset,
644:                                SOSMarker.length);
645:                        bufOffset += SOSMarker.length;
646:                    }
647:
648:                    // Copy the segment data into the buffer.
649:                    buf[bufOffset++] = twoBytes[0];
650:                    buf[bufOffset++] = twoBytes[1];
651:                    stream.readFully(buf, bufOffset, byteCount - 2);
652:                    bufOffset += byteCount - 2;
653:
654:                    // EOI.
655:                    buf[bufOffset++] = (byte) 0xff; // Marker identifier
656:                    buf[bufOffset++] = (byte) EOI;
657:
658:                    ByteArrayInputStream bais = new ByteArrayInputStream(buf,
659:                            0, bufOffset);
660:                    ImageInputStream is = new MemoryCacheImageInputStream(bais);
661:
662:                    JPEGReader.setInput(is, true, true);
663:                }
664:
665:                // Read real image
666:                JPEGParam.setDestination(rawImage);
667:                JPEGReader.read(0, JPEGParam);
668:            }
669:
670:            protected void finalize() throws Throwable {
671:                super.finalize();
672:                JPEGReader.dispose();
673:            }
674:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.