Source Code Cross Referenced for ImageInfo.java in  » Swing-Library » wings3 » org » wings » util » 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 » Swing Library » wings3 » org.wings.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ImageInfo.java
0003:         *
0004:         * Version 1.5
0005:         *
0006:         * A Java class to determine image width, height and color depth for
0007:         * a number of image file formats.
0008:         *
0009:         * Written by Marco Schmidt 
0010:         * <http://www.geocities.com/marcoschmidt.geo/contact.html>.
0011:         *
0012:         * Contributed to the Public Domain.
0013:         *
0014:         * Last modification 2004-02-29
0015:         */
0016:
0017:        /*
0018:         * Copyright 2000,2005 wingS development team.
0019:         *
0020:         * This file is part of wingS (http://wingsframework.org).
0021:         *
0022:         * wingS is free software; you can redistribute it and/or modify
0023:         * it under the terms of the GNU Lesser General Public License
0024:         * as published by the Free Software Foundation; either version 2.1
0025:         * of the License, or (at your option) any later version.
0026:         *
0027:         * Please see COPYING for the complete licence.
0028:         */
0029:        package org.wings.util;
0030:
0031:        import java.io.DataInput;
0032:        import java.io.FileInputStream;
0033:        import java.io.IOException;
0034:        import java.io.InputStream;
0035:        import java.net.URL;
0036:        import java.util.ArrayList;
0037:        import java.util.List;
0038:
0039:        /**
0040:         * Get file format, image resolution, number of bits per pixel and optionally
0041:         * number of images, comments and physical resolution from
0042:         * JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files
0043:         * (or input streams).
0044:         * <p/>
0045:         * Use the class like this:
0046:         * <pre>
0047:         * ImageInfo ii = new ImageInfo();
0048:         * ii.setInput(in); // in can be InputStream or RandomAccessFile
0049:         * ii.setDetermineImageNumber(true); // default is false
0050:         * ii.setCollectComments(true); // default is false
0051:         * if (!ii.check()) {
0052:         *   System.err.println("Not a supported image file format.");
0053:         *   return;
0054:         * }
0055:         * System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
0056:         *   ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels, " +
0057:         *   ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
0058:         *   " image(s), " + ii.getNumberOfComments() + " comment(s).");
0059:         *  // there are other properties, check out the API documentation
0060:         * </pre>
0061:         * You can also use this class as a command line program.
0062:         * Call it with a number of image file names and URLs as parameters:
0063:         * <pre>
0064:         *   java ImageInfo *.jpg *.png *.gif http://somesite.tld/image.jpg
0065:         * </pre>
0066:         * or call it without parameters and pipe data to it:
0067:         * <pre>
0068:         *   java ImageInfo &lt; image.jpg
0069:         * </pre>
0070:         * <p/>
0071:         * Known limitations:
0072:         * <ul>
0073:         * <li>When the determination of the number of images is turned off, GIF bits
0074:         * per pixel are only read from the global header.
0075:         * For some GIFs, local palettes change this to a typically larger
0076:         * value. To be certain to get the correct color depth, call
0077:         * setDetermineImageNumber(true) before calling check().
0078:         * The complete scan over the GIF file will take additional time.</li>
0079:         * <li>Transparency information is not included in the bits per pixel count.
0080:         * Actually, it was my decision not to include those bits, so it's a feature! ;-)</li>
0081:         * </ul>
0082:         * <p/>
0083:         * Requirements:
0084:         * <ul>
0085:         * <li>Java 1.1 or higher</li>
0086:         * </ul>
0087:         * <p/>
0088:         * The latest version can be found at <a href="http://www.geocities.com/marcoschmidt.geo/image-info.html">http://www.geocities.com/marcoschmidt.geo/image-info.html</a>.
0089:         * <p/>
0090:         * Written by <a href="http://www.geocities.com/marcoschmidt.geo/contact.html">Marco Schmidt</a>.
0091:         * <p/>
0092:         * This class is contributed to the Public Domain.
0093:         * Use it at your own risk.
0094:         * <p/>
0095:         * Last modification 2004-02-29.
0096:         * <p/>
0097:         * History:
0098:         * <ul>
0099:         * <li><strong>2001-08-24</strong> Initial version.</li>
0100:         * <li><strong>2001-10-13</strong> Added support for the file formats BMP and PCX.</li>
0101:         * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int) that returned
0102:         * <li><strong>2002-01-22</strong> Added support for file formats Amiga IFF and Sun Raster (RAS).</li>
0103:         * <li><strong>2002-01-24</strong> Added support for file formats Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe Photoshop (PSD).
0104:         * Added new method getMimeType() to return the MIME type associated with a particular file format.</li>
0105:         * <li><strong>2002-03-15</strong> Added support to recognize number of images in file. Only works with GIF.
0106:         * Use {@link #setDetermineImageNumber} with <code>true</code> as argument to identify animated GIFs
0107:         * ({@link #getNumberOfImages()} will return a value larger than <code>1</code>).</li>
0108:         * <li><strong>2002-04-10</strong> Fixed a bug in the feature 'determine number of images in animated GIF' introduced with version 1.1.
0109:         * Thanks to Marcelo P. Lima for sending in the bug report.
0110:         * Released as 1.1.1.</li>
0111:         * <li><strong>2002-04-18</strong> Added {@link #setCollectComments(boolean)}.
0112:         * That new method lets the user specify whether textual comments are to be
0113:         * stored in an internal list when encountered in an input image file / stream.
0114:         * Added two methods to return the physical width and height of the image in dpi:
0115:         * {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
0116:         * If the physical resolution could not be retrieved, these methods return <code>-1</code>.
0117:         * </li>
0118:         * <li><strong>2002-04-23</strong> Added support for the new properties physical resolution and
0119:         * comments for some formats. Released as 1.2.</li>
0120:         * <li><strong>2002-06-17</strong> Added support for SWF, sent in by Michael Aird.
0121:         * Changed checkJpeg() so that other APP markers than APP0 will not lead to a failure anymore.
0122:         * Released as 1.3.</li>
0123:         * <li><strong>2003-07-28</strong> Bug fix - skip method now takes return values into consideration.
0124:         * Less bytes than necessary may have been skipped, leading to flaws in the retrieved information in some cases.
0125:         * Thanks to Bernard Bernstein for pointing that out.
0126:         * Released as 1.4.</li>
0127:         * <li><strong>2004-02-29</strong> Added support for recognizing progressive JPEG and
0128:         * interlaced PNG and GIF. A new method {@link #isProgressive()} returns whether ImageInfo
0129:         * has found that the storage type is progressive (or interlaced).
0130:         * Thanks to Joe Germuska for suggesting the feature.
0131:         * Bug fix: BMP physical resolution is now correctly determined.
0132:         * Released as 1.5.</li>
0133:         * </ul>
0134:         */
0135:        public class ImageInfo {
0136:            /**
0137:             * Return value of {@link #getFormat()} for JPEG streams.
0138:             * ImageInfo can extract physical resolution and comments
0139:             * from JPEGs (only from APP0 headers).
0140:             * Only one image can be stored in a file.
0141:             * It is determined whether the JPEG stream is progressive
0142:             * (see {@link #isProgressive()}).
0143:             */
0144:            public static final int FORMAT_JPEG = 0;
0145:
0146:            /**
0147:             * Return value of {@link #getFormat()} for GIF streams.
0148:             * ImageInfo can extract comments from GIFs and count the number
0149:             * of images (GIFs with more than one image are animations).
0150:             * If you know of a place where GIFs store the physical resolution
0151:             * of an image, please
0152:             * <a href="http://www.geocities.com/marcoschmidt.geo/contact.html">send me a mail</a>!
0153:             * It is determined whether the GIF stream is interlaced (see {@link #isProgressive()}).
0154:             */
0155:            public static final int FORMAT_GIF = 1;
0156:
0157:            /**
0158:             * Return value of {@link #getFormat()} for PNG streams.
0159:             * PNG only supports one image per file.
0160:             * Both physical resolution and comments can be stored with PNG,
0161:             * but ImageInfo is currently not able to extract those.
0162:             * It is determined whether the PNG stream is interlaced (see {@link #isProgressive()}).
0163:             */
0164:            public static final int FORMAT_PNG = 2;
0165:
0166:            /**
0167:             * Return value of {@link #getFormat()} for BMP streams.
0168:             * BMP only supports one image per file.
0169:             * BMP does not allow for comments.
0170:             * The physical resolution can be stored.
0171:             */
0172:            public static final int FORMAT_BMP = 3;
0173:
0174:            /**
0175:             * Return value of {@link #getFormat()} for PCX streams.
0176:             * PCX does not allow for comments or more than one image per file.
0177:             * However, the physical resolution can be stored.
0178:             */
0179:            public static final int FORMAT_PCX = 4;
0180:
0181:            /**
0182:             * Return value of {@link #getFormat()} for IFF streams.
0183:             */
0184:            public static final int FORMAT_IFF = 5;
0185:
0186:            /**
0187:             * Return value of {@link #getFormat()} for RAS streams.
0188:             * Sun Raster allows for one image per file only and is not able to
0189:             * store physical resolution or comments.
0190:             */
0191:            public static final int FORMAT_RAS = 6;
0192:
0193:            /**
0194:             * Return value of {@link #getFormat()} for PBM streams.
0195:             */
0196:            public static final int FORMAT_PBM = 7;
0197:
0198:            /**
0199:             * Return value of {@link #getFormat()} for PGM streams.
0200:             */
0201:            public static final int FORMAT_PGM = 8;
0202:
0203:            /**
0204:             * Return value of {@link #getFormat()} for PPM streams.
0205:             */
0206:            public static final int FORMAT_PPM = 9;
0207:
0208:            /**
0209:             * Return value of {@link #getFormat()} for PSD streams.
0210:             */
0211:            public static final int FORMAT_PSD = 10;
0212:
0213:            /**
0214:             * Return value of {@link #getFormat()} for SWF (Shockwave) streams.
0215:             */
0216:            public static final int FORMAT_SWF = 11;
0217:
0218:            public static final int COLOR_TYPE_UNKNOWN = -1;
0219:            public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
0220:            public static final int COLOR_TYPE_PALETTED = 1;
0221:            public static final int COLOR_TYPE_GRAYSCALE = 2;
0222:            public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;
0223:
0224:            /**
0225:             * The names of all supported file formats.
0226:             * The FORMAT_xyz int constants can be used as index values for
0227:             * this array.
0228:             */
0229:            public static final String[] FORMAT_NAMES = { "jpeg", "gif", "png",
0230:                    "bmp", "pcx", "iff", "ras", "pbm", "pgm", "ppm", "psd",
0231:                    "swf" };
0232:
0233:            /**
0234:             * The names of the MIME types for all supported file formats.
0235:             * The FORMAT_xyz int constants can be used as index values for
0236:             * this array.
0237:             */
0238:            public static final String[] MIME_TYPE_STRINGS = { "image/jpeg",
0239:                    "image/gif", "image/png", "image/bmp", "image/pcx",
0240:                    "image/iff", "image/ras", "image/x-portable-bitmap",
0241:                    "image/x-portable-graymap", "image/x-portable-pixmap",
0242:                    "image/psd", "application/x-shockwave-flash" };
0243:
0244:            private int width;
0245:            private int height;
0246:            private int bitsPerPixel;
0247:            private int colorType = COLOR_TYPE_UNKNOWN;
0248:            private boolean progressive;
0249:            private int format;
0250:            private InputStream in;
0251:            private DataInput din;
0252:            private boolean collectComments = true;
0253:            private List comments;
0254:            private boolean determineNumberOfImages;
0255:            private int numberOfImages;
0256:            private int physicalHeightDpi;
0257:            private int physicalWidthDpi;
0258:            private int bitBuf;
0259:            private int bitPos;
0260:
0261:            private void addComment(String s) {
0262:                if (comments == null) {
0263:                    comments = new ArrayList();
0264:                }
0265:                comments.add(s);
0266:            }
0267:
0268:            /**
0269:             * Call this method after you have provided an input stream or file
0270:             * using {@link #setInput(java.io.InputStream)} or {@link #setInput(java.io.DataInput)}.
0271:             * If true is returned, the file format was known and information
0272:             * on the file's content can be retrieved using the various getXyz methods.
0273:             *
0274:             * @return if information could be retrieved from input
0275:             */
0276:            public boolean check() {
0277:                format = -1;
0278:                width = -1;
0279:                height = -1;
0280:                bitsPerPixel = -1;
0281:                numberOfImages = 1;
0282:                physicalHeightDpi = -1;
0283:                physicalWidthDpi = -1;
0284:                comments = null;
0285:                try {
0286:                    int b1 = read() & 0xff;
0287:                    int b2 = read() & 0xff;
0288:                    if (b1 == 0x47 && b2 == 0x49) {
0289:                        return checkGif();
0290:                    } else if (b1 == 0x89 && b2 == 0x50) {
0291:                        return checkPng();
0292:                    } else if (b1 == 0xff && b2 == 0xd8) {
0293:                        return checkJpeg();
0294:                    } else if (b1 == 0x42 && b2 == 0x4d) {
0295:                        return checkBmp();
0296:                    } else if (b1 == 0x0a && b2 < 0x06) {
0297:                        return checkPcx();
0298:                    } else if (b1 == 0x46 && b2 == 0x4f) {
0299:                        return checkIff();
0300:                    } else if (b1 == 0x59 && b2 == 0xa6) {
0301:                        return checkRas();
0302:                    } else if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
0303:                        return checkPnm(b2 - '0');
0304:                    } else if (b1 == 0x38 && b2 == 0x42) {
0305:                        return checkPsd();
0306:                    } else if (b1 == 0x46 && b2 == 0x57) {
0307:                        return checkSwf();
0308:                    } else {
0309:                        return false;
0310:                    }
0311:                } catch (IOException ioe) {
0312:                    return false;
0313:                }
0314:            }
0315:
0316:            private boolean checkBmp() throws IOException {
0317:                byte[] a = new byte[44];
0318:                if (read(a) != a.length) {
0319:                    return false;
0320:                }
0321:                width = getIntLittleEndian(a, 16);
0322:                height = getIntLittleEndian(a, 20);
0323:                if (width < 1 || height < 1) {
0324:                    return false;
0325:                }
0326:                bitsPerPixel = getShortLittleEndian(a, 26);
0327:                if (bitsPerPixel != 1 && bitsPerPixel != 4 && bitsPerPixel != 8
0328:                        && bitsPerPixel != 16 && bitsPerPixel != 24
0329:                        && bitsPerPixel != 32) {
0330:                    return false;
0331:                }
0332:                int x = (int) (getIntLittleEndian(a, 36) * 0.0254);
0333:                if (x > 0) {
0334:                    setPhysicalWidthDpi(x);
0335:                }
0336:                int y = (int) (getIntLittleEndian(a, 40) * 0.0254);
0337:                if (y > 0) {
0338:                    setPhysicalHeightDpi(y);
0339:                }
0340:                format = FORMAT_BMP;
0341:                return true;
0342:            }
0343:
0344:            private boolean checkGif() throws IOException {
0345:                final byte[] GIF_MAGIC_87A = { 0x46, 0x38, 0x37, 0x61 };
0346:                final byte[] GIF_MAGIC_89A = { 0x46, 0x38, 0x39, 0x61 };
0347:                byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
0348:                if (read(a) != 11) {
0349:                    return false;
0350:                }
0351:                if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4))
0352:                        && (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
0353:                    return false;
0354:                }
0355:                format = FORMAT_GIF;
0356:                width = getShortLittleEndian(a, 4);
0357:                height = getShortLittleEndian(a, 6);
0358:                int flags = a[8] & 0xff;
0359:                bitsPerPixel = ((flags >> 4) & 0x07) + 1;
0360:                progressive = (flags & 0x02) != 0;
0361:                if (!determineNumberOfImages) {
0362:                    return true;
0363:                }
0364:                // skip global color palette
0365:                if ((flags & 0x80) != 0) {
0366:                    int tableSize = (1 << ((flags & 7) + 1)) * 3;
0367:                    skip(tableSize);
0368:                }
0369:                numberOfImages = 0;
0370:                int blockType;
0371:                do {
0372:                    blockType = read();
0373:                    switch (blockType) {
0374:                    case (0x2c): // image separator
0375:                    {
0376:                        if (read(a, 0, 9) != 9) {
0377:                            return false;
0378:                        }
0379:                        flags = a[8] & 0xff;
0380:                        int localBitsPerPixel = (flags & 0x07) + 1;
0381:                        if (localBitsPerPixel > bitsPerPixel) {
0382:                            bitsPerPixel = localBitsPerPixel;
0383:                        }
0384:                        if ((flags & 0x80) != 0) {
0385:                            skip((1 << localBitsPerPixel) * 3);
0386:                        }
0387:                        skip(1); // initial code length
0388:                        int n;
0389:                        do {
0390:                            n = read();
0391:                            if (n > 0) {
0392:                                skip(n);
0393:                            } else if (n == -1) {
0394:                                return false;
0395:                            }
0396:                        } while (n > 0);
0397:                        numberOfImages++;
0398:                        break;
0399:                    }
0400:                    case (0x21): // extension
0401:                    {
0402:                        int extensionType = read();
0403:                        if (collectComments && extensionType == 0xfe) {
0404:                            SStringBuilder sb = new SStringBuilder();
0405:                            int n;
0406:                            do {
0407:                                n = read();
0408:                                if (n == -1) {
0409:                                    return false;
0410:                                }
0411:                                if (n > 0) {
0412:                                    for (int i = 0; i < n; i++) {
0413:                                        int ch = read();
0414:                                        if (ch == -1) {
0415:                                            return false;
0416:                                        }
0417:                                        sb.append((char) ch);
0418:                                    }
0419:                                }
0420:                            } while (n > 0);
0421:                        } else {
0422:                            int n;
0423:                            do {
0424:                                n = read();
0425:                                if (n > 0) {
0426:                                    skip(n);
0427:                                } else if (n == -1) {
0428:                                    return false;
0429:                                }
0430:                            } while (n > 0);
0431:                        }
0432:                        break;
0433:                    }
0434:                    case (0x3b): // end of file
0435:                    {
0436:                        break;
0437:                    }
0438:                    default: {
0439:                        return false;
0440:                    }
0441:                    }
0442:                } while (blockType != 0x3b);
0443:                return true;
0444:            }
0445:
0446:            private boolean checkIff() throws IOException {
0447:                byte[] a = new byte[10];
0448:                // read remaining 2 bytes of file id, 4 bytes file size 
0449:                // and 4 bytes IFF subformat
0450:                if (read(a, 0, 10) != 10) {
0451:                    return false;
0452:                }
0453:                final byte[] IFF_RM = { 0x52, 0x4d };
0454:                if (!equals(a, 0, IFF_RM, 0, 2)) {
0455:                    return false;
0456:                }
0457:                int type = getIntBigEndian(a, 6);
0458:                if (type != 0x494c424d && // type must be ILBM...
0459:                        type != 0x50424d20) { // ...or PBM
0460:                    return false;
0461:                }
0462:                // loop chunks to find BMHD chunk
0463:                do {
0464:                    if (read(a, 0, 8) != 8) {
0465:                        return false;
0466:                    }
0467:                    int chunkId = getIntBigEndian(a, 0);
0468:                    int size = getIntBigEndian(a, 4);
0469:                    if ((size & 1) == 1) {
0470:                        size++;
0471:                    }
0472:                    if (chunkId == 0x424d4844) { // BMHD chunk
0473:                        if (read(a, 0, 9) != 9) {
0474:                            return false;
0475:                        }
0476:                        format = FORMAT_IFF;
0477:                        width = getShortBigEndian(a, 0);
0478:                        height = getShortBigEndian(a, 2);
0479:                        bitsPerPixel = a[8] & 0xff;
0480:                        return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
0481:                    } else {
0482:                        skip(size);
0483:                    }
0484:                } while (true);
0485:            }
0486:
0487:            private boolean checkJpeg() throws IOException {
0488:                byte[] data = new byte[12];
0489:                while (true) {
0490:                    if (read(data, 0, 4) != 4) {
0491:                        return false;
0492:                    }
0493:                    int marker = getShortBigEndian(data, 0);
0494:                    int size = getShortBigEndian(data, 2);
0495:                    if ((marker & 0xff00) != 0xff00) {
0496:                        return false; // not a valid marker
0497:                    }
0498:                    if (marker == 0xffe0) { // APPx 
0499:                        if (size < 14) {
0500:                            return false; // APPx header must be >= 14 bytes
0501:                        }
0502:                        if (read(data, 0, 12) != 12) {
0503:                            return false;
0504:                        }
0505:                        final byte[] APP0_ID = { 0x4a, 0x46, 0x49, 0x46, 0x00 };
0506:                        if (equals(APP0_ID, 0, data, 0, 5)) {
0507:                            //System.out.println("data 7=" + data[7]);
0508:                            if (data[7] == 1) {
0509:                                setPhysicalWidthDpi(getShortBigEndian(data, 8));
0510:                                setPhysicalHeightDpi(getShortBigEndian(data, 10));
0511:                            } else if (data[7] == 2) {
0512:                                int x = getShortBigEndian(data, 8);
0513:                                int y = getShortBigEndian(data, 10);
0514:                                setPhysicalWidthDpi((int) (x * 2.54f));
0515:                                setPhysicalHeightDpi((int) (y * 2.54f));
0516:                            }
0517:                        }
0518:                        skip(size - 14);
0519:                    } else if (collectComments && size > 2 && marker == 0xfffe) { // comment
0520:                        size -= 2;
0521:                        byte[] chars = new byte[size];
0522:                        if (read(chars, 0, size) != size) {
0523:                            return false;
0524:                        }
0525:                        String comment = new String(chars, "iso-8859-1");
0526:                        comment = comment.trim();
0527:                        addComment(comment);
0528:                    } else if (marker >= 0xffc0 && marker <= 0xffcf
0529:                            && marker != 0xffc4 && marker != 0xffc8) {
0530:                        if (read(data, 0, 6) != 6) {
0531:                            return false;
0532:                        }
0533:                        format = FORMAT_JPEG;
0534:                        bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
0535:                        progressive = marker == 0xffc2 || marker == 0xffc6
0536:                                || marker == 0xffca || marker == 0xffce;
0537:                        width = getShortBigEndian(data, 3);
0538:                        height = getShortBigEndian(data, 1);
0539:                        return true;
0540:                    } else {
0541:                        skip(size - 2);
0542:                    }
0543:                }
0544:            }
0545:
0546:            private boolean checkPcx() throws IOException {
0547:                byte[] a = new byte[64];
0548:                if (read(a) != a.length) {
0549:                    return false;
0550:                }
0551:                if (a[0] != 1) { // encoding, 1=RLE is only valid value
0552:                    return false;
0553:                }
0554:                // width / height
0555:                int x1 = getShortLittleEndian(a, 2);
0556:                int y1 = getShortLittleEndian(a, 4);
0557:                int x2 = getShortLittleEndian(a, 6);
0558:                int y2 = getShortLittleEndian(a, 8);
0559:                if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
0560:                    return false;
0561:                }
0562:                width = x2 - x1 + 1;
0563:                height = y2 - y1 + 1;
0564:                // color depth
0565:                int bits = a[1];
0566:                int planes = a[63];
0567:                if (planes == 1
0568:                        && (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
0569:                    // paletted
0570:                    bitsPerPixel = bits;
0571:                } else if (planes == 3 && bits == 8) {
0572:                    // RGB truecolor
0573:                    bitsPerPixel = 24;
0574:                } else {
0575:                    return false;
0576:                }
0577:                setPhysicalWidthDpi(getShortLittleEndian(a, 10));
0578:                setPhysicalHeightDpi(getShortLittleEndian(a, 10));
0579:                format = FORMAT_PCX;
0580:                return true;
0581:            }
0582:
0583:            private boolean checkPng() throws IOException {
0584:                final byte[] PNG_MAGIC = { 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
0585:                byte[] a = new byte[27];
0586:                if (read(a) != 27) {
0587:                    return false;
0588:                }
0589:                if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
0590:                    return false;
0591:                }
0592:                format = FORMAT_PNG;
0593:                width = getIntBigEndian(a, 14);
0594:                height = getIntBigEndian(a, 18);
0595:                bitsPerPixel = a[22] & 0xff;
0596:                colorType = a[23] & 0xff;
0597:                if (colorType == 2 || colorType == 6) {
0598:                    bitsPerPixel *= 3;
0599:                }
0600:                progressive = (a[26] & 0xff) != 0;
0601:                return true;
0602:            }
0603:
0604:            private boolean checkPnm(int id) throws IOException {
0605:                if (id < 1 || id > 6) {
0606:                    return false;
0607:                }
0608:                final int[] PNM_FORMATS = { FORMAT_PBM, FORMAT_PGM, FORMAT_PPM };
0609:                format = PNM_FORMATS[(id - 1) % 3];
0610:                boolean hasPixelResolution = false;
0611:                String s;
0612:                while (true) {
0613:                    s = readLine();
0614:                    if (s != null) {
0615:                        s = s.trim();
0616:                    }
0617:                    if (s == null || s.length() < 1) {
0618:                        continue;
0619:                    }
0620:                    if (s.charAt(0) == '#') { // comment
0621:                        if (collectComments && s.length() > 1) {
0622:                            addComment(s.substring(1));
0623:                        }
0624:                        continue;
0625:                    }
0626:                    if (!hasPixelResolution) { // split "343 966" into width=343, height=966
0627:                        int spaceIndex = s.indexOf(' ');
0628:                        if (spaceIndex == -1) {
0629:                            return false;
0630:                        }
0631:                        String widthString = s.substring(0, spaceIndex);
0632:                        spaceIndex = s.lastIndexOf(' ');
0633:                        if (spaceIndex == -1) {
0634:                            return false;
0635:                        }
0636:                        String heightString = s.substring(spaceIndex + 1);
0637:                        try {
0638:                            width = Integer.parseInt(widthString);
0639:                            height = Integer.parseInt(heightString);
0640:                        } catch (NumberFormatException nfe) {
0641:                            return false;
0642:                        }
0643:                        if (width < 1 || height < 1) {
0644:                            return false;
0645:                        }
0646:                        if (format == FORMAT_PBM) {
0647:                            bitsPerPixel = 1;
0648:                            return true;
0649:                        }
0650:                        hasPixelResolution = true;
0651:                    } else {
0652:                        int maxSample;
0653:                        try {
0654:                            maxSample = Integer.parseInt(s);
0655:                        } catch (NumberFormatException nfe) {
0656:                            return false;
0657:                        }
0658:                        if (maxSample < 0) {
0659:                            return false;
0660:                        }
0661:                        for (int i = 0; i < 25; i++) {
0662:                            if (maxSample < (1 << (i + 1))) {
0663:                                bitsPerPixel = i + 1;
0664:                                if (format == FORMAT_PPM) {
0665:                                    bitsPerPixel *= 3;
0666:                                }
0667:                                return true;
0668:                            }
0669:                        }
0670:                        return false;
0671:                    }
0672:                }
0673:            }
0674:
0675:            private boolean checkPsd() throws IOException {
0676:                byte[] a = new byte[24];
0677:                if (read(a) != a.length) {
0678:                    return false;
0679:                }
0680:                final byte[] PSD_MAGIC = { 0x50, 0x53 };
0681:                if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
0682:                    return false;
0683:                }
0684:                format = FORMAT_PSD;
0685:                width = getIntBigEndian(a, 16);
0686:                height = getIntBigEndian(a, 12);
0687:                int channels = getShortBigEndian(a, 10);
0688:                int depth = getShortBigEndian(a, 20);
0689:                bitsPerPixel = channels * depth;
0690:                return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
0691:            }
0692:
0693:            private boolean checkRas() throws IOException {
0694:                byte[] a = new byte[14];
0695:                if (read(a) != a.length) {
0696:                    return false;
0697:                }
0698:                final byte[] RAS_MAGIC = { 0x6a, (byte) 0x95 };
0699:                if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
0700:                    return false;
0701:                }
0702:                format = FORMAT_RAS;
0703:                width = getIntBigEndian(a, 2);
0704:                height = getIntBigEndian(a, 6);
0705:                bitsPerPixel = getIntBigEndian(a, 10);
0706:                return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
0707:            }
0708:
0709:            // Written by Michael Aird.
0710:            private boolean checkSwf() throws IOException {
0711:                //get rid of the last byte of the signature, the byte of the version and 4 bytes of the size
0712:                byte[] a = new byte[6];
0713:                if (read(a) != a.length) {
0714:                    return false;
0715:                }
0716:                format = FORMAT_SWF;
0717:                int bitSize = (int) readUBits(5);
0718:                int minX = readSBits(bitSize);
0719:                int maxX = readSBits(bitSize);
0720:                int minY = readSBits(bitSize);
0721:                int maxY = readSBits(bitSize);
0722:                width = maxX / 20; //cause we're in twips
0723:                height = maxY / 20; //cause we're in twips
0724:                setPhysicalWidthDpi(72);
0725:                setPhysicalHeightDpi(72);
0726:                return (width > 0 && height > 0);
0727:            }
0728:
0729:            /**
0730:             * Run over String list, return false iff at least one of the arguments
0731:             * equals <code>-c</code>.
0732:             */
0733:            private static boolean determineVerbosity(String[] args) {
0734:                if (args != null && args.length > 0) {
0735:                    for (int i = 0; i < args.length; i++) {
0736:                        if ("-c".equals(args[i])) {
0737:                            return false;
0738:                        }
0739:                    }
0740:                }
0741:                return true;
0742:            }
0743:
0744:            private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2,
0745:                    int num) {
0746:                while (num-- > 0) {
0747:                    if (a1[offs1++] != a2[offs2++]) {
0748:                        return false;
0749:                    }
0750:                }
0751:                return true;
0752:            }
0753:
0754:            /**
0755:             * If {@link #check()} was successful, returns the image's number of bits per pixel.
0756:             * Does not include transparency information like the alpha channel.
0757:             *
0758:             * @return number of bits per image pixel
0759:             */
0760:            public int getBitsPerPixel() {
0761:                return bitsPerPixel;
0762:            }
0763:
0764:            /**
0765:             * Returns the index'th comment retrieved from the image.
0766:             *
0767:             * @throws java.lang.IllegalArgumentException
0768:             *          if index is smaller than 0 or larger than or equal
0769:             *          to the number of comments retrieved
0770:             * @see #getNumberOfComments
0771:             */
0772:            public String getComment(int index) {
0773:                if (comments == null || index < 0 || index >= comments.size()) {
0774:                    throw new IllegalArgumentException(
0775:                            "Not a valid comment index: " + index);
0776:                }
0777:                return (String) comments.get(index);
0778:            }
0779:
0780:            /**
0781:             * If {@link #check()} was successful, returns the image format as one
0782:             * of the FORMAT_xyz constants from this class.
0783:             * Use {@link #getFormatName()} to get a textual description of the file format.
0784:             *
0785:             * @return file format as a FORMAT_xyz constant
0786:             */
0787:            public int getFormat() {
0788:                return format;
0789:            }
0790:
0791:            /**
0792:             * If {@link #check()} was successful, returns the image format's name.
0793:             * Use {@link #getFormat()} to get a unique number.
0794:             *
0795:             * @return file format name
0796:             */
0797:            public String getFormatName() {
0798:                if (format >= 0 && format < FORMAT_NAMES.length) {
0799:                    return FORMAT_NAMES[format];
0800:                } else {
0801:                    return "?";
0802:                }
0803:            }
0804:
0805:            /**
0806:             * If {@link #check()} was successful, returns one the image's vertical
0807:             * resolution in pixels.
0808:             *
0809:             * @return image height in pixels
0810:             */
0811:            public int getHeight() {
0812:                return height;
0813:            }
0814:
0815:            private int getIntBigEndian(byte[] a, int offs) {
0816:                return (a[offs] & 0xff) << 24 | (a[offs + 1] & 0xff) << 16
0817:                        | (a[offs + 2] & 0xff) << 8 | a[offs + 3] & 0xff;
0818:            }
0819:
0820:            private int getIntLittleEndian(byte[] a, int offs) {
0821:                return (a[offs + 3] & 0xff) << 24 | (a[offs + 2] & 0xff) << 16
0822:                        | (a[offs + 1] & 0xff) << 8 | a[offs] & 0xff;
0823:            }
0824:
0825:            /**
0826:             * If {@link #check()} was successful, returns a String with the
0827:             * MIME type of the format.
0828:             *
0829:             * @return MIME type, e.g. <code>image/jpeg</code>
0830:             */
0831:            public String getMimeType() {
0832:                if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
0833:                    if (format == FORMAT_JPEG && progressive) {
0834:                        return "image/pjpeg";
0835:                    }
0836:                    return MIME_TYPE_STRINGS[format];
0837:                } else {
0838:                    return null;
0839:                }
0840:            }
0841:
0842:            /**
0843:             * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with
0844:             * <code>true</code> as argument, returns the number of comments retrieved
0845:             * from the input image stream / file.
0846:             * Any number &gt;= 0 and smaller than this number of comments is then a
0847:             * valid argument for the {@link #getComment(int)} method.
0848:             *
0849:             * @return number of comments retrieved from input image
0850:             */
0851:            public int getNumberOfComments() {
0852:                if (comments == null) {
0853:                    return 0;
0854:                } else {
0855:                    return comments.size();
0856:                }
0857:            }
0858:
0859:            /**
0860:             * Returns the number of images in the examined file.
0861:             * Assumes that <code>setDetermineImageNumber(true);</code> was called before
0862:             * a successful call to {@link #check()}.
0863:             * This value can currently be only different from <code>1</code> for GIF images.
0864:             *
0865:             * @return number of images in file
0866:             */
0867:            public int getNumberOfImages() {
0868:                return numberOfImages;
0869:            }
0870:
0871:            /**
0872:             * Returns the physical height of this image in dots per inch (dpi).
0873:             * Assumes that {@link #check()} was successful.
0874:             * Returns <code>-1</code> on failure.
0875:             *
0876:             * @return physical height (in dpi)
0877:             * @see #getPhysicalWidthDpi()
0878:             * @see #getPhysicalHeightInch()
0879:             */
0880:            public int getPhysicalHeightDpi() {
0881:                return physicalHeightDpi;
0882:            }
0883:
0884:            /**
0885:             * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
0886:             * or -1 if no value could be found.
0887:             *
0888:             * @return physical height (in dpi)
0889:             * @see #getPhysicalHeightDpi()
0890:             * @see #getPhysicalWidthDpi()
0891:             * @see #getPhysicalWidthInch()
0892:             */
0893:            public float getPhysicalHeightInch() {
0894:                int h = getHeight();
0895:                int ph = getPhysicalHeightDpi();
0896:                if (h > 0 && ph > 0) {
0897:                    return ((float) h) / ((float) ph);
0898:                } else {
0899:                    return -1.0f;
0900:                }
0901:            }
0902:
0903:            /**
0904:             * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
0905:             * or -1 if no value could be found.
0906:             *
0907:             * @return physical width (in dpi)
0908:             * @see #getPhysicalHeightDpi()
0909:             * @see #getPhysicalWidthInch()
0910:             * @see #getPhysicalHeightInch()
0911:             */
0912:            public int getPhysicalWidthDpi() {
0913:                return physicalWidthDpi;
0914:            }
0915:
0916:            /**
0917:             * Returns the physical width of an image in inches, or
0918:             * <code>-1.0f</code> if width information is not available.
0919:             * Assumes that {@link #check} has been called successfully.
0920:             *
0921:             * @return physical width in inches or <code>-1.0f</code> on failure
0922:             * @see #getPhysicalWidthDpi
0923:             * @see #getPhysicalHeightInch
0924:             */
0925:            public float getPhysicalWidthInch() {
0926:                int w = getWidth();
0927:                int pw = getPhysicalWidthDpi();
0928:                if (w > 0 && pw > 0) {
0929:                    return ((float) w) / ((float) pw);
0930:                } else {
0931:                    return -1.0f;
0932:                }
0933:            }
0934:
0935:            private int getShortBigEndian(byte[] a, int offs) {
0936:                return (a[offs] & 0xff) << 8 | (a[offs + 1] & 0xff);
0937:            }
0938:
0939:            private int getShortLittleEndian(byte[] a, int offs) {
0940:                return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
0941:            }
0942:
0943:            /**
0944:             * If {@link #check()} was successful, returns one the image's horizontal
0945:             * resolution in pixels.
0946:             *
0947:             * @return image width in pixels
0948:             */
0949:            public int getWidth() {
0950:                return width;
0951:            }
0952:
0953:            /**
0954:             * Returns whether the image is stored in a progressive (also called: interlaced) way.
0955:             *
0956:             * @return true for progressive/interlaced, false otherwise
0957:             */
0958:            public boolean isProgressive() {
0959:                return progressive;
0960:            }
0961:
0962:            /**
0963:             * To use this class as a command line application, give it either
0964:             * some file names as parameters (information on them will be
0965:             * printed to standard output, one line per file) or call
0966:             * it with no parameters. It will then check data given to it
0967:             * via standard input.
0968:             *
0969:             * @param args the program arguments which must be file names
0970:             */
0971:            public static void main(String[] args) {
0972:                ImageInfo imageInfo = new ImageInfo();
0973:                imageInfo.setDetermineImageNumber(true);
0974:                boolean verbose = determineVerbosity(args);
0975:                if (args.length == 0) {
0976:                    run(null, System.in, imageInfo, verbose);
0977:                } else {
0978:                    int index = 0;
0979:                    while (index < args.length) {
0980:                        InputStream in = null;
0981:                        try {
0982:                            String name = args[index++];
0983:                            System.out.print(name + ";");
0984:                            if (name.startsWith("http://")) {
0985:                                in = new URL(name).openConnection()
0986:                                        .getInputStream();
0987:                            } else {
0988:                                in = new FileInputStream(name);
0989:                            }
0990:                            run(name, in, imageInfo, verbose);
0991:                            in.close();
0992:                        } catch (Exception e) {
0993:                            System.out.println(e);
0994:                            try {
0995:                                in.close();
0996:                            } catch (Exception ee) {
0997:                            }
0998:                        }
0999:                    }
1000:                }
1001:            }
1002:
1003:            private static void print(String sourceName, ImageInfo ii,
1004:                    boolean verbose) {
1005:                if (verbose) {
1006:                    printVerbose(sourceName, ii);
1007:                } else {
1008:                    printCompact(sourceName, ii);
1009:                }
1010:            }
1011:
1012:            private static void printCompact(String sourceName,
1013:                    ImageInfo imageInfo) {
1014:                System.out.println(imageInfo.getFormatName() + ";"
1015:                        + imageInfo.getMimeType() + ";" + imageInfo.getWidth()
1016:                        + ";" + imageInfo.getHeight() + ";"
1017:                        + imageInfo.getBitsPerPixel() + ";"
1018:                        + imageInfo.getNumberOfImages() + ";"
1019:                        + imageInfo.getPhysicalWidthDpi() + ";"
1020:                        + imageInfo.getPhysicalHeightDpi() + ";"
1021:                        + imageInfo.getPhysicalWidthInch() + ";"
1022:                        + imageInfo.getPhysicalHeightInch() + ";"
1023:                        + imageInfo.isProgressive());
1024:            }
1025:
1026:            private static void printLine(int indentLevels, String text,
1027:                    float value, float minValidValue) {
1028:                if (value < minValidValue) {
1029:                    return;
1030:                }
1031:                printLine(indentLevels, text, Float.toString(value));
1032:            }
1033:
1034:            private static void printLine(int indentLevels, String text,
1035:                    int value, int minValidValue) {
1036:                if (value >= minValidValue) {
1037:                    printLine(indentLevels, text, Integer.toString(value));
1038:                }
1039:            }
1040:
1041:            private static void printLine(int indentLevels, String text,
1042:                    String value) {
1043:                if (value == null || value.length() == 0) {
1044:                    return;
1045:                }
1046:                while (indentLevels-- > 0) {
1047:                    System.out.print("\t");
1048:                }
1049:                if (text != null && text.length() > 0) {
1050:                    System.out.print(text);
1051:                    System.out.print(" ");
1052:                }
1053:                System.out.println(value);
1054:            }
1055:
1056:            private static void printVerbose(String sourceName, ImageInfo ii) {
1057:                printLine(0, null, sourceName);
1058:                printLine(1, "File format: ", ii.getFormatName());
1059:                printLine(1, "MIME type: ", ii.getMimeType());
1060:                printLine(1, "Width (pixels): ", ii.getWidth(), 1);
1061:                printLine(1, "Height (pixels): ", ii.getHeight(), 1);
1062:                printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
1063:                printLine(1, "Progressive: ", Boolean.toString(ii
1064:                        .isProgressive()));
1065:                printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
1066:                printLine(1, "Physical width (dpi): ",
1067:                        ii.getPhysicalWidthDpi(), 1);
1068:                printLine(1, "Physical height (dpi): ", ii
1069:                        .getPhysicalHeightDpi(), 1);
1070:                printLine(1, "Physical width (inches): ", ii
1071:                        .getPhysicalWidthInch(), 1.0f);
1072:                printLine(1, "Physical height (inches): ", ii
1073:                        .getPhysicalHeightInch(), 1.0f);
1074:                int numComments = ii.getNumberOfComments();
1075:                printLine(1, "Number of textual comments: ", numComments, 1);
1076:                if (numComments > 0) {
1077:                    for (int i = 0; i < numComments; i++) {
1078:                        printLine(2, null, ii.getComment(i));
1079:                    }
1080:                }
1081:            }
1082:
1083:            private int read() throws IOException {
1084:                if (in != null) {
1085:                    return in.read();
1086:                } else {
1087:                    return din.readByte();
1088:                }
1089:            }
1090:
1091:            private int read(byte[] a) throws IOException {
1092:                if (in != null) {
1093:                    return in.read(a);
1094:                } else {
1095:                    din.readFully(a);
1096:                    return a.length;
1097:                }
1098:            }
1099:
1100:            private int read(byte[] a, int offset, int num) throws IOException {
1101:                if (in != null) {
1102:                    return in.read(a, offset, num);
1103:                } else {
1104:                    din.readFully(a, offset, num);
1105:                    return num;
1106:                }
1107:            }
1108:
1109:            private String readLine() throws IOException {
1110:                return readLine(new SStringBuilder());
1111:            }
1112:
1113:            private String readLine(SStringBuilder sb) throws IOException {
1114:                boolean finished;
1115:                do {
1116:                    int value = read();
1117:                    finished = (value == -1 || value == 10);
1118:                    if (!finished) {
1119:                        sb.append((char) value);
1120:                    }
1121:                } while (!finished);
1122:                return sb.toString();
1123:            }
1124:
1125:            private long readUBits(int numBits) throws IOException {
1126:                if (numBits == 0) {
1127:                    return 0;
1128:                }
1129:                int bitsLeft = numBits;
1130:                long result = 0;
1131:                if (bitPos == 0) { //no value in the buffer - read a byte
1132:                    if (in != null) {
1133:                        bitBuf = in.read();
1134:                    } else {
1135:                        bitBuf = din.readByte();
1136:                    }
1137:                    bitPos = 8;
1138:                }
1139:
1140:                while (true) {
1141:                    int shift = bitsLeft - bitPos;
1142:                    if (shift > 0) {
1143:                        // Consume the entire buffer
1144:                        result |= bitBuf << shift;
1145:                        bitsLeft -= bitPos;
1146:
1147:                        // Get the next byte from the input stream
1148:                        if (in != null) {
1149:                            bitBuf = in.read();
1150:                        } else {
1151:                            bitBuf = din.readByte();
1152:                        }
1153:                        bitPos = 8;
1154:                    } else {
1155:                        // Consume a portion of the buffer
1156:                        result |= bitBuf >> -shift;
1157:                        bitPos -= bitsLeft;
1158:                        bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits
1159:
1160:                        return result;
1161:                    }
1162:                }
1163:            }
1164:
1165:            /**
1166:             * Read a signed value from the given number of bits
1167:             */
1168:            private int readSBits(int numBits) throws IOException {
1169:                // Get the number as an unsigned value.
1170:                long uBits = readUBits(numBits);
1171:
1172:                // Is the number negative?
1173:                if ((uBits & (1L << (numBits - 1))) != 0) {
1174:                    // Yes. Extend the sign.
1175:                    uBits |= -1L << numBits;
1176:                }
1177:
1178:                return (int) uBits;
1179:            }
1180:
1181:            private void synchBits() {
1182:                bitBuf = 0;
1183:                bitPos = 0;
1184:            }
1185:
1186:            private String readLine(int firstChar) throws IOException {
1187:                SStringBuilder result = new SStringBuilder();
1188:                result.append((char) firstChar);
1189:                return readLine(result);
1190:            }
1191:
1192:            private static void run(String sourceName, InputStream in,
1193:                    ImageInfo imageInfo, boolean verbose) {
1194:                imageInfo.setInput(in);
1195:                imageInfo.setDetermineImageNumber(false);
1196:                imageInfo.setCollectComments(verbose);
1197:                if (imageInfo.check()) {
1198:                    print(sourceName, imageInfo, verbose);
1199:                }
1200:            }
1201:
1202:            /**
1203:             * Specify whether textual comments are supposed to be extracted from input.
1204:             * Default is <code>false</code>.
1205:             * If enabled, comments will be added to an internal list.
1206:             *
1207:             * @param newValue if <code>true</code>, this class will read comments
1208:             * @see #getNumberOfComments
1209:             * @see #getComment
1210:             */
1211:            public void setCollectComments(boolean newValue) {
1212:                collectComments = newValue;
1213:            }
1214:
1215:            /**
1216:             * Specify whether the number of images in a file is to be
1217:             * determined - default is <code>false</code>.
1218:             * This is a special option because some file formats require running over
1219:             * the entire file to find out the number of images, a rather time-consuming
1220:             * task.
1221:             * Not all file formats support more than one image.
1222:             * If this method is called with <code>true</code> as argument,
1223:             * the actual number of images can be queried via
1224:             * {@link #getNumberOfImages()} after a successful call to
1225:             * {@link #check()}.
1226:             *
1227:             * @param newValue will the number of images be determined?
1228:             * @see #getNumberOfImages
1229:             */
1230:            public void setDetermineImageNumber(boolean newValue) {
1231:                determineNumberOfImages = newValue;
1232:            }
1233:
1234:            /**
1235:             * Set the input stream to the argument stream (or file).
1236:             * Note that {@link java.io.RandomAccessFile} implements
1237:             * {@link java.io.DataInput}.
1238:             *
1239:             * @param dataInput the input stream to read from
1240:             */
1241:            public void setInput(DataInput dataInput) {
1242:                din = dataInput;
1243:                in = null;
1244:            }
1245:
1246:            /**
1247:             * Set the input stream to the argument stream (or file).
1248:             *
1249:             * @param inputStream the input stream to read from
1250:             */
1251:            public void setInput(InputStream inputStream) {
1252:                in = inputStream;
1253:                din = null;
1254:            }
1255:
1256:            private void setPhysicalHeightDpi(int newValue) {
1257:                physicalWidthDpi = newValue;
1258:            }
1259:
1260:            private void setPhysicalWidthDpi(int newValue) {
1261:                physicalHeightDpi = newValue;
1262:            }
1263:
1264:            private void skip(int num) throws IOException {
1265:                while (num > 0) {
1266:                    long result;
1267:                    if (in != null) {
1268:                        result = in.skip(num);
1269:                    } else {
1270:                        result = din.skipBytes(num);
1271:                    }
1272:                    if (result > 0) {
1273:                        num -= result;
1274:                    }
1275:                }
1276:            }
1277:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.