001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019:
020: package de.schlund.pfixxml;
021:
022: /*
023: * 2002/04/16: Added packaged name for our purposes (jtl)
024: *
025: * ImageInfo.java
026: *
027: * Version 1.1.1
028: *
029: * A Java class to determine image width, height and color depth for
030: * a number of image file formats.
031: *
032: * Written by Marco Schmidt <marcoschmidt@users.sourceforge.net>
033: *
034: * Contributed to the Public Domain.
035: *
036: * Last modification 2002-04-10
037: */
038:
039: import java.io.DataInput;
040: import java.io.FileInputStream;
041: import java.io.IOException;
042: import java.io.InputStream;
043:
044: /**
045: * Get file format, image resolution, number of bits per pixel and optionally
046: * number of images from
047: * JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM and PSD files
048: * (or input streams).
049: * <p>
050: * Use the class like this:
051: * <pre>
052: * ImageInfo ii = new ImageInfo();
053: * ii.setInput(in); // in can be InputStream or RandomAccessFile
054: * ii.setDetermineImageNumber(true); // default is false
055: * if (!ii.check()) {
056: * System.err.println("Not a supported image file format.");
057: * } else {
058: * System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
059: * ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels, " +
060: * ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
061: * " image(s).");
062: * }
063: * </pre>
064: * You can also use this class as a command line program.
065: * Call it with a number of image file names as parameters:
066: * <pre>
067: * java ImageInfo *.jpg *.png *.gif
068: * </pre>
069: * or call it without parameters and pipe data to it:
070: * <pre>
071: * cat image.jpg | java ImageInfo
072: * </pre>
073: * <p>
074: * Known limitations:
075: * <ul>
076: * <li>When the determination of the number of images is turned off, GIF bits
077: * per pixel are only read from the global header.
078: * For some GIFs, local palettes change this to a typically larger
079: * value. To be certain to get the correct color depth, call
080: * setDetermineImageNumber(true) before calling check().
081: * The complete scan over the GIF file will take additional time.</li>
082: * <li>Transparency information is not included in the bits per pixel count.
083: * Actually, it was my decision not to include those bits, so it's a feature! ;-)</li>
084: * </ul>
085: * <p>
086: * Requirements:
087: * <ul>
088: * <li>Java 1.1 or higher</li>
089: * </ul>
090: * <p>
091: * 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>.
092: * <p>
093: * Written by <a href="mailto:marcoschmidt@users.sourceforge.net">Marco Schmidt</a>.
094: * <p>
095: * This class is contributed to the Public Domain.
096: * Use it at your own risk.
097: * <p>
098: * Last modification 2002-04-10.
099: * <p>
100: * History:
101: * <ul>
102: * <li><strong>2001-08-24</strong> Initial version.</li>
103: * <li><strong>2001-10-13</strong> Added support for the file formats BMP and PCX.</li>
104: * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int) that returned
105: * <li><strong>2002-01-22</strong> Added support for file formats Amiga IFF and Sun Raster (RAS).</li>
106: * <li><strong>2002-01-24</strong> Added support for file formats Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe Photoshop (PSD).
107: * Added new method getMimeType() to return the MIME type associated with a particular file format.</li>
108: * <li><strong>2002-03-15</strong> Added support to recognize number of images in file. Only works with GIF.
109: * Use {@link #setDetermineImageNumber} with <code>true</code> as argument to identify animated GIFs
110: * ({@link #getNumberOfImages()} will return a value larger than <code>1</code>).</li>
111: * <li><strong>2002-04-10</strong> Fixed a bug in the feature 'determine number of images in animated GIF' introduced with version 1.1.
112: * Thanks to Marcelo P. Lima for sending in the bug report.</li>
113: * </ul>
114: */
115: public class ImageInfo {
116: /** Return value of {@link #getFormat()} for JPEG streams. */
117: public static final int FORMAT_JPEG = 0;
118: /** Return value of {@link #getFormat()} for GIF streams. */
119: public static final int FORMAT_GIF = 1;
120: /** Return value of {@link #getFormat()} for PNG streams. */
121: public static final int FORMAT_PNG = 2;
122: /** Return value of {@link #getFormat()} for BMP streams. */
123: public static final int FORMAT_BMP = 3;
124: /** Return value of {@link #getFormat()} for PCX streams. */
125: public static final int FORMAT_PCX = 4;
126: /** Return value of {@link #getFormat()} for IFF streams. */
127: public static final int FORMAT_IFF = 5;
128: /** Return value of {@link #getFormat()} for RAS streams. */
129: public static final int FORMAT_RAS = 6;
130: /** Return value of {@link #getFormat()} for PBM streams. */
131: public static final int FORMAT_PBM = 7;
132: /** Return value of {@link #getFormat()} for PBM streams. */
133: public static final int FORMAT_PGM = 8;
134: /** Return value of {@link #getFormat()} for PBM streams. */
135: public static final int FORMAT_PPM = 9;
136: /** Return value of {@link #getFormat()} for PBM streams. */
137: public static final int FORMAT_PSD = 10;
138: private static final String[] FORMAT_NAMES = { "JPEG", "GIF",
139: "PNG", "BMP", "PCX", "IFF", "RAS", "PBM", "PGM", "PPM",
140: "PSD" };
141: private static final String[] MIME_TYPE_STRINGS = { "image/jpeg",
142: "image/gif", "image/png", "image/bmp", "image/pcx",
143: "image/iff", "image/ras", "image/x-portable-bitmap",
144: "image/x-portable-graymap", "image/x-portable-pixmap",
145: "image/psd" };
146: private int width;
147: private int height;
148: private int bitsPerPixel;
149: private int format;
150: private InputStream in;
151: private DataInput din;
152: // private boolean collectComments;
153: private boolean determineNumberOfImages;
154: private int numberOfImages;
155:
156: /**
157: * Call this method after you have provided an input stream or file
158: * using {@link #setInput(InputStream)} or {@link #setInput(DataInput)}.
159: * If true is returned, the file format was known and you information
160: * about its content can be retrieved using the various getXyz methods.
161: * @return if information could be retrieved from input
162: */
163: public boolean check() {
164: format = -1;
165: width = -1;
166: height = -1;
167: bitsPerPixel = -1;
168: numberOfImages = 1;
169: try {
170: int b1 = read() & 0xff;
171: int b2 = read() & 0xff;
172: if (b1 == 0x47 && b2 == 0x49) {
173: return checkGif();
174: } else if (b1 == 0x89 && b2 == 0x50) {
175: return checkPng();
176: } else if (b1 == 0xff && b2 == 0xd8) {
177: return checkJpeg();
178: } else if (b1 == 0x42 && b2 == 0x4d) {
179: return checkBmp();
180: } else if (b1 == 0x0a && b2 < 0x06) {
181: return checkPcx();
182: } else if (b1 == 0x46 && b2 == 0x4f) {
183: return checkIff();
184: } else if (b1 == 0x59 && b2 == 0xa6) {
185: return checkRas();
186: } else if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
187: return checkPnm(b2 - '0');
188: } else if (b1 == 0x38 && b2 == 0x42) {
189: return checkPsd();
190: } else {
191: return false;
192: }
193: } catch (IOException ioe) {
194: return false;
195: }
196: }
197:
198: private boolean checkBmp() throws IOException {
199: byte[] a = new byte[28];
200: if (read(a) != a.length) {
201: return false;
202: }
203: width = getIntLittleEndian(a, 16);
204: height = getIntLittleEndian(a, 20);
205: bitsPerPixel = getShortLittleEndian(a, 26);
206: if (width < 1 || height < 1) {
207: return false;
208: }
209: if (bitsPerPixel != 1 && bitsPerPixel != 4 && bitsPerPixel != 8
210: && bitsPerPixel != 16 && bitsPerPixel != 24
211: && bitsPerPixel != 32) {
212: return false;
213: }
214: format = FORMAT_BMP;
215: return true;
216: }
217:
218: private boolean checkGif() throws IOException {
219: final byte[] GIF_MAGIC_87A = { 0x46, 0x38, 0x37, 0x61 };
220: final byte[] GIF_MAGIC_89A = { 0x46, 0x38, 0x39, 0x61 };
221: byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
222: if (read(a) != 11) {
223: return false;
224: }
225: if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4))
226: && (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
227: return false;
228: }
229: format = FORMAT_GIF;
230: width = getShortLittleEndian(a, 4);
231: height = getShortLittleEndian(a, 6);
232: int flags = a[8] & 0xff;
233: bitsPerPixel = ((flags >> 4) & 0x07) + 1;
234: if (!determineNumberOfImages) {
235: return true;
236: }
237: // skip global color palette
238: if ((flags & 0x80) != 0) {
239: int tableSize = (1 << ((flags & 7) + 1)) * 3;
240: skip(tableSize);
241: }
242: numberOfImages = 0;
243: int blockType;
244: do {
245: blockType = read();
246: switch (blockType) {
247: case (0x2c): // image separator
248: {
249: if (read(a, 0, 9) != 9) {
250: return false;
251: }
252: flags = a[8] & 0xff;
253: int localBitsPerPixel = (flags & 0x07) + 1;
254: if (localBitsPerPixel > bitsPerPixel) {
255: bitsPerPixel = localBitsPerPixel;
256: }
257: if ((flags & 0x80) != 0) {
258: skip((1 << localBitsPerPixel) * 3);
259: }
260: skip(1); // initial code length
261: int n;
262: do {
263: n = read();
264: if (n > 0) {
265: skip(n);
266: } else if (n == -1) {
267: return false;
268: }
269: } while (n > 0);
270: numberOfImages++;
271: break;
272: }
273: case (0x21): // extension
274: {
275: skip(1); // extension type
276: int n;
277: do {
278: n = read();
279: if (n > 0) {
280: skip(n);
281: } else if (n == -1) {
282: return false;
283: }
284: } while (n > 0);
285: break;
286: }
287: case (0x3b): // end of file
288: {
289: break;
290: }
291: default: {
292: return false;
293: }
294: }
295: } while (blockType != 0x3b);
296: return true;
297: }
298:
299: private boolean checkIff() throws IOException {
300: byte[] a = new byte[10];
301: // read remaining 2 bytes of file id, 4 bytes file size
302: // and 4 bytes IFF subformat
303: if (read(a, 0, 10) != 10) {
304: return false;
305: }
306: final byte[] IFF_RM = { 0x52, 0x4d };
307: if (!equals(a, 0, IFF_RM, 0, 2)) {
308: return false;
309: }
310: int type = getIntBigEndian(a, 6);
311: if (type != 0x494c424d && // type must be ILBM...
312: type != 0x50424d20) { // ...or PBM
313: return false;
314: }
315: // loop chunks to find BMHD chunk
316: do {
317: if (read(a, 0, 8) != 8) {
318: return false;
319: }
320: int chunkId = getIntBigEndian(a, 0);
321: int size = getIntBigEndian(a, 4);
322: if ((size & 1) == 1) {
323: size++;
324: }
325: if (chunkId == 0x424d4844) { // BMHD chunk
326: if (read(a, 0, 9) != 9) {
327: return false;
328: }
329: format = FORMAT_IFF;
330: width = getShortBigEndian(a, 0);
331: height = getShortBigEndian(a, 2);
332: bitsPerPixel = a[8] & 0xff;
333: return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
334: } else {
335: skip(size);
336: }
337: } while (true);
338: }
339:
340: private boolean checkJpeg() throws IOException {
341: byte[] data = new byte[6];
342: while (true) {
343: if (read(data, 0, 4) != 4) {
344: return false;
345: }
346: int marker = getShortBigEndian(data, 0);
347: int size = getShortBigEndian(data, 2);
348: if ((marker & 0xff00) != 0xff00) {
349: return false; // not a valid marker
350: }
351: if (marker >= 0xffc0 && marker <= 0xffcf
352: && marker != 0xffc4 && marker != 0xffc8) {
353: if (read(data) != 6) {
354: return false;
355: }
356: format = FORMAT_JPEG;
357: bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
358: width = getShortBigEndian(data, 3);
359: height = getShortBigEndian(data, 1);
360: return true;
361: } else {
362: skip(size - 2);
363: }
364: }
365: }
366:
367: private boolean checkPcx() throws IOException {
368: byte[] a = new byte[64];
369: if (read(a) != a.length) {
370: return false;
371: }
372: if (a[0] != 1) { // encoding, 1=RLE is only valid value
373: return false;
374: }
375: // width / height
376: int x1 = getShortLittleEndian(a, 2);
377: int y1 = getShortLittleEndian(a, 4);
378: int x2 = getShortLittleEndian(a, 6);
379: int y2 = getShortLittleEndian(a, 8);
380: if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
381: return false;
382: }
383: width = x2 - x1 + 1;
384: height = y2 - y1 + 1;
385: // color depth
386: int bits = a[1];
387: int planes = a[63];
388: if (planes == 1
389: && (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
390: // paletted
391: bitsPerPixel = bits;
392: } else if (planes == 3 && bits == 8) {
393: // RGB truecolor
394: bitsPerPixel = 24;
395: } else {
396: return false;
397: }
398: format = FORMAT_PCX;
399: return true;
400: }
401:
402: private boolean checkPng() throws IOException {
403: final byte[] PNG_MAGIC = { 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
404: byte[] a = new byte[24];
405: if (read(a) != 24) {
406: return false;
407: }
408: if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
409: return false;
410: }
411: format = FORMAT_PNG;
412: width = getIntBigEndian(a, 14);
413: height = getIntBigEndian(a, 18);
414: bitsPerPixel = a[22] & 0xff;
415: int colorType = a[23] & 0xff;
416: if (colorType == 2 || colorType == 6) {
417: bitsPerPixel *= 3;
418: }
419: return true;
420: }
421:
422: private boolean checkPnm(int id) throws IOException {
423: if (id < 1 || id > 6) {
424: return false;
425: }
426: final int[] PNM_FORMATS = { FORMAT_PBM, FORMAT_PGM, FORMAT_PPM };
427: format = PNM_FORMATS[(id - 1) % 3];
428: boolean hasPixelResolution = false;
429: String s;
430: while (true) {
431: s = readLine();
432: if (s != null) {
433: s = s.trim();
434: }
435: if (s == null || s.length() < 1) {
436: continue;
437: }
438: if (s.charAt(0) == '#') { // comment
439: continue;
440: }
441: if (!hasPixelResolution) { // split "343 966" into width=343, height=966
442: int spaceIndex = s.indexOf(' ');
443: if (spaceIndex == -1) {
444: return false;
445: }
446: String widthString = s.substring(0, spaceIndex);
447: spaceIndex = s.lastIndexOf(' ');
448: if (spaceIndex == -1) {
449: return false;
450: }
451: String heightString = s.substring(spaceIndex + 1);
452: try {
453: width = Integer.parseInt(widthString);
454: height = Integer.parseInt(heightString);
455: } catch (NumberFormatException nfe) {
456: return false;
457: }
458: if (width < 1 || height < 1) {
459: return false;
460: }
461: if (format == FORMAT_PBM) {
462: bitsPerPixel = 1;
463: return true;
464: }
465: hasPixelResolution = true;
466: } else {
467: int maxSample;
468: try {
469: maxSample = Integer.parseInt(s);
470: } catch (NumberFormatException nfe) {
471: return false;
472: }
473: if (maxSample < 0) {
474: return false;
475: }
476: for (int i = 0; i < 25; i++) {
477: if (maxSample < (1 << (i + 1))) {
478: bitsPerPixel = i + 1;
479: if (format == FORMAT_PPM) {
480: bitsPerPixel *= 3;
481: }
482: return true;
483: }
484: }
485: return false;
486: }
487: }
488: }
489:
490: private boolean checkPsd() throws IOException {
491: byte[] a = new byte[24];
492: if (read(a) != a.length) {
493: return false;
494: }
495: final byte[] PSD_MAGIC = { 0x50, 0x53 };
496: if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
497: return false;
498: }
499: format = FORMAT_PSD;
500: width = getIntBigEndian(a, 16);
501: height = getIntBigEndian(a, 12);
502: int channels = getShortBigEndian(a, 10);
503: int depth = getShortBigEndian(a, 20);
504: bitsPerPixel = channels * depth;
505: return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
506: }
507:
508: private boolean checkRas() throws IOException {
509: byte[] a = new byte[14];
510: if (read(a) != a.length) {
511: return false;
512: }
513: final byte[] RAS_MAGIC = { 0x6a, (byte) 0x95 };
514: if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
515: return false;
516: }
517: format = FORMAT_RAS;
518: width = getIntBigEndian(a, 2);
519: height = getIntBigEndian(a, 6);
520: bitsPerPixel = getIntBigEndian(a, 10);
521: return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
522: }
523:
524: private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2,
525: int num) {
526: while (num-- > 0) {
527: if (a1[offs1++] != a2[offs2++]) {
528: return false;
529: }
530: }
531: return true;
532: }
533:
534: /**
535: * If {@link #check()} was successful, returns the image's number of bits per pixel.
536: * Does not include transparency information like the alpha channel.
537: * @return number of bits per image pixel
538: */
539: public int getBitsPerPixel() {
540: return bitsPerPixel;
541: }
542:
543: /**
544: * If {@link #check()} was successful, returns the image format as one
545: * of the FORMAT_xyz constants from this class.
546: * Use {@link #getFormatName()} to get a textual description of the file format.
547: * @return file format as a FORMAT_xyz constant
548: */
549: public int getFormat() {
550: return format;
551: }
552:
553: /**
554: * If {@link #check()} was successful, returns the image format's name.
555: * Use {@link #getFormat()} to get a unique number.
556: * @return file format name
557: */
558: public String getFormatName() {
559: if (format >= 0 && format < FORMAT_NAMES.length) {
560: return FORMAT_NAMES[format];
561: } else {
562: return "?";
563: }
564: }
565:
566: /**
567: * If {@link #check()} was successful, returns one the image's vertical
568: * resolution in pixels.
569: * @return image height in pixels
570: */
571: public int getHeight() {
572: return height;
573: }
574:
575: private int getIntBigEndian(byte[] a, int offs) {
576: return (a[offs] & 0xff) << 24 | (a[offs + 1] & 0xff) << 16
577: | (a[offs + 2] & 0xff) << 8 | a[offs + 3] & 0xff;
578: }
579:
580: private int getIntLittleEndian(byte[] a, int offs) {
581: return (a[offs + 3] & 0xff) << 24 | (a[offs + 2] & 0xff) << 16
582: | (a[offs + 1] & 0xff) << 8 | a[offs] & 0xff;
583: }
584:
585: /**
586: * If {@link #check()} was successful, returns a String with the
587: * MIME type of the format.
588: * @return MIME type, e.g. <code>image/jpeg</code>
589: */
590: public String getMimeType() {
591: if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
592: return MIME_TYPE_STRINGS[format];
593: } else {
594: return null;
595: }
596: }
597:
598: /**
599: * Returns the number of images in the examined file
600: * if <code>setDetermineImageNumber(true);</code> was called before
601: * a successful call to {@link #check()}.
602: * @return number of images in file
603: */
604: public int getNumberOfImages() {
605: return numberOfImages;
606: }
607:
608: private int getShortBigEndian(byte[] a, int offs) {
609: return (a[offs] & 0xff) << 8 | (a[offs + 1] & 0xff);
610: }
611:
612: private int getShortLittleEndian(byte[] a, int offs) {
613: return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
614: }
615:
616: /**
617: * If {@link #check()} was successful, returns one the image's horizontal
618: * resolution in pixels.
619: * @return image width in pixels
620: */
621: public int getWidth() {
622: return width;
623: }
624:
625: /**
626: * To use this class as a command line application, give it either
627: * some file names as parameters (information on them will be
628: * printed to standard output, one line per file) or call
629: * it with no parameters. It will then check data given to it
630: * via standard input.
631: * @param args the program arguments which must be file names
632: */
633: public static void main(String[] args) {
634: ImageInfo imageInfo = new ImageInfo();
635: if (args.length == 0) {
636: run(System.in, imageInfo);
637: } else {
638: int index = 0;
639: while (index < args.length) {
640: FileInputStream tmp = null;
641: try {
642: String filename = args[index++];
643: System.out.print(filename + ";");
644: tmp = new FileInputStream(filename);
645: run(tmp, imageInfo);
646: tmp.close();
647: } catch (Exception e) {
648: System.out.println(e);
649: try {
650: tmp.close();
651: } catch (Exception ee) {
652: }
653: }
654: }
655: }
656: }
657:
658: private int read() throws IOException {
659: if (in != null) {
660: return in.read();
661: } else {
662: return din.readByte();
663: }
664: }
665:
666: private int read(byte[] a) throws IOException {
667: if (in != null) {
668: return in.read(a);
669: } else {
670: din.readFully(a);
671: return a.length;
672: }
673: }
674:
675: private int read(byte[] a, int offset, int num) throws IOException {
676: if (in != null) {
677: return in.read(a, offset, num);
678: } else {
679: din.readFully(a, offset, num);
680: return num;
681: }
682: }
683:
684: private String readLine() throws IOException {
685: return readLine(new StringBuffer());
686: }
687:
688: private String readLine(StringBuffer sb) throws IOException {
689: boolean finished;
690: do {
691: int value = read();
692: finished = (value == -1 || value == 10);
693: if (!finished) {
694: sb.append((char) value);
695: }
696: } while (!finished);
697: return sb.toString();
698: }
699:
700: private static void run(InputStream in, ImageInfo imageInfo) {
701: imageInfo.setInput(in);
702: imageInfo.setDetermineImageNumber(true);
703: if (imageInfo.check()) {
704: System.out.println(imageInfo.getFormatName() + ";"
705: + imageInfo.getMimeType() + ";"
706: + imageInfo.getWidth() + ";"
707: + imageInfo.getHeight() + ";"
708: + imageInfo.getBitsPerPixel() + ";"
709: + imageInfo.getNumberOfImages());
710: } else {
711: System.out.println("?");
712: }
713: }
714:
715: public void setCollectComments(boolean newValue) {
716: // collectComments = newValue;
717: }
718:
719: /**
720: * Specify whether the number of images in a file are to be
721: * determined - default is <code>false</code>.
722: * Will only make a difference with file formats that do support
723: * more than one image like GIF.
724: * If this method is called with <code>true</code> as argument,
725: * the actual number of images can be queried via
726: * {@link #getNumberOfImages()} after a successful call to
727: * {@link #check()}.
728: * @param newValue will the number of images be determined?
729: */
730: public void setDetermineImageNumber(boolean newValue) {
731: determineNumberOfImages = newValue;
732: }
733:
734: /**
735: * Set the input stream to the argument stream (or file).
736: * Note that {@link java.io.RandomAccessFile} implements
737: * {@link java.io.DataInput}.
738: * @param dataInput the input stream to read from
739: */
740: public void setInput(DataInput dataInput) {
741: din = dataInput;
742: in = null;
743: }
744:
745: /**
746: * Set the input stream to the argument stream (or file).
747: * @param inputStream the input stream to read from
748: */
749: public void setInput(InputStream inputStream) {
750: in = inputStream;
751: din = null;
752: }
753:
754: private void skip(int num) throws IOException {
755: if (in != null) {
756: in.skip(num);
757: } else {
758: din.skipBytes(num);
759: }
760: }
761: }
|