1 16 17 package org.mmbase.util.images; 18 import java.io.DataInput ; 19 import java.io.FileInputStream ; 20 import java.io.InputStream ; 21 import java.io.IOException ; 22 import java.net.URL ; 23 import java.util.Vector ; 24 25 124 public class ImageInfo { 125 133 public static final int FORMAT_JPEG = 0; 134 135 144 public static final int FORMAT_GIF = 1; 145 146 153 public static final int FORMAT_PNG = 2; 154 155 161 public static final int FORMAT_BMP = 3; 162 163 168 public static final int FORMAT_PCX = 4; 169 170 173 public static final int FORMAT_IFF = 5; 174 175 180 public static final int FORMAT_RAS = 6; 181 182 183 public static final int FORMAT_PBM = 7; 184 185 186 public static final int FORMAT_PGM = 8; 187 188 189 public static final int FORMAT_PPM = 9; 190 191 192 public static final int FORMAT_PSD = 10; 193 194 195 public static final int FORMAT_SWF = 11; 196 197 public static final int COLOR_TYPE_UNKNOWN = -1; 198 public static final int COLOR_TYPE_TRUECOLOR_RGB = 0; 199 public static final int COLOR_TYPE_PALETTED = 1; 200 public static final int COLOR_TYPE_GRAYSCALE= 2; 201 public static final int COLOR_TYPE_BLACK_AND_WHITE = 3; 202 203 208 private static final String [] FORMAT_NAMES = 209 {"JPEG", "GIF", "PNG", "BMP", "PCX", 210 "IFF", "RAS", "PBM", "PGM", "PPM", 211 "PSD", "SWF"}; 212 213 218 private static final String [] MIME_TYPE_STRINGS = 219 {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx", 220 "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", 221 "image/psd", "application/x-shockwave-flash"}; 222 223 private int width; 224 private int height; 225 private int bitsPerPixel; 226 private int colorType = COLOR_TYPE_UNKNOWN; 227 private boolean progressive; 228 private int format; 229 private InputStream in; 230 private DataInput din; 231 private boolean collectComments = true; 232 private Vector comments; 233 private boolean determineNumberOfImages; 234 private int numberOfImages; 235 private int physicalHeightDpi; 236 private int physicalWidthDpi; 237 private int bitBuf; 238 private int bitPos; 239 240 private void addComment(String s) { 241 if (comments == null) { 242 comments = new Vector (); 243 } 244 comments.addElement(s); 245 } 246 247 254 public boolean check() { 255 format = -1; 256 width = -1; 257 height = -1; 258 bitsPerPixel = -1; 259 numberOfImages = 1; 260 physicalHeightDpi = -1; 261 physicalWidthDpi = -1; 262 comments = null; 263 try { 264 int b1 = read() & 0xff; 265 int b2 = read() & 0xff; 266 if (b1 == 0x47 && b2 == 0x49) { 267 return checkGif(); 268 } 269 else 270 if (b1 == 0x89 && b2 == 0x50) { 271 return checkPng(); 272 } 273 else 274 if (b1 == 0xff && b2 == 0xd8) { 275 return checkJpeg(); 276 } 277 else 278 if (b1 == 0x42 && b2 == 0x4d) { 279 return checkBmp(); 280 } 281 else 282 if (b1 == 0x0a && b2 < 0x06) { 283 return checkPcx(); 284 } 285 else 286 if (b1 == 0x46 && b2 == 0x4f) { 287 return checkIff(); 288 } 289 else 290 if (b1 == 0x59 && b2 == 0xa6) { 291 return checkRas(); 292 } 293 else 294 if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) { 295 return checkPnm(b2 - '0'); 296 } 297 else 298 if (b1 == 0x38 && b2 == 0x42) { 299 return checkPsd(); 300 } 301 else 302 if (b1 == 0x46 && b2 == 0x57) { 303 return checkSwf(); 304 } 305 else { 306 return false; 307 } 308 } catch (IOException ioe) { 309 return false; 310 } 311 } 312 313 private boolean checkBmp() throws IOException { 314 byte[] a = new byte[44]; 315 if (read(a) != a.length) { 316 return false; 317 } 318 width = getIntLittleEndian(a, 16); 319 height = getIntLittleEndian(a, 20); 320 if (width < 1 || height < 1) { 321 return false; 322 } 323 bitsPerPixel = getShortLittleEndian(a, 26); 324 if (bitsPerPixel != 1 && bitsPerPixel != 4 && 325 bitsPerPixel != 8 && bitsPerPixel != 16 && 326 bitsPerPixel != 24 && bitsPerPixel != 32) { 327 return false; 328 } 329 int x = (int)(getIntLittleEndian(a, 36) * 0.0254); 330 if (x > 0) { 331 setPhysicalWidthDpi(x); 332 } 333 int y = (int)(getIntLittleEndian(a, 40) * 0.0254); 334 if (y > 0) { 335 setPhysicalHeightDpi(y); 336 } 337 format = FORMAT_BMP; 338 return true; 339 } 340 341 private boolean checkGif() throws IOException { 342 final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61}; 343 final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61}; 344 byte[] a = new byte[11]; if (read(a) != 11) { 346 return false; 347 } 348 if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) && 349 (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) { 350 return false; 351 } 352 format = FORMAT_GIF; 353 width = getShortLittleEndian(a, 4); 354 height = getShortLittleEndian(a, 6); 355 int flags = a[8] & 0xff; 356 bitsPerPixel = ((flags >> 4) & 0x07) + 1; 357 progressive = (flags & 0x02) != 0; 358 if (!determineNumberOfImages) { 359 return true; 360 } 361 if ((flags & 0x80) != 0) { 363 int tableSize = (1 << ((flags & 7) + 1)) * 3; 364 skip(tableSize); 365 } 366 numberOfImages = 0; 367 int blockType; 368 do 369 { 370 blockType = read(); 371 switch(blockType) 372 { 373 case(0x2c): { 375 if (read(a, 0, 9) != 9) { 376 return false; 377 } 378 flags = a[8] & 0xff; 379 int localBitsPerPixel = (flags & 0x07) + 1; 380 if (localBitsPerPixel > bitsPerPixel) { 381 bitsPerPixel = localBitsPerPixel; 382 } 383 if ((flags & 0x80) != 0) { 384 skip((1 << localBitsPerPixel) * 3); 385 } 386 skip(1); int n; 388 do 389 { 390 n = read(); 391 if (n > 0) { 392 skip(n); 393 } 394 else 395 if (n == -1) { 396 return false; 397 } 398 } 399 while (n > 0); 400 numberOfImages++; 401 break; 402 } 403 case(0x21): { 405 int extensionType = read(); 406 if (collectComments && extensionType == 0xfe) { 407 StringBuffer sb = new StringBuffer (); 408 int n; 409 do 410 { 411 n = read(); 412 if (n == -1) { 413 return false; 414 } 415 if (n > 0) { 416 for (int i = 0; i < n; i++) { 417 int ch = read(); 418 if (ch == -1) { 419 return false; 420 } 421 sb.append((char)ch); 422 } 423 } 424 } 425 while (n > 0); 426 } else { 427 int n; 428 do 429 { 430 n = read(); 431 if (n > 0) { 432 skip(n); 433 } 434 else 435 if (n == -1) { 436 return false; 437 } 438 } 439 while (n > 0); 440 } 441 break; 442 } 443 case(0x3b): { 445 break; 446 } 447 default: 448 { 449 return false; 450 } 451 } 452 } 453 while (blockType != 0x3b); 454 return true; 455 } 456 457 private boolean checkIff() throws IOException { 458 byte[] a = new byte[10]; 459 if (read(a, 0, 10) != 10) { 462 return false; 463 } 464 final byte[] IFF_RM = {0x52, 0x4d}; 465 if (!equals(a, 0, IFF_RM, 0, 2)) { 466 return false; 467 } 468 int type = getIntBigEndian(a, 6); 469 if (type != 0x494c424d && type != 0x50424d20) { return false; 472 } 473 do { 475 if (read(a, 0, 8) != 8) { 476 return false; 477 } 478 int chunkId = getIntBigEndian(a, 0); 479 int size = getIntBigEndian(a, 4); 480 if ((size & 1) == 1) { 481 size++; 482 } 483 if (chunkId == 0x424d4844) { if (read(a, 0, 9) != 9) { 485 return false; 486 } 487 format = FORMAT_IFF; 488 width = getShortBigEndian(a, 0); 489 height = getShortBigEndian(a, 2); 490 bitsPerPixel = a[8] & 0xff; 491 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33); 492 } else { 493 skip(size); 494 } 495 } while (true); 496 } 497 498 private boolean checkJpeg() throws IOException { 499 byte[] data = new byte[12]; 500 while (true) { 501 if (read(data, 0, 4) != 4) { 502 return false; 503 } 504 int marker = getShortBigEndian(data, 0); 505 int size = getShortBigEndian(data, 2); 506 if ((marker & 0xff00) != 0xff00) { 507 return false; } 509 if (marker == 0xffe0) { if (size < 14) { 511 return false; } 513 if (read(data, 0, 12) != 12) { 514 return false; 515 } 516 final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00}; 517 if (equals(APP0_ID, 0, data, 0, 5)) { 518 if (data[7] == 1) { 520 setPhysicalWidthDpi(getShortBigEndian(data, 8)); 521 setPhysicalHeightDpi(getShortBigEndian(data, 10)); 522 } 523 else 524 if (data[7] == 2) { 525 int x = getShortBigEndian(data, 8); 526 int y = getShortBigEndian(data, 10); 527 setPhysicalWidthDpi((int)(x * 2.54f)); 528 setPhysicalHeightDpi((int)(y * 2.54f)); 529 } 530 } 531 skip(size - 14); 532 } 533 else 534 if (collectComments && size > 2 && marker == 0xfffe) { size -= 2; 536 byte[] chars = new byte[size]; 537 if (read(chars, 0, size) != size) { 538 return false; 539 } 540 String comment = new String (chars, "iso-8859-1"); 541 comment = comment.trim(); 542 addComment(comment); 543 } 544 else 545 if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) { 546 if (read(data, 0, 6) != 6) { 547 return false; 548 } 549 format = FORMAT_JPEG; 550 bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff); 551 progressive = marker == 0xffc2 || marker == 0xffc6 || 552 marker == 0xffca || marker == 0xffce; 553 width = getShortBigEndian(data, 3); 554 height = getShortBigEndian(data, 1); 555 return true; 556 } else { 557 skip(size - 2); 558 } 559 } 560 } 561 562 private boolean checkPcx() throws IOException { 563 byte[] a = new byte[64]; 564 if (read(a) != a.length) { 565 return false; 566 } 567 if (a[0] != 1) { return false; 569 } 570 int x1 = getShortLittleEndian(a, 2); 572 int y1 = getShortLittleEndian(a, 4); 573 int x2 = getShortLittleEndian(a, 6); 574 int y2 = getShortLittleEndian(a, 8); 575 if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) { 576 return false; 577 } 578 width = x2 - x1 + 1; 579 height = y2 - y1 + 1; 580 int bits = a[1]; 582 int planes = a[63]; 583 if (planes == 1 && 584 (bits == 1 || bits == 2 || bits == 4 || bits == 8)) { 585 bitsPerPixel = bits; 587 } else 588 if (planes == 3 && bits == 8) { 589 bitsPerPixel = 24; 591 } else { 592 return false; 593 } 594 setPhysicalWidthDpi(getShortLittleEndian(a, 10)); 595 setPhysicalHeightDpi(getShortLittleEndian(a, 10)); 596 format = FORMAT_PCX; 597 return true; 598 } 599 600 private boolean checkPng() throws IOException { 601 final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; 602 byte[] a = new byte[27]; 603 if (read(a) != 27) { 604 return false; 605 } 606 if (!equals(a, 0, PNG_MAGIC, 0, 6)) { 607 return false; 608 } 609 format = FORMAT_PNG; 610 width = getIntBigEndian(a, 14); 611 height = getIntBigEndian(a, 18); 612 bitsPerPixel = a[22] & 0xff; 613 int colorType = a[23] & 0xff; 614 if (colorType == 2 || colorType == 6) { 615 bitsPerPixel *= 3; 616 } 617 progressive = (a[26] & 0xff) != 0; 618 return true; 619 } 620 621 private boolean checkPnm(int id) throws IOException { 622 if (id < 1 || id > 6) { 623 return false; 624 } 625 final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM}; 626 format = PNM_FORMATS[(id - 1) % 3]; 627 boolean hasPixelResolution = false; 628 String s; 629 while (true) { 630 s = readLine(); 631 if (s != null) { 632 s = s.trim(); 633 } 634 if (s == null || s.length() < 1) { 635 continue; 636 } 637 if (s.charAt(0) == '#') { if (collectComments && s.length() > 1) { 639 addComment(s.substring(1)); 640 } 641 continue; 642 } 643 if (!hasPixelResolution) { int spaceIndex = s.indexOf(' '); 645 if (spaceIndex == -1) { 646 return false; 647 } 648 String widthString = s.substring(0, spaceIndex); 649 spaceIndex = s.lastIndexOf(' '); 650 if (spaceIndex == -1) { 651 return false; 652 } 653 String heightString = s.substring(spaceIndex + 1); 654 try { 655 width = Integer.parseInt(widthString); 656 height = Integer.parseInt(heightString); 657 } catch (NumberFormatException nfe) { 658 return false; 659 } 660 if (width < 1 || height < 1) { 661 return false; 662 } 663 if (format == FORMAT_PBM) { 664 bitsPerPixel = 1; 665 return true; 666 } 667 hasPixelResolution = true; 668 } 669 else 670 { 671 int maxSample; 672 try { 673 maxSample = Integer.parseInt(s); 674 } catch (NumberFormatException nfe) { 675 return false; 676 } 677 if (maxSample < 0) { 678 return false; 679 } 680 for (int i = 0; i < 25; i++) { 681 if (maxSample < (1 << (i + 1))) { 682 bitsPerPixel = i + 1; 683 if (format == FORMAT_PPM) { 684 bitsPerPixel *= 3; 685 } 686 return true; 687 } 688 } 689 return false; 690 } 691 } 692 } 693 694 private boolean checkPsd() throws IOException { 695 byte[] a = new byte[24]; 696 if (read(a) != a.length) { 697 return false; 698 } 699 final byte[] PSD_MAGIC = {0x50, 0x53}; 700 if (!equals(a, 0, PSD_MAGIC, 0, 2)) { 701 return false; 702 } 703 format = FORMAT_PSD; 704 width = getIntBigEndian(a, 16); 705 height = getIntBigEndian(a, 12); 706 int channels = getShortBigEndian(a, 10); 707 int depth = getShortBigEndian(a, 20); 708 bitsPerPixel = channels * depth; 709 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64); 710 } 711 712 private boolean checkRas() throws IOException { 713 byte[] a = new byte[14]; 714 if (read(a) != a.length) { 715 return false; 716 } 717 final byte[] RAS_MAGIC = {0x6a, (byte)0x95}; 718 if (!equals(a, 0, RAS_MAGIC, 0, 2)) { 719 return false; 720 } 721 format = FORMAT_RAS; 722 width = getIntBigEndian(a, 2); 723 height = getIntBigEndian(a, 6); 724 bitsPerPixel = getIntBigEndian(a, 10); 725 return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24); 726 } 727 728 private boolean checkSwf() throws IOException { 730 byte[] a = new byte[6]; 732 if (read(a) != a.length) { 733 return false; 734 } 735 format = FORMAT_SWF; 736 int bitSize = (int)readUBits( 5 ); 737 int minX = (int)readSBits( bitSize ); 738 int maxX = (int)readSBits( bitSize ); 739 int minY = (int)readSBits( bitSize ); 740 int maxY = (int)readSBits( bitSize ); 741 width = maxX/20; height = maxY/20; setPhysicalWidthDpi(72); 744 setPhysicalHeightDpi(72); 745 return (width > 0 && height > 0); 746 } 747 748 752 private static boolean determineVerbosity(String [] args) { 753 if (args != null && args.length > 0) { 754 for (int i = 0; i < args.length; i++) { 755 if ("-c".equals(args[i])) { 756 return false; 757 } 758 } 759 } 760 return true; 761 } 762 763 private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) { 764 while (num-- > 0) { 765 if (a1[offs1++] != a2[offs2++]) { 766 return false; 767 } 768 } 769 return true; 770 } 771 772 777 public int getBitsPerPixel() { 778 return bitsPerPixel; 779 } 780 781 787 public String getComment(int index) { 788 if (comments == null || index < 0 || index >= comments.size()) { 789 throw new IllegalArgumentException ("Not a valid comment index: " + index); 790 } 791 return (String )comments.elementAt(index); 792 } 793 794 800 public int getFormat() { 801 return format; 802 } 803 804 809 public String getFormatName() { 810 if (format >= 0 && format < FORMAT_NAMES.length) { 811 return FORMAT_NAMES[format]; 812 } else { 813 return "?"; 814 } 815 } 816 817 822 public int getHeight() { 823 return height; 824 } 825 826 private int getIntBigEndian(byte[] a, int offs) { 827 return 828 (a[offs] & 0xff) << 24 | 829 (a[offs + 1] & 0xff) << 16 | 830 (a[offs + 2] & 0xff) << 8 | 831 a[offs + 3] & 0xff; 832 } 833 834 private int getIntLittleEndian(byte[] a, int offs) { 835 return 836 (a[offs + 3] & 0xff) << 24 | 837 (a[offs + 2] & 0xff) << 16 | 838 (a[offs + 1] & 0xff) << 8 | 839 a[offs] & 0xff; 840 } 841 842 847 public String getMimeType() { 848 if (format >= 0 && format < MIME_TYPE_STRINGS.length) { 849 if (format == FORMAT_JPEG && progressive) 850 { 851 return "image/pjpeg"; 852 } 853 return MIME_TYPE_STRINGS[format]; 854 } else { 855 return null; 856 } 857 } 858 859 867 public int getNumberOfComments() 868 { 869 if (comments == null) { 870 return 0; 871 } else { 872 return comments.size(); 873 } 874 } 875 876 883 public int getNumberOfImages() 884 { 885 return numberOfImages; 886 } 887 888 896 public int getPhysicalHeightDpi() { 897 return physicalHeightDpi; 898 } 899 900 908 public float getPhysicalHeightInch() { 909 int h = getHeight(); 910 int ph = getPhysicalHeightDpi(); 911 if (h > 0 && ph > 0) { 912 return ((float)h) / ((float)ph); 913 } else { 914 return -1.0f; 915 } 916 } 917 918 926 public int getPhysicalWidthDpi() { 927 return physicalWidthDpi; 928 } 929 930 938 public float getPhysicalWidthInch() { 939 int w = getWidth(); 940 int pw = getPhysicalWidthDpi(); 941 if (w > 0 && pw > 0) { 942 return ((float)w) / ((float)pw); 943 } else { 944 return -1.0f; 945 } 946 } 947 948 private int getShortBigEndian(byte[] a, int offs) { 949 return 950 (a[offs] & 0xff) << 8 | 951 (a[offs + 1] & 0xff); 952 } 953 954 private int getShortLittleEndian(byte[] a, int offs) { 955 return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8; 956 } 957 958 963 public int getWidth() { 964 return width; 965 } 966 967 971 public boolean isProgressive() 972 { 973 return progressive; 974 } 975 976 984 public static void main(String [] args) { 985 ImageInfo imageInfo = new ImageInfo(); 986 imageInfo.setDetermineImageNumber(true); 987 boolean verbose = determineVerbosity(args); 988 if (args.length == 0) { 989 run(null, System.in, imageInfo, verbose); 990 } else { 991 int index = 0; 992 while (index < args.length) { 993 InputStream in = null; 994 try { 995 String name = args[index++]; 996 System.out.print(name + ";"); 997 if (name.startsWith("http://")) { 998 in = new URL (name).openConnection().getInputStream(); 999 } else { 1000 in = new FileInputStream (name); 1001 } 1002 run(name, in, imageInfo, verbose); 1003 in.close(); 1004 } catch (Exception e) { 1005 System.out.println(e); 1006 try { 1007 in.close(); 1008 } catch (Exception ee) { 1009 } 1010 } 1011 } 1012 } 1013 } 1014 1015 private static void print(String sourceName, ImageInfo ii, boolean verbose) { 1016 if (verbose) { 1017 printVerbose(sourceName, ii); 1018 } else { 1019 printCompact(sourceName, ii); 1020 } 1021 } 1022 1023 private static void printCompact(String sourceName, ImageInfo imageInfo) { 1024 System.out.println( 1025 imageInfo.getFormatName() + ";" + 1026 imageInfo.getMimeType() + ";" + 1027 imageInfo.getWidth() + ";" + 1028 imageInfo.getHeight() + ";" + 1029 imageInfo.getBitsPerPixel() + ";" + 1030 imageInfo.getNumberOfImages() + ";" + 1031 imageInfo.getPhysicalWidthDpi() + ";" + 1032 imageInfo.getPhysicalHeightDpi() + ";" + 1033 imageInfo.getPhysicalWidthInch() + ";" + 1034 imageInfo.getPhysicalHeightInch() + ";" + 1035 imageInfo.isProgressive() 1036 ); 1037 } 1038 1039 private static void printLine(int indentLevels, String text, float value, float minValidValue) { 1040 if (value < minValidValue) { 1041 return; 1042 } 1043 printLine(indentLevels, text, Float.toString(value)); 1044 } 1045 1046 private static void printLine(int indentLevels, String text, int value, int minValidValue) { 1047 if (value >= minValidValue) { 1048 printLine(indentLevels, text, Integer.toString(value)); 1049 } 1050 } 1051 1052 private static void printLine(int indentLevels, String text, String value) { 1053 if (value == null || value.length() == 0) { 1054 return; 1055 } 1056 while (indentLevels-- > 0) { 1057 System.out.print("\t"); 1058 } 1059 if (text != null && text.length() > 0) { 1060 System.out.print(text); 1061 System.out.print(" "); 1062 } 1063 System.out.println(value); 1064 } 1065 1066 private static void printVerbose(String sourceName, ImageInfo ii) { 1067 printLine(0, null, sourceName); 1068 printLine(1, "File format: ", ii.getFormatName()); 1069 printLine(1, "MIME type: ", ii.getMimeType()); 1070 printLine(1, "Width (pixels): ", ii.getWidth(), 1); 1071 printLine(1, "Height (pixels): ", ii.getHeight(), 1); 1072 printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1); 1073 printLine(1, "Progressive: ", Boolean.toString(ii.isProgressive())); 1074 printLine(1, "Number of images: ", ii.getNumberOfImages(), 1); 1075 printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1); 1076 printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1); 1077 printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f); 1078 printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f); 1079 int numComments = ii.getNumberOfComments(); 1080 printLine(1, "Number of textual comments: ", numComments, 1); 1081 if (numComments > 0) { 1082 for (int i = 0; i < numComments; i++) { 1083 printLine(2, null, ii.getComment(i)); 1084 } 1085 } 1086 } 1087 1088 private int read() throws IOException { 1089 if (in != null) { 1090 return in.read(); 1091 } else { 1092 return din.readByte(); 1093 } 1094 } 1095 1096 private int read(byte[] a) throws IOException { 1097 if (in != null) { 1098 return in.read(a); 1099 } else { 1100 din.readFully(a); 1101 return a.length; 1102 } 1103 } 1104 1105 private int read(byte[] a, int offset, int num) throws IOException { 1106 if (in != null) { 1107 return in.read(a, offset, num); 1108 } else { 1109 din.readFully(a, offset, num); 1110 return num; 1111 } 1112 } 1113 1114 private String readLine() throws IOException { 1115 return readLine(new StringBuffer ()); 1116 } 1117 1118 private String readLine(StringBuffer sb) throws IOException { 1119 boolean finished; 1120 do { 1121 int value = read(); 1122 finished = (value == -1 || value == 10); 1123 if (!finished) { 1124 sb.append((char)value); 1125 } 1126 } while (!finished); 1127 return sb.toString(); 1128 } 1129 1130 private long readUBits( int numBits ) throws IOException 1131 { 1132 if (numBits == 0) { 1133 return 0; 1134 } 1135 int bitsLeft = numBits; 1136 long result = 0; 1137 if (bitPos == 0) { if (in != null) { 1139 bitBuf = in.read(); 1140 } else { 1141 bitBuf = din.readByte(); 1142 } 1143 bitPos = 8; 1144 } 1145 1146 while( true ) 1147 { 1148 int shift = bitsLeft - bitPos; 1149 if( shift > 0 ) 1150 { 1151 result |= bitBuf << shift; 1153 bitsLeft -= bitPos; 1154 1155 if (in != null) { 1157 bitBuf = in.read(); 1158 } else { 1159 bitBuf = din.readByte(); 1160 } 1161 bitPos = 8; 1162 } 1163 else 1164 { 1165 result |= bitBuf >> -shift; 1167 bitPos -= bitsLeft; 1168 bitBuf &= 0xff >> (8 - bitPos); 1170 return result; 1171 } 1172 } 1173 } 1174 1175 1178 private int readSBits( int numBits ) throws IOException 1179 { 1180 long uBits = readUBits( numBits ); 1182 1183 if( ( uBits & (1L << (numBits - 1))) != 0 ) 1185 { 1186 uBits |= -1L << numBits; 1188 } 1189 1190 return (int)uBits; 1191 } 1192 1193 private void synchBits() 1194 { 1195 bitBuf = 0; 1196 bitPos = 0; 1197 } 1198 1199 private String readLine(int firstChar) throws IOException { 1200 StringBuffer result = new StringBuffer (); 1201 result.append((char)firstChar); 1202 return readLine(result); 1203 } 1204 1205 private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean verbose) { 1206 imageInfo.setInput(in); 1207 imageInfo.setDetermineImageNumber(false); 1208 imageInfo.setCollectComments(verbose); 1209 if (imageInfo.check()) { 1210 print(sourceName, imageInfo, verbose); 1211 } 1212 } 1213 1214 1222 public void setCollectComments(boolean newValue) 1223 { 1224 collectComments = newValue; 1225 } 1226 1227 1241 public void setDetermineImageNumber(boolean newValue) 1242 { 1243 determineNumberOfImages = newValue; 1244 } 1245 1246 1252 public void setInput(DataInput dataInput) { 1253 din = dataInput; 1254 in = null; 1255 } 1256 1257 1261 public void setInput(InputStream inputStream) { 1262 in = inputStream; 1263 din = null; 1264 } 1265 1266 private void setPhysicalHeightDpi(int newValue) { 1267 physicalWidthDpi = newValue; 1268 } 1269 1270 private void setPhysicalWidthDpi(int newValue) { 1271 physicalHeightDpi = newValue; 1272 } 1273 1274 private void skip(int num) throws IOException { 1275 while (num > 0) { 1276 long result; 1277 if (in != null) { 1278 result = in.skip(num); 1279 } else { 1280 result = din.skipBytes(num); 1281 } 1282 if (result > 0) { 1283 num -= result; 1284 } 1285 } 1286 } 1287} 1288 | Popular Tags |