Source Code Cross Referenced for TIFFDirectory.java in  » IDE-Eclipse » swt » org » eclipse » swt » internal » image » 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 » IDE Eclipse » swt » org.eclipse.swt.internal.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2005 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.swt.internal.image;
011:
012:        import org.eclipse.swt.*;
013:        import org.eclipse.swt.graphics.*;
014:        import java.io.*;
015:
016:        final class TIFFDirectory {
017:
018:            TIFFRandomFileAccess file;
019:            boolean isLittleEndian;
020:            ImageLoader loader;
021:            int depth;
022:
023:            /* Directory fields */
024:            int imageWidth;
025:            int imageLength;
026:            int[] bitsPerSample;
027:            int compression;
028:            int photometricInterpretation;
029:            int[] stripOffsets;
030:            int samplesPerPixel;
031:            int rowsPerStrip;
032:            int[] stripByteCounts;
033:            int t4Options;
034:            int colorMapOffset;
035:
036:            /* Encoder fields */
037:            ImageData image;
038:            LEDataOutputStream out;
039:
040:            static final int NO_VALUE = -1;
041:
042:            static final short TAG_ImageWidth = 256;
043:            static final short TAG_ImageLength = 257;
044:            static final short TAG_BitsPerSample = 258;
045:            static final short TAG_Compression = 259;
046:            static final short TAG_PhotometricInterpretation = 262;
047:            static final short TAG_StripOffsets = 273;
048:            static final short TAG_SamplesPerPixel = 277;
049:            static final short TAG_RowsPerStrip = 278;
050:            static final short TAG_StripByteCounts = 279;
051:            static final short TAG_XResolution = 282;
052:            static final short TAG_YResolution = 283;
053:            static final short TAG_T4Options = 292;
054:            static final short TAG_ResolutionUnit = 296;
055:            static final short TAG_ColorMap = 320;
056:
057:            static final int TYPE_BYTE = 1;
058:            static final int TYPE_ASCII = 2;
059:            static final int TYPE_SHORT = 3;
060:            static final int TYPE_LONG = 4;
061:            static final int TYPE_RATIONAL = 5;
062:
063:            /* Different compression schemes */
064:            static final int COMPRESSION_NONE = 1;
065:            static final int COMPRESSION_CCITT_3_1 = 2;
066:            static final int COMPRESSION_PACKBITS = 32773;
067:
068:            static final int IFD_ENTRY_SIZE = 12;
069:
070:            public TIFFDirectory(TIFFRandomFileAccess file,
071:                    boolean isLittleEndian, ImageLoader loader) {
072:                this .file = file;
073:                this .isLittleEndian = isLittleEndian;
074:                this .loader = loader;
075:            }
076:
077:            public TIFFDirectory(ImageData image) {
078:                this .image = image;
079:            }
080:
081:            /* PackBits decoder */
082:            int decodePackBits(byte[] src, byte[] dest, int offsetDest) {
083:                int destIndex = offsetDest;
084:                int srcIndex = 0;
085:                while (srcIndex < src.length) {
086:                    byte n = src[srcIndex];
087:                    if (0 <= n && n <= 127) {
088:                        /* Copy next n+1 bytes literally */
089:                        System.arraycopy(src, ++srcIndex, dest, destIndex,
090:                                n + 1);
091:                        srcIndex += n + 1;
092:                        destIndex += n + 1;
093:                    } else if (-127 <= n && n <= -1) {
094:                        /* Copy next byte -n+1 times */
095:                        byte value = src[++srcIndex];
096:                        for (int j = 0; j < -n + 1; j++) {
097:                            dest[destIndex++] = value;
098:                        }
099:                        srcIndex++;
100:                    } else {
101:                        /* Noop when n == -128 */
102:                        srcIndex++;
103:                    }
104:                }
105:                /* Number of bytes copied */
106:                return destIndex - offsetDest;
107:            }
108:
109:            int getEntryValue(int type, byte[] buffer, int index) {
110:                return toInt(buffer, index + 8, type);
111:            }
112:
113:            void getEntryValue(int type, byte[] buffer, int index, int[] values)
114:                    throws IOException {
115:                int start = index + 8;
116:                int size;
117:                int offset = toInt(buffer, start, TYPE_LONG);
118:                switch (type) {
119:                case TYPE_SHORT:
120:                    size = 2;
121:                    break;
122:                case TYPE_LONG:
123:                    size = 4;
124:                    break;
125:                case TYPE_RATIONAL:
126:                    size = 8;
127:                    break;
128:                case TYPE_ASCII:
129:                case TYPE_BYTE:
130:                    size = 1;
131:                    break;
132:                default:
133:                    SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
134:                    return;
135:                }
136:                if (values.length * size > 4) {
137:                    buffer = new byte[values.length * size];
138:                    file.seek(offset);
139:                    file.read(buffer);
140:                    start = 0;
141:                }
142:                for (int i = 0; i < values.length; i++) {
143:                    values[i] = toInt(buffer, start + i * size, type);
144:                }
145:            }
146:
147:            void decodePixels(ImageData image) throws IOException {
148:                /* Each row is byte aligned */
149:                byte[] imageData = new byte[(imageWidth * depth + 7) / 8
150:                        * imageLength];
151:                image.data = imageData;
152:                int destIndex = 0;
153:                int length = stripOffsets.length;
154:                for (int i = 0; i < length; i++) {
155:                    /* Read a strip */
156:                    byte[] data = new byte[stripByteCounts[i]];
157:                    file.seek(stripOffsets[i]);
158:                    file.read(data);
159:                    if (compression == COMPRESSION_NONE) {
160:                        System.arraycopy(data, 0, imageData, destIndex,
161:                                data.length);
162:                        destIndex += data.length;
163:                    } else if (compression == COMPRESSION_PACKBITS) {
164:                        destIndex += decodePackBits(data, imageData, destIndex);
165:                    } else if (compression == COMPRESSION_CCITT_3_1
166:                            || compression == 3) {
167:                        TIFFModifiedHuffmanCodec codec = new TIFFModifiedHuffmanCodec();
168:                        int nRows = rowsPerStrip;
169:                        if (i == length - 1) {
170:                            int n = imageLength % rowsPerStrip;
171:                            if (n != 0)
172:                                nRows = n;
173:                        }
174:                        destIndex += codec.decode(data, imageData, destIndex,
175:                                imageWidth, nRows);
176:                    }
177:                    if (loader.hasListeners()) {
178:                        loader.notifyListeners(new ImageLoaderEvent(loader,
179:                                image, i, i == length - 1));
180:                    }
181:                }
182:            }
183:
184:            PaletteData getColorMap() throws IOException {
185:                int numColors = 1 << bitsPerSample[0];
186:                /* R, G, B entries are 16 bit wide (2 bytes) */
187:                int numBytes = 3 * 2 * numColors;
188:                byte[] buffer = new byte[numBytes];
189:                file.seek(colorMapOffset);
190:                file.read(buffer);
191:                RGB[] colors = new RGB[numColors];
192:                /**
193:                 * SWT does not support 16-bit depth color formats.
194:                 * Convert the 16-bit data to 8-bit data.
195:                 * The correct way to do this is to multiply each
196:                 * 16 bit value by the value:
197:                 * (2^8 - 1) / (2^16 - 1).
198:                 * The fast way to do this is just to drop the low
199:                 * byte of the 16-bit value.
200:                 */
201:                int offset = isLittleEndian ? 1 : 0;
202:                int startG = 2 * numColors;
203:                int startB = startG + 2 * numColors;
204:                for (int i = 0; i < numColors; i++) {
205:                    int r = buffer[offset] & 0xFF;
206:                    int g = buffer[startG + offset] & 0xFF;
207:                    int b = buffer[startB + offset] & 0xFF;
208:                    colors[i] = new RGB(r, g, b);
209:                    offset += 2;
210:                }
211:                return new PaletteData(colors);
212:            }
213:
214:            PaletteData getGrayPalette() {
215:                int numColors = 1 << bitsPerSample[0];
216:                RGB[] rgbs = new RGB[numColors];
217:                for (int i = 0; i < numColors; i++) {
218:                    int value = i * 0xFF / (numColors - 1);
219:                    if (photometricInterpretation == 0)
220:                        value = 0xFF - value;
221:                    rgbs[i] = new RGB(value, value, value);
222:                }
223:                return new PaletteData(rgbs);
224:            }
225:
226:            PaletteData getRGBPalette(int bitsR, int bitsG, int bitsB) {
227:                int blueMask = 0;
228:                for (int i = 0; i < bitsB; i++) {
229:                    blueMask |= 1 << i;
230:                }
231:                int greenMask = 0;
232:                for (int i = bitsB; i < bitsB + bitsG; i++) {
233:                    greenMask |= 1 << i;
234:                }
235:                int redMask = 0;
236:                for (int i = bitsB + bitsG; i < bitsB + bitsG + bitsR; i++) {
237:                    redMask |= 1 << i;
238:                }
239:                return new PaletteData(redMask, greenMask, blueMask);
240:            }
241:
242:            int formatStrips(int rowByteSize, int nbrRows, byte[] data,
243:                    int maxStripByteSize, int offsetPostIFD, int extraBytes,
244:                    int[][] strips) {
245:                /* 
246:                 * Calculate the nbr of required strips given the following requirements: 
247:                 * - each strip should, if possible, not be greater than maxStripByteSize
248:                 * - each strip should contain 1 or more entire rows
249:                 * 
250:                 * Format the strip fields arrays so that the image data is stored in one
251:                 * contiguous block. This block is stored after the IFD and after any tag
252:                 * info described in the IFD.
253:                 */
254:                int n, nbrRowsPerStrip;
255:                if (rowByteSize > maxStripByteSize) {
256:                    /* Each strip contains 1 row */
257:                    n = data.length / rowByteSize;
258:                    nbrRowsPerStrip = 1;
259:                } else {
260:                    int nbr = (data.length + maxStripByteSize - 1)
261:                            / maxStripByteSize;
262:                    nbrRowsPerStrip = nbrRows / nbr;
263:                    n = (nbrRows + nbrRowsPerStrip - 1) / nbrRowsPerStrip;
264:                }
265:                int stripByteSize = rowByteSize * nbrRowsPerStrip;
266:
267:                int[] offsets = new int[n];
268:                int[] counts = new int[n];
269:                /* 
270:                 * Nbr of bytes between the end of the IFD directory and the start of
271:                 * the image data. Keep space for at least the offsets and counts
272:                 * data, each field being TYPE_LONG (4 bytes). If other tags require
273:                 * space between the IFD and the image block, use the extraBytes
274:                 * parameter.
275:                 * If there is only one strip, the offsets and counts data is stored
276:                 * directly in the IFD and we need not reserve space for it.
277:                 */
278:                int postIFDData = n == 1 ? 0 : n * 2 * 4;
279:                int startOffset = offsetPostIFD + extraBytes + postIFDData; /* offset of image data */
280:
281:                int offset = startOffset;
282:                for (int i = 0; i < n; i++) {
283:                    /* 
284:                     * Store all strips sequentially to allow us
285:                     * to copy all pixels in one contiguous area.
286:                     */
287:                    offsets[i] = offset;
288:                    counts[i] = stripByteSize;
289:                    offset += stripByteSize;
290:                }
291:                /* The last strip may contain fewer rows */
292:                int mod = data.length % stripByteSize;
293:                if (mod != 0)
294:                    counts[counts.length - 1] = mod;
295:
296:                strips[0] = offsets;
297:                strips[1] = counts;
298:                return nbrRowsPerStrip;
299:            }
300:
301:            int[] formatColorMap(RGB[] rgbs) {
302:                /* 
303:                 * In a TIFF ColorMap, all red come first, followed by
304:                 * green and blue. All values must be converted from
305:                 * 8 bit to 16 bit. 
306:                 */
307:                int[] colorMap = new int[rgbs.length * 3];
308:                int offsetGreen = rgbs.length;
309:                int offsetBlue = rgbs.length * 2;
310:                for (int i = 0; i < rgbs.length; i++) {
311:                    colorMap[i] = rgbs[i].red << 8 | rgbs[i].red;
312:                    colorMap[i + offsetGreen] = rgbs[i].green << 8
313:                            | rgbs[i].green;
314:                    colorMap[i + offsetBlue] = rgbs[i].blue << 8 | rgbs[i].blue;
315:                }
316:                return colorMap;
317:            }
318:
319:            void parseEntries(byte[] buffer) throws IOException {
320:                for (int offset = 0; offset < buffer.length; offset += IFD_ENTRY_SIZE) {
321:                    int tag = toInt(buffer, offset, TYPE_SHORT);
322:                    int type = toInt(buffer, offset + 2, TYPE_SHORT);
323:                    int count = toInt(buffer, offset + 4, TYPE_LONG);
324:                    switch (tag) {
325:                    case TAG_ImageWidth: {
326:                        imageWidth = getEntryValue(type, buffer, offset);
327:                        break;
328:                    }
329:                    case TAG_ImageLength: {
330:                        imageLength = getEntryValue(type, buffer, offset);
331:                        break;
332:                    }
333:                    case TAG_BitsPerSample: {
334:                        if (type != TYPE_SHORT)
335:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
336:                        bitsPerSample = new int[count];
337:                        getEntryValue(type, buffer, offset, bitsPerSample);
338:                        break;
339:                    }
340:                    case TAG_Compression: {
341:                        compression = getEntryValue(type, buffer, offset);
342:                        break;
343:                    }
344:                    case TAG_PhotometricInterpretation: {
345:                        photometricInterpretation = getEntryValue(type, buffer,
346:                                offset);
347:                        break;
348:                    }
349:                    case TAG_StripOffsets: {
350:                        if (type != TYPE_LONG && type != TYPE_SHORT)
351:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
352:                        stripOffsets = new int[count];
353:                        getEntryValue(type, buffer, offset, stripOffsets);
354:                        break;
355:                    }
356:                    case TAG_SamplesPerPixel: {
357:                        if (type != TYPE_SHORT)
358:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
359:                        samplesPerPixel = getEntryValue(type, buffer, offset);
360:                        /* Only the basic 1 and 3 values are supported */
361:                        if (samplesPerPixel != 1 && samplesPerPixel != 3)
362:                            SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
363:                        break;
364:                    }
365:                    case TAG_RowsPerStrip: {
366:                        rowsPerStrip = getEntryValue(type, buffer, offset);
367:                        break;
368:                    }
369:                    case TAG_StripByteCounts: {
370:                        stripByteCounts = new int[count];
371:                        getEntryValue(type, buffer, offset, stripByteCounts);
372:                        break;
373:                    }
374:                    case TAG_XResolution: {
375:                        /* Ignored */
376:                        break;
377:                    }
378:                    case TAG_YResolution: {
379:                        /* Ignored */
380:                        break;
381:                    }
382:                    case TAG_T4Options: {
383:                        if (type != TYPE_LONG)
384:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
385:                        t4Options = getEntryValue(type, buffer, offset);
386:                        if ((t4Options & 0x1) == 1) {
387:                            /* 2-dimensional coding is not supported */
388:                            SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
389:                        }
390:                        break;
391:                    }
392:                    case TAG_ResolutionUnit: {
393:                        /* Ignored */
394:                        break;
395:                    }
396:                    case TAG_ColorMap: {
397:                        if (type != TYPE_SHORT)
398:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
399:                        /* Get the offset of the colorMap (use TYPE_LONG) */
400:                        colorMapOffset = getEntryValue(TYPE_LONG, buffer,
401:                                offset);
402:                        break;
403:                    }
404:                    }
405:                }
406:            }
407:
408:            public ImageData read() throws IOException {
409:                /* Set TIFF default values */
410:                bitsPerSample = new int[] { 1 };
411:                colorMapOffset = NO_VALUE;
412:                compression = 1;
413:                imageLength = NO_VALUE;
414:                imageWidth = NO_VALUE;
415:                photometricInterpretation = NO_VALUE;
416:                rowsPerStrip = Integer.MAX_VALUE;
417:                samplesPerPixel = 1;
418:                stripByteCounts = null;
419:                stripOffsets = null;
420:
421:                byte[] buffer = new byte[2];
422:                file.read(buffer);
423:                int numberEntries = toInt(buffer, 0, TYPE_SHORT);
424:                buffer = new byte[IFD_ENTRY_SIZE * numberEntries];
425:                file.read(buffer);
426:                parseEntries(buffer);
427:
428:                PaletteData palette = null;
429:                depth = 0;
430:                switch (photometricInterpretation) {
431:                case 0:
432:                case 1: {
433:                    /* Bilevel or Grayscale image */
434:                    palette = getGrayPalette();
435:                    depth = bitsPerSample[0];
436:                    break;
437:                }
438:                case 2: {
439:                    /* RGB image */
440:                    if (colorMapOffset != NO_VALUE)
441:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
442:                    /* SamplesPerPixel 3 is the only value supported */
443:                    palette = getRGBPalette(bitsPerSample[0], bitsPerSample[1],
444:                            bitsPerSample[2]);
445:                    depth = bitsPerSample[0] + bitsPerSample[1]
446:                            + bitsPerSample[2];
447:                    break;
448:                }
449:                case 3: {
450:                    /* Palette Color image */
451:                    if (colorMapOffset == NO_VALUE)
452:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
453:                    palette = getColorMap();
454:                    depth = bitsPerSample[0];
455:                    break;
456:                }
457:                default: {
458:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
459:                }
460:                }
461:
462:                ImageData image = ImageData.internal_new(imageWidth,
463:                        imageLength, depth, palette, 1, null, 0, null, null,
464:                        -1, -1, SWT.IMAGE_TIFF, 0, 0, 0, 0);
465:                decodePixels(image);
466:                return image;
467:            }
468:
469:            int toInt(byte[] buffer, int i, int type) {
470:                if (type == TYPE_LONG) {
471:                    return isLittleEndian ? (buffer[i] & 0xFF)
472:                            | ((buffer[i + 1] & 0xFF) << 8)
473:                            | ((buffer[i + 2] & 0xFF) << 16)
474:                            | ((buffer[i + 3] & 0xFF) << 24)
475:                            : (buffer[i + 3] & 0xFF)
476:                                    | ((buffer[i + 2] & 0xFF) << 8)
477:                                    | ((buffer[i + 1] & 0xFF) << 16)
478:                                    | ((buffer[i] & 0xFF) << 24);
479:                }
480:                if (type == TYPE_SHORT) {
481:                    return isLittleEndian ? (buffer[i] & 0xFF)
482:                            | ((buffer[i + 1] & 0xFF) << 8)
483:                            : (buffer[i + 1] & 0xFF)
484:                                    | ((buffer[i] & 0xFF) << 8);
485:                }
486:                /* Invalid type */
487:                SWT.error(SWT.ERROR_INVALID_IMAGE);
488:                return -1;
489:            }
490:
491:            void write(int photometricInterpretation) throws IOException {
492:                boolean isRGB = photometricInterpretation == 2;
493:                boolean isColorMap = photometricInterpretation == 3;
494:                boolean isBiLevel = photometricInterpretation == 0
495:                        || photometricInterpretation == 1;
496:
497:                int imageWidth = image.width;
498:                int imageLength = image.height;
499:                int rowByteSize = image.bytesPerLine;
500:
501:                int numberEntries = isBiLevel ? 9 : 11;
502:                int lengthDirectory = 2 + 12 * numberEntries + 4;
503:                /* Offset following the header and the directory */
504:                int nextOffset = 8 + lengthDirectory;
505:
506:                /* Extra space used by XResolution and YResolution values */
507:                int extraBytes = 16;
508:
509:                int[] colorMap = null;
510:                if (isColorMap) {
511:                    PaletteData palette = image.palette;
512:                    RGB[] rgbs = palette.getRGBs();
513:                    colorMap = formatColorMap(rgbs);
514:                    /* The number of entries of the Color Map must match the bitsPerSample field */
515:                    if (colorMap.length != 3 * 1 << image.depth)
516:                        SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
517:                    /* Extra space used by ColorMap values */
518:                    extraBytes += colorMap.length * 2;
519:                }
520:                if (isRGB) {
521:                    /* Extra space used by BitsPerSample values */
522:                    extraBytes += 6;
523:                }
524:                /* TIFF recommends storing the data in strips of no more than 8 Ko */
525:                byte[] data = image.data;
526:                int[][] strips = new int[2][];
527:                int nbrRowsPerStrip = formatStrips(rowByteSize, imageLength,
528:                        data, 8192, nextOffset, extraBytes, strips);
529:                int[] stripOffsets = strips[0];
530:                int[] stripByteCounts = strips[1];
531:
532:                int bitsPerSampleOffset = NO_VALUE;
533:                if (isRGB) {
534:                    bitsPerSampleOffset = nextOffset;
535:                    nextOffset += 6;
536:                }
537:                int stripOffsetsOffset = NO_VALUE, stripByteCountsOffset = NO_VALUE;
538:                int xResolutionOffset, yResolutionOffset, colorMapOffset = NO_VALUE;
539:                int cnt = stripOffsets.length;
540:                if (cnt > 1) {
541:                    stripOffsetsOffset = nextOffset;
542:                    nextOffset += 4 * cnt;
543:                    stripByteCountsOffset = nextOffset;
544:                    nextOffset += 4 * cnt;
545:                }
546:                xResolutionOffset = nextOffset;
547:                nextOffset += 8;
548:                yResolutionOffset = nextOffset;
549:                nextOffset += 8;
550:                if (isColorMap) {
551:                    colorMapOffset = nextOffset;
552:                    nextOffset += colorMap.length * 2;
553:                }
554:                /* TIFF header */
555:                writeHeader();
556:
557:                /* Image File Directory */
558:                out.writeShort(numberEntries);
559:                writeEntry(TAG_ImageWidth, TYPE_LONG, 1, imageWidth);
560:                writeEntry(TAG_ImageLength, TYPE_LONG, 1, imageLength);
561:                if (isColorMap)
562:                    writeEntry(TAG_BitsPerSample, TYPE_SHORT, 1, image.depth);
563:                if (isRGB)
564:                    writeEntry(TAG_BitsPerSample, TYPE_SHORT, 3,
565:                            bitsPerSampleOffset);
566:                writeEntry(TAG_Compression, TYPE_SHORT, 1, COMPRESSION_NONE);
567:                writeEntry(TAG_PhotometricInterpretation, TYPE_SHORT, 1,
568:                        photometricInterpretation);
569:                writeEntry(TAG_StripOffsets, TYPE_LONG, cnt,
570:                        cnt > 1 ? stripOffsetsOffset : stripOffsets[0]);
571:                if (isRGB)
572:                    writeEntry(TAG_SamplesPerPixel, TYPE_SHORT, 1, 3);
573:                writeEntry(TAG_RowsPerStrip, TYPE_LONG, 1, nbrRowsPerStrip);
574:                writeEntry(TAG_StripByteCounts, TYPE_LONG, cnt,
575:                        cnt > 1 ? stripByteCountsOffset : stripByteCounts[0]);
576:                writeEntry(TAG_XResolution, TYPE_RATIONAL, 1, xResolutionOffset);
577:                writeEntry(TAG_YResolution, TYPE_RATIONAL, 1, yResolutionOffset);
578:                if (isColorMap)
579:                    writeEntry(TAG_ColorMap, TYPE_SHORT, colorMap.length,
580:                            colorMapOffset);
581:                /* Offset of next IFD (0 for last IFD) */
582:                out.writeInt(0);
583:
584:                /* Values longer than 4 bytes Section */
585:
586:                /* BitsPerSample 8,8,8 */
587:                if (isRGB)
588:                    for (int i = 0; i < 3; i++)
589:                        out.writeShort(8);
590:                if (cnt > 1) {
591:                    for (int i = 0; i < cnt; i++)
592:                        out.writeInt(stripOffsets[i]);
593:                    for (int i = 0; i < cnt; i++)
594:                        out.writeInt(stripByteCounts[i]);
595:                }
596:                /* XResolution and YResolution set to 300 dpi */
597:                for (int i = 0; i < 2; i++) {
598:                    out.writeInt(300);
599:                    out.writeInt(1);
600:                }
601:                /* ColorMap */
602:                if (isColorMap)
603:                    for (int i = 0; i < colorMap.length; i++)
604:                        out.writeShort(colorMap[i]);
605:
606:                /* Image Data */
607:                out.write(data);
608:            }
609:
610:            void writeEntry(short tag, int type, int count, int value)
611:                    throws IOException {
612:                out.writeShort(tag);
613:                out.writeShort(type);
614:                out.writeInt(count);
615:                out.writeInt(value);
616:            }
617:
618:            void writeHeader() throws IOException {
619:                /* little endian */
620:                out.write(0x49);
621:                out.write(0x49);
622:
623:                /* TIFF identifier */
624:                out.writeShort(42);
625:                /* 
626:                 * Offset of the first IFD is chosen to be 8.
627:                 * It is word aligned and immediately after this header.
628:                 */
629:                out.writeInt(8);
630:            }
631:
632:            void writeToStream(LEDataOutputStream byteStream)
633:                    throws IOException {
634:                out = byteStream;
635:                int photometricInterpretation = -1;
636:
637:                /* Scanline pad must be 1 */
638:                if (image.scanlinePad != 1)
639:                    SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
640:                switch (image.depth) {
641:                case 1: {
642:                    /* Palette must be black and white or white and black */
643:                    PaletteData palette = image.palette;
644:                    RGB[] rgbs = palette.colors;
645:                    if (palette.isDirect || rgbs == null || rgbs.length != 2)
646:                        SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
647:                    RGB rgb0 = rgbs[0];
648:                    RGB rgb1 = rgbs[1];
649:                    if (!(rgb0.red == rgb0.green && rgb0.green == rgb0.blue
650:                            && rgb1.red == rgb1.green
651:                            && rgb1.green == rgb1.blue && ((rgb0.red == 0x0 && rgb1.red == 0xFF) || (rgb0.red == 0xFF && rgb1.red == 0x0)))) {
652:                        SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
653:                    }
654:                    /* 0 means a color index of 0 is imaged as white */
655:                    photometricInterpretation = image.palette.colors[0].red == 0xFF ? 0
656:                            : 1;
657:                    break;
658:                }
659:                case 4:
660:                case 8: {
661:                    photometricInterpretation = 3;
662:                    break;
663:                }
664:                case 24: {
665:                    photometricInterpretation = 2;
666:                    break;
667:                }
668:                default: {
669:                    SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
670:                }
671:                }
672:                write(photometricInterpretation);
673:            }
674:
675:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.