1
2
3
4
5
6
7
8
9
10
11
12
13 package org.devlib.schmidt.imageinfo;
14
15 import java.io.DataInput;
16 import java.io.FileInputStream;
17 import java.io.InputStream;
18 import java.io.IOException;
19 import java.net.URL;
20 import java.util.Vector;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 @SuppressWarnings("unchecked")
152 public class ImageInfo {
153
154
155
156
157
158
159
160
161 public static final int FORMAT_JPEG = 0;
162
163
164
165
166
167
168
169 public static final int FORMAT_GIF = 1;
170
171
172
173
174
175
176
177
178 public static final int FORMAT_PNG = 2;
179
180
181
182
183
184
185
186 public static final int FORMAT_BMP = 3;
187
188
189
190
191
192
193 public static final int FORMAT_PCX = 4;
194
195
196
197
198 public static final int FORMAT_IFF = 5;
199
200
201
202
203
204
205 public static final int FORMAT_RAS = 6;
206
207
208 public static final int FORMAT_PBM = 7;
209
210
211 public static final int FORMAT_PGM = 8;
212
213
214 public static final int FORMAT_PPM = 9;
215
216
217 public static final int FORMAT_PSD = 10;
218
219
220
221
222
223
224
225
226
227
228
229
230 private static final String[] FORMAT_NAMES =
231 {"JPEG", "GIF", "PNG", "BMP", "PCX",
232 "IFF", "RAS", "PBM", "PGM", "PPM",
233 "PSD"};
234
235
236
237
238
239
240 private static final String[] MIME_TYPE_STRINGS =
241 {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx",
242 "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap",
243 "image/psd"};
244
245 private int width;
246 private int height;
247 private int bitsPerPixel;
248
249 private boolean progressive;
250 private int format;
251 private InputStream in;
252 private DataInput din;
253 private boolean collectComments = true;
254 private Vector comments;
255 private boolean determineNumberOfImages;
256 private int numberOfImages;
257 private int physicalHeightDpi;
258 private int physicalWidthDpi;
259
260 private void addComment(String s) {
261 if (comments == null) {
262 comments = new Vector();
263 }
264 comments.addElement(s);
265 }
266
267
268
269
270
271
272
273
274 public boolean check() {
275 format = -1;
276 width = -1;
277 height = -1;
278 bitsPerPixel = -1;
279 numberOfImages = 1;
280 physicalHeightDpi = -1;
281 physicalWidthDpi = -1;
282 comments = null;
283 try {
284 int b1 = read() & 0xff;
285 int b2 = read() & 0xff;
286 if (b1 == 0x47 && b2 == 0x49) {
287 return checkGif();
288 }
289 else
290 if (b1 == 0x89 && b2 == 0x50) {
291 return checkPng();
292 }
293 else
294 if (b1 == 0xff && b2 == 0xd8) {
295 return checkJpeg();
296 }
297 else
298 if (b1 == 0x42 && b2 == 0x4d) {
299 return checkBmp();
300 }
301 else
302 if (b1 == 0x0a && b2 < 0x06) {
303 return checkPcx();
304 }
305 else
306 if (b1 == 0x46 && b2 == 0x4f) {
307 return checkIff();
308 }
309 else
310 if (b1 == 0x59 && b2 == 0xa6) {
311 return checkRas();
312 }
313 else
314 if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
315 return checkPnm(b2 - '0');
316 }
317 else
318 if (b1 == 0x38 && b2 == 0x42) {
319 return checkPsd();
320 }
321 else {
322 return false;
323 }
324 } catch (IOException ioe) {
325 return false;
326 }
327 }
328
329 private boolean checkBmp() throws IOException {
330 byte[] a = new byte[44];
331 if (read(a) != a.length) {
332 return false;
333 }
334 width = getIntLittleEndian(a, 16);
335 height = getIntLittleEndian(a, 20);
336 if (width < 1 || height < 1) {
337 return false;
338 }
339 bitsPerPixel = getShortLittleEndian(a, 26);
340 if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
341 bitsPerPixel != 8 && bitsPerPixel != 16 &&
342 bitsPerPixel != 24 && bitsPerPixel != 32) {
343 return false;
344 }
345 int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
346 if (x > 0) {
347 setPhysicalWidthDpi(x);
348 }
349 int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
350 if (y > 0) {
351 setPhysicalHeightDpi(y);
352 }
353 format = FORMAT_BMP;
354 return true;
355 }
356
357 private boolean checkGif() throws IOException {
358 final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
359 final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
360 byte[] a = new byte[11];
361 if (read(a) != 11) {
362 return false;
363 }
364 if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
365 (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
366 return false;
367 }
368 format = FORMAT_GIF;
369 width = getShortLittleEndian(a, 4);
370 height = getShortLittleEndian(a, 6);
371 int flags = a[8] & 0xff;
372 bitsPerPixel = ((flags >> 4) & 0x07) + 1;
373
374 if (!determineNumberOfImages) {
375 return true;
376 }
377
378 if ((flags & 0x80) != 0) {
379 int tableSize = (1 << ((flags & 7) + 1)) * 3;
380 skip(tableSize);
381 }
382 numberOfImages = 0;
383 int blockType;
384 do
385 {
386 blockType = read();
387 switch(blockType)
388 {
389 case(0x2c):
390 {
391 if (read(a, 0, 9) != 9) {
392 return false;
393 }
394 flags = a[8] & 0xff;
395 progressive = (flags & 0x40) != 0;
396
397
398
399 int localBitsPerPixel = (flags & 0x07) + 1;
400 if (localBitsPerPixel > bitsPerPixel) {
401 bitsPerPixel = localBitsPerPixel;
402 }
403 if ((flags & 0x80) != 0) {
404 skip((1 << localBitsPerPixel) * 3);
405 }
406 skip(1);
407 int n;
408 do
409 {
410 n = read();
411 if (n > 0) {
412 skip(n);
413 }
414 else
415 if (n == -1) {
416 return false;
417 }
418 }
419 while (n > 0);
420 numberOfImages++;
421 break;
422 }
423 case(0x21):
424 {
425 int extensionType = read();
426 if (collectComments && extensionType == 0xfe) {
427 StringBuffer sb = new StringBuffer();
428 int n;
429 do
430 {
431 n = read();
432 if (n == -1) {
433 return false;
434 }
435 if (n > 0) {
436 for (int i = 0; i < n; i++) {
437 int ch = read();
438 if (ch == -1) {
439 return false;
440 }
441 sb.append((char)ch);
442 }
443 }
444 }
445 while (n > 0);
446 } else {
447 int n;
448 do
449 {
450 n = read();
451 if (n > 0) {
452 skip(n);
453 }
454 else
455 if (n == -1) {
456 return false;
457 }
458 }
459 while (n > 0);
460 }
461 break;
462 }
463 case(0x3b):
464 {
465 break;
466 }
467 default:
468 {
469 return false;
470 }
471 }
472 }
473 while (blockType != 0x3b);
474 return true;
475 }
476
477 private boolean checkIff() throws IOException {
478 byte[] a = new byte[10];
479
480
481 if (read(a, 0, 10) != 10) {
482 return false;
483 }
484 final byte[] IFF_RM = {0x52, 0x4d};
485 if (!equals(a, 0, IFF_RM, 0, 2)) {
486 return false;
487 }
488 int type = getIntBigEndian(a, 6);
489 if (type != 0x494c424d &&
490 type != 0x50424d20) {
491 return false;
492 }
493
494 do {
495 if (read(a, 0, 8) != 8) {
496 return false;
497 }
498 int chunkId = getIntBigEndian(a, 0);
499 int size = getIntBigEndian(a, 4);
500 if ((size & 1) == 1) {
501 size++;
502 }
503 if (chunkId == 0x424d4844) {
504 if (read(a, 0, 9) != 9) {
505 return false;
506 }
507 format = FORMAT_IFF;
508 width = getShortBigEndian(a, 0);
509 height = getShortBigEndian(a, 2);
510 bitsPerPixel = a[8] & 0xff;
511 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
512 } else {
513 skip(size);
514 }
515 } while (true);
516 }
517
518 private boolean checkJpeg() throws IOException {
519 byte[] data = new byte[12];
520 while (true) {
521 if (read(data, 0, 4) != 4) {
522 return false;
523 }
524 int marker = getShortBigEndian(data, 0);
525 int size = getShortBigEndian(data, 2);
526 if ((marker & 0xff00) != 0xff00) {
527 return false;
528 }
529 if (marker == 0xffe0) {
530 if (size < 14) {
531
532 skip(size - 2);
533 continue;
534 }
535 if (read(data, 0, 12) != 12) {
536 return false;
537 }
538 final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
539 if (equals(APP0_ID, 0, data, 0, 5)) {
540
541 if (data[7] == 1) {
542 setPhysicalWidthDpi(getShortBigEndian(data, 8));
543 setPhysicalHeightDpi(getShortBigEndian(data, 10));
544 }
545 else
546 if (data[7] == 2) {
547 int x = getShortBigEndian(data, 8);
548 int y = getShortBigEndian(data, 10);
549 setPhysicalWidthDpi((int)(x * 2.54f));
550 setPhysicalHeightDpi((int)(y * 2.54f));
551 }
552 }
553 skip(size - 14);
554 }
555 else
556 if (collectComments && size > 2 && marker == 0xfffe) {
557 size -= 2;
558 byte[] chars = new byte[size];
559 if (read(chars, 0, size) != size) {
560 return false;
561 }
562 String comment = new String(chars, "iso-8859-1");
563 comment = comment.trim();
564 addComment(comment);
565 }
566 else
567 if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
568 if (read(data, 0, 6) != 6) {
569 return false;
570 }
571 format = FORMAT_JPEG;
572 bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
573 progressive = marker == 0xffc2 || marker == 0xffc6 ||
574 marker == 0xffca || marker == 0xffce;
575 width = getShortBigEndian(data, 3);
576 height = getShortBigEndian(data, 1);
577 return true;
578 } else {
579 skip(size - 2);
580 }
581 }
582 }
583
584 private boolean checkPcx() throws IOException {
585 byte[] a = new byte[64];
586 if (read(a) != a.length) {
587 return false;
588 }
589 if (a[0] != 1) {
590 return false;
591 }
592
593 int x1 = getShortLittleEndian(a, 2);
594 int y1 = getShortLittleEndian(a, 4);
595 int x2 = getShortLittleEndian(a, 6);
596 int y2 = getShortLittleEndian(a, 8);
597 if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
598 return false;
599 }
600 width = x2 - x1 + 1;
601 height = y2 - y1 + 1;
602
603 int bits = a[1];
604 int planes = a[63];
605 if (planes == 1 &&
606 (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
607
608 bitsPerPixel = bits;
609 } else
610 if (planes == 3 && bits == 8) {
611
612 bitsPerPixel = 24;
613 } else {
614 return false;
615 }
616 setPhysicalWidthDpi(getShortLittleEndian(a, 10));
617 setPhysicalHeightDpi(getShortLittleEndian(a, 10));
618 format = FORMAT_PCX;
619 return true;
620 }
621
622 private boolean checkPng() throws IOException {
623 final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
624 byte[] a = new byte[27];
625 if (read(a) != 27) {
626 return false;
627 }
628 if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
629 return false;
630 }
631 format = FORMAT_PNG;
632 width = getIntBigEndian(a, 14);
633 height = getIntBigEndian(a, 18);
634 bitsPerPixel = a[22] & 0xff;
635 int colorType = a[23] & 0xff;
636 if (colorType == 2 || colorType == 6) {
637 bitsPerPixel *= 3;
638 }
639 progressive = (a[26] & 0xff) != 0;
640 return true;
641 }
642
643 private boolean checkPnm(int id) throws IOException {
644 if (id < 1 || id > 6) {
645 return false;
646 }
647 final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
648 format = PNM_FORMATS[(id - 1) % 3];
649 boolean hasPixelResolution = false;
650 String s;
651 while (true)
652 {
653 s = readLine();
654 if (s != null) {
655 s = s.trim();
656 }
657 if (s == null || s.length() < 1) {
658 continue;
659 }
660 if (s.charAt(0) == '#') {
661 if (collectComments && s.length() > 1) {
662 addComment(s.substring(1));
663 }
664 continue;
665 }
666 if (!hasPixelResolution) {
667 int spaceIndex = s.indexOf(' ');
668 if (spaceIndex == -1) {
669 return false;
670 }
671 String widthString = s.substring(0, spaceIndex);
672 spaceIndex = s.lastIndexOf(' ');
673 if (spaceIndex == -1) {
674 return false;
675 }
676 String heightString = s.substring(spaceIndex + 1);
677 try {
678 width = Integer.parseInt(widthString);
679 height = Integer.parseInt(heightString);
680 } catch (NumberFormatException nfe) {
681 return false;
682 }
683 if (width < 1 || height < 1) {
684 return false;
685 }
686 if (format == FORMAT_PBM) {
687 bitsPerPixel = 1;
688 return true;
689 }
690 hasPixelResolution = true;
691 }
692 else
693 {
694 int maxSample;
695 try {
696 maxSample = Integer.parseInt(s);
697 } catch (NumberFormatException nfe) {
698 return false;
699 }
700 if (maxSample < 0) {
701 return false;
702 }
703 for (int i = 0; i < 25; i++) {
704 if (maxSample < (1 << (i + 1))) {
705 bitsPerPixel = i + 1;
706 if (format == FORMAT_PPM) {
707 bitsPerPixel *= 3;
708 }
709 return true;
710 }
711 }
712 return false;
713 }
714 }
715 }
716
717 private boolean checkPsd() throws IOException {
718 byte[] a = new byte[24];
719 if (read(a) != a.length) {
720 return false;
721 }
722 final byte[] PSD_MAGIC = {0x50, 0x53};
723 if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
724 return false;
725 }
726 format = FORMAT_PSD;
727 width = getIntBigEndian(a, 16);
728 height = getIntBigEndian(a, 12);
729 int channels = getShortBigEndian(a, 10);
730 int depth = getShortBigEndian(a, 20);
731 bitsPerPixel = channels * depth;
732 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
733 }
734
735 private boolean checkRas() throws IOException {
736 byte[] a = new byte[14];
737 if (read(a) != a.length) {
738 return false;
739 }
740 final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
741 if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
742 return false;
743 }
744 format = FORMAT_RAS;
745 width = getIntBigEndian(a, 2);
746 height = getIntBigEndian(a, 6);
747 bitsPerPixel = getIntBigEndian(a, 10);
748 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
749 }
750
751
752
753
754
755
756 private static boolean determineVerbosity(String[] args) {
757 if (args != null && args.length > 0) {
758 for (int i = 0; i < args.length; i++) {
759 if ("-c".equals(args[i])) {
760 return false;
761 }
762 }
763 }
764 return true;
765 }
766
767 private static boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
768 while (num-- > 0) {
769 if (a1[offs1++] != a2[offs2++]) {
770 return false;
771 }
772 }
773 return true;
774 }
775
776
777
778
779
780
781 public int getBitsPerPixel() {
782 return bitsPerPixel;
783 }
784
785
786
787
788
789
790
791
792 public String getComment(int index) {
793 if (comments == null || index < 0 || index >= comments.size()) {
794 throw new IllegalArgumentException("Not a valid comment index: " + index);
795 }
796 return (String)comments.elementAt(index);
797 }
798
799
800
801
802
803
804
805 public int getFormat() {
806 return format;
807 }
808
809
810
811
812
813
814 public String getFormatName() {
815 if (format >= 0 && format < FORMAT_NAMES.length) {
816 return FORMAT_NAMES[format];
817 } else {
818 return "?";
819 }
820 }
821
822
823
824
825
826
827 public int getHeight() {
828 return height;
829 }
830
831 private static int getIntBigEndian(byte[] a, int offs) {
832 return
833 (a[offs] & 0xff) << 24 |
834 (a[offs + 1] & 0xff) << 16 |
835 (a[offs + 2] & 0xff) << 8 |
836 a[offs + 3] & 0xff;
837 }
838
839 private static int getIntLittleEndian(byte[] a, int offs) {
840 return
841 (a[offs + 3] & 0xff) << 24 |
842 (a[offs + 2] & 0xff) << 16 |
843 (a[offs + 1] & 0xff) << 8 |
844 a[offs] & 0xff;
845 }
846
847
848
849
850
851
852 public String getMimeType() {
853 if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
854 if (format == FORMAT_JPEG && progressive)
855 {
856 return "image/pjpeg";
857 }
858 return MIME_TYPE_STRINGS[format];
859 } else {
860 return null;
861 }
862 }
863
864
865
866
867
868
869
870
871
872 public int getNumberOfComments()
873 {
874 if (comments == null) {
875 return 0;
876 } else {
877 return comments.size();
878 }
879 }
880
881
882
883
884
885
886
887
888 public int getNumberOfImages()
889 {
890 return numberOfImages;
891 }
892
893
894
895
896
897
898
899
900
901 public int getPhysicalHeightDpi() {
902 return physicalHeightDpi;
903 }
904
905
906
907
908
909
910
911
912
913 public float getPhysicalHeightInch() {
914 int h = getHeight();
915 int ph = getPhysicalHeightDpi();
916 if (h > 0 && ph > 0) {
917 return ((float)h) / ((float)ph);
918 } else {
919 return -1.0f;
920 }
921 }
922
923
924
925
926
927
928
929
930
931 public int getPhysicalWidthDpi() {
932 return physicalWidthDpi;
933 }
934
935
936
937
938
939
940
941
942
943 public float getPhysicalWidthInch() {
944 int w = getWidth();
945 int pw = getPhysicalWidthDpi();
946 if (w > 0 && pw > 0) {
947 return ((float)w) / ((float)pw);
948 } else {
949 return -1.0f;
950 }
951 }
952
953 private static int getShortBigEndian(byte[] a, int offs) {
954 return
955 (a[offs] & 0xff) << 8 |
956 (a[offs + 1] & 0xff);
957 }
958
959 private static int getShortLittleEndian(byte[] a, int offs) {
960 return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
961 }
962
963
964
965
966
967
968 public int getWidth() {
969 return width;
970 }
971
972
973
974
975
976 public boolean isProgressive()
977 {
978 return progressive;
979 }
980
981
982
983
984
985
986
987
988
989 public static void main(String[] args) {
990 ImageInfo imageInfo = new ImageInfo();
991 imageInfo.setDetermineImageNumber(true);
992 boolean verbose = determineVerbosity(args);
993 if (args.length == 0) {
994 run(null, System.in, imageInfo, verbose);
995 } else {
996 int index = 0;
997 while (index < args.length) {
998 InputStream in = null;
999 try {
1000 String name = args[index++];
1001 System.out.print(name + ";");
1002 if (name.startsWith("http://")) {
1003 in = new URL(name).openConnection().getInputStream();
1004 } else {
1005 in = new FileInputStream(name);
1006 }
1007 run(name, in, imageInfo, verbose);
1008 in.close();
1009 } catch (IOException e) {
1010 System.out.println(e);
1011 try {
1012 if (in != null) {
1013 in.close();
1014 }
1015 } catch (IOException ee) {
1016 }
1017 }
1018 }
1019 }
1020 }
1021
1022 private static void print(String sourceName, ImageInfo ii, boolean verbose) {
1023 if (verbose) {
1024 printVerbose(sourceName, ii);
1025 } else {
1026 printCompact(sourceName, ii);
1027 }
1028 }
1029
1030 private static void printCompact(String sourceName, ImageInfo imageInfo) {
1031 final String SEP = "\t";
1032 System.out.println(
1033 sourceName + SEP +
1034 imageInfo.getFormatName() + SEP +
1035 imageInfo.getMimeType() + SEP +
1036 imageInfo.getWidth() + SEP +
1037 imageInfo.getHeight() + SEP +
1038 imageInfo.getBitsPerPixel() + SEP +
1039 imageInfo.getNumberOfImages() + SEP +
1040 imageInfo.getPhysicalWidthDpi() + SEP +
1041 imageInfo.getPhysicalHeightDpi() + SEP +
1042 imageInfo.getPhysicalWidthInch() + SEP +
1043 imageInfo.getPhysicalHeightInch() + SEP +
1044 imageInfo.isProgressive()
1045 );
1046 }
1047
1048 private static void printLine(int indentLevels, String text, float value, float minValidValue) {
1049 if (value < minValidValue) {
1050 return;
1051 }
1052 printLine(indentLevels, text, Float.toString(value));
1053 }
1054
1055 private static void printLine(int indentLevels, String text, int value, int minValidValue) {
1056 if (value >= minValidValue) {
1057 printLine(indentLevels, text, Integer.toString(value));
1058 }
1059 }
1060
1061 private static void printLine(int indentLevels, String text, String value) {
1062 if (value == null || value.length() == 0) {
1063 return;
1064 }
1065 while (indentLevels-- > 0) {
1066 System.out.print("\t");
1067 }
1068 if (text != null && text.length() > 0) {
1069 System.out.print(text);
1070 System.out.print(" ");
1071 }
1072 System.out.println(value);
1073 }
1074
1075 private static void printVerbose(String sourceName, ImageInfo ii) {
1076 printLine(0, null, sourceName);
1077 printLine(1, "File format: ", ii.getFormatName());
1078 printLine(1, "MIME type: ", ii.getMimeType());
1079 printLine(1, "Width (pixels): ", ii.getWidth(), 1);
1080 printLine(1, "Height (pixels): ", ii.getHeight(), 1);
1081 printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
1082 printLine(1, "Progressive: ", ii.isProgressive() ? "yes" : "no");
1083 printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
1084 printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
1085 printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
1086 printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
1087 printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f);
1088 int numComments = ii.getNumberOfComments();
1089 printLine(1, "Number of textual comments: ", numComments, 1);
1090 if (numComments > 0) {
1091 for (int i = 0; i < numComments; i++) {
1092 printLine(2, null, ii.getComment(i));
1093 }
1094 }
1095 }
1096
1097 private int read() throws IOException {
1098 if (in != null) {
1099 return in.read();
1100 } else {
1101 return din.readByte();
1102 }
1103 }
1104
1105 private int read(byte[] a) throws IOException {
1106 if (in != null) {
1107 return in.read(a);
1108 } else {
1109 din.readFully(a);
1110 return a.length;
1111 }
1112 }
1113
1114 private int read(byte[] a, int offset, int num) throws IOException {
1115 if (in != null) {
1116 return in.read(a, offset, num);
1117 } else {
1118 din.readFully(a, offset, num);
1119 return num;
1120 }
1121 }
1122
1123 private String readLine() throws IOException {
1124 return readLine(new StringBuffer());
1125 }
1126
1127 private String readLine(StringBuffer sb) throws IOException {
1128 boolean finished;
1129 do {
1130 int value = read();
1131 finished = (value == -1 || value == 10);
1132 if (!finished) {
1133 sb.append((char)value);
1134 }
1135 } while (!finished);
1136 return sb.toString();
1137 }
1138
1139 private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean verbose) {
1140 imageInfo.setInput(in);
1141 imageInfo.setDetermineImageNumber(true);
1142 imageInfo.setCollectComments(verbose);
1143 if (imageInfo.check()) {
1144 print(sourceName, imageInfo, verbose);
1145 }
1146 }
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 public void setCollectComments(boolean newValue)
1157 {
1158 collectComments = newValue;
1159 }
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175 public void setDetermineImageNumber(boolean newValue)
1176 {
1177 determineNumberOfImages = newValue;
1178 }
1179
1180
1181
1182
1183
1184
1185
1186 public void setInput(DataInput dataInput) {
1187 din = dataInput;
1188 in = null;
1189 }
1190
1191
1192
1193
1194
1195 public void setInput(InputStream inputStream) {
1196 in = inputStream;
1197 din = null;
1198 }
1199
1200 private void setPhysicalHeightDpi(int newValue) {
1201 physicalWidthDpi = newValue;
1202 }
1203
1204 private void setPhysicalWidthDpi(int newValue) {
1205 physicalHeightDpi = newValue;
1206 }
1207
1208 private void skip(int num) throws IOException {
1209 while (num > 0) {
1210 long result;
1211 if (in != null) {
1212 result = in.skip(num);
1213 } else {
1214 result = din.skipBytes(num);
1215 }
1216 if (result > 0) {
1217 num -= result;
1218 } else {
1219 if (in != null) {
1220 result = in.read();
1221 } else {
1222 result = din.readByte();
1223 }
1224 if (result == -1) {
1225 throw new IOException("Premature end of input.");
1226 } else {
1227 num--;
1228 }
1229 }
1230 }
1231 }
1232 }