Changeset 13061 in josm for trunk/src/com/drew/metadata
- Timestamp:
- 2017-10-30T22:46:09+01:00 (7 years ago)
- Location:
- trunk/src/com/drew/metadata
- Files:
-
- 45 added
- 7 deleted
- 74 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/drew/metadata/Age.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 51 51 public static Age fromPanasonicString(@NotNull String s) 52 52 { 53 if (s == null)54 throw new NullPointerException();55 56 53 if (s.length() != 19 || s.startsWith("9999:99:99")) 57 54 return null; … … 143 140 144 141 @Override 145 public boolean equals( Object o)142 public boolean equals(@Nullable Object o) 146 143 { 147 144 if (this == o) return true; -
trunk/src/com/drew/metadata/Directory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 24 24 import com.drew.lang.annotations.NotNull; 25 25 import com.drew.lang.annotations.Nullable; 26 import com.drew.lang.annotations.SuppressWarnings; 26 27 27 28 import java.io.UnsupportedEncodingException; … … 41 42 * @author Drew Noakes https://drewnoakes.com 42 43 */ 44 @java.lang.SuppressWarnings("WeakerAccess") 43 45 public abstract class Directory 44 46 { 45 private static final DecimalFormat _floatFormat = new DecimalFormat("0.###");47 private static final String _floatFormatPattern = "0.###"; 46 48 47 49 /** Map of values hashed by type identifiers. */ … … 260 262 261 263 /** 264 * Sets a <code>StringValue</code> value for the specified tag. 265 * 266 * @param tagType the tag's value as an int 267 * @param value the value for the specified tag as a StringValue 268 */ 269 @java.lang.SuppressWarnings({ "ConstantConditions" }) 270 public void setStringValue(int tagType, @NotNull StringValue value) 271 { 272 if (value == null) 273 throw new NullPointerException("cannot set a null StringValue"); 274 setObject(tagType, value); 275 } 276 277 /** 262 278 * Sets a <code>String</code> value for the specified tag. 263 279 * … … 280 296 */ 281 297 public void setStringArray(int tagType, @NotNull String[] strings) 298 { 299 setObjectArray(tagType, strings); 300 } 301 302 /** 303 * Sets a <code>StringValue[]</code> (array) for the specified tag. 304 * 305 * @param tagType the tag identifier 306 * @param strings the StringValue array to store 307 */ 308 public void setStringValueArray(int tagType, @NotNull StringValue[] strings) 282 309 { 283 310 setObjectArray(tagType, strings); … … 440 467 if (o instanceof Number) { 441 468 return ((Number)o).intValue(); 442 } else if (o instanceof String ) {469 } else if (o instanceof String || o instanceof StringValue) { 443 470 try { 444 return Integer.parseInt( (String)o);471 return Integer.parseInt(o.toString()); 445 472 } catch (NumberFormatException nfe) { 446 473 // convert the char array to an int 447 String s = (String)o;474 String s = o.toString(); 448 475 byte[] bytes = s.getBytes(); 449 476 long val = 0; … … 466 493 if (ints.length == 1) 467 494 return ints[0]; 495 } else if (o instanceof short[]) { 496 short[] shorts = (short[])o; 497 if (shorts.length == 1) 498 return (int)shorts[0]; 468 499 } 469 500 return null; … … 472 503 /** 473 504 * Gets the specified tag's value as a String array, if possible. Only supported 474 * where the tag is set as String [], String, int[], byte[] or Rational[].505 * where the tag is set as StringValue[], String[], StringValue, String, int[], byte[] or Rational[]. 475 506 * 476 507 * @param tagType the tag identifier … … 487 518 if (o instanceof String) 488 519 return new String[] { (String)o }; 520 if (o instanceof StringValue) 521 return new String[] { o.toString() }; 522 if (o instanceof StringValue[]) { 523 StringValue[] stringValues = (StringValue[])o; 524 String[] strings = new String[stringValues.length]; 525 for (int i = 0; i < strings.length; i++) 526 strings[i] = stringValues[i].toString(); 527 return strings; 528 } 489 529 if (o instanceof int[]) { 490 530 int[] ints = (int[])o; … … 493 533 strings[i] = Integer.toString(ints[i]); 494 534 return strings; 495 } else if (o instanceof byte[]) { 535 } 536 if (o instanceof byte[]) { 496 537 byte[] bytes = (byte[])o; 497 538 String[] strings = new String[bytes.length]; … … 499 540 strings[i] = Byte.toString(bytes[i]); 500 541 return strings; 501 } else if (o instanceof Rational[]) { 542 } 543 if (o instanceof Rational[]) { 502 544 Rational[] rationals = (Rational[])o; 503 545 String[] strings = new String[rationals.length]; … … 506 548 return strings; 507 549 } 550 return null; 551 } 552 553 /** 554 * Gets the specified tag's value as a StringValue array, if possible. 555 * Only succeeds if the tag is set as StringValue[], or StringValue. 556 * 557 * @param tagType the tag identifier 558 * @return the tag's value as an array of StringValues. If the value is unset or cannot be converted, <code>null</code> is returned. 559 */ 560 @Nullable 561 public StringValue[] getStringValueArray(int tagType) 562 { 563 Object o = getObject(tagType); 564 if (o == null) 565 return null; 566 if (o instanceof StringValue[]) 567 return (StringValue[])o; 568 if (o instanceof StringValue) 569 return new StringValue[] {(StringValue) o}; 508 570 return null; 509 571 } … … 575 637 if (o == null) { 576 638 return null; 639 } else if (o instanceof StringValue) { 640 return ((StringValue)o).getBytes(); 577 641 } else if (o instanceof Rational[]) { 578 642 Rational[] rationals = (Rational[])o; … … 630 694 if (o == null) 631 695 return null; 632 if (o instanceof String ) {696 if (o instanceof String || o instanceof StringValue) { 633 697 try { 634 return Double.parseDouble( (String)o);698 return Double.parseDouble(o.toString()); 635 699 } catch (NumberFormatException nfe) { 636 700 return null; … … 662 726 if (o == null) 663 727 return null; 664 if (o instanceof String ) {728 if (o instanceof String || o instanceof StringValue) { 665 729 try { 666 return Float.parseFloat( (String)o);730 return Float.parseFloat(o.toString()); 667 731 } catch (NumberFormatException nfe) { 668 732 return null; … … 678 742 { 679 743 Long value = getLongObject(tagType); 680 if (value !=null)744 if (value != null) 681 745 return value; 682 746 Object o = getObject(tagType); … … 693 757 if (o == null) 694 758 return null; 695 if (o instanceof String ) {759 if (o instanceof String || o instanceof StringValue) { 696 760 try { 697 return Long.parseLong( (String)o);761 return Long.parseLong(o.toString()); 698 762 } catch (NumberFormatException nfe) { 699 763 return null; … … 709 773 { 710 774 Boolean value = getBooleanObject(tagType); 711 if (value !=null)775 if (value != null) 712 776 return value; 713 777 Object o = getObject(tagType); … … 719 783 /** Returns the specified tag's value as a boolean. If the tag is not set or cannot be converted, <code>null</code> is returned. */ 720 784 @Nullable 785 @SuppressWarnings(value = "NP_BOOLEAN_RETURN_NULL", justification = "keep API interface consistent") 721 786 public Boolean getBooleanObject(int tagType) 722 787 { … … 726 791 if (o instanceof Boolean) 727 792 return (Boolean)o; 728 if (o instanceof String ) {793 if (o instanceof String || o instanceof StringValue) { 729 794 try { 730 return Boolean.getBoolean( (String)o);795 return Boolean.getBoolean(o.toString()); 731 796 } catch (NumberFormatException nfe) { 732 797 return null; … … 788 853 java.util.Date date = null; 789 854 790 if ( o instanceof String) {855 if ((o instanceof String) || (o instanceof StringValue)) { 791 856 // This seems to cover all known Exif and Xmp date strings 792 857 // Note that " : : : : " is a valid date string according to the Exif spec (which means 'unknown date'): http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/datetimeoriginal.html … … 802 867 "yyyy-MM-dd", 803 868 "yyyy-MM", 869 "yyyyMMdd", // as used in IPTC data 804 870 "yyyy" }; 805 String dateString = (String)o; 871 872 String dateString = o.toString(); 806 873 807 874 // if the date string has subsecond information, it supersedes the subsecond parameter … … 945 1012 if (i != 0) 946 1013 string.append(' '); 947 string.append( _floatFormat.format(Array.getFloat(o, i)));1014 string.append(new DecimalFormat(_floatFormatPattern).format(Array.getFloat(o, i))); 948 1015 } 949 1016 } else if (componentType.getName().equals("double")) { … … 951 1018 if (i != 0) 952 1019 string.append(' '); 953 string.append( _floatFormat.format(Array.getDouble(o, i)));1020 string.append(new DecimalFormat(_floatFormatPattern).format(Array.getDouble(o, i))); 954 1021 } 955 1022 } else if (componentType.getName().equals("byte")) { … … 967 1034 968 1035 if (o instanceof Double) 969 return _floatFormat.format(((Double)o).doubleValue());1036 return new DecimalFormat(_floatFormatPattern).format(((Double)o).doubleValue()); 970 1037 971 1038 if (o instanceof Float) 972 return _floatFormat.format(((Float)o).floatValue());1039 return new DecimalFormat(_floatFormatPattern).format(((Float)o).floatValue()); 973 1040 974 1041 // Note that several cameras leave trailing spaces (Olympus, Nikon) but this library is intended to show … … 990 1057 return null; 991 1058 } 1059 } 1060 1061 @Nullable 1062 public StringValue getStringValue(int tagType) 1063 { 1064 Object o = getObject(tagType); 1065 if (o instanceof StringValue) 1066 return (StringValue)o; 1067 return null; 992 1068 } 993 1069 -
trunk/src/com/drew/metadata/Face.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/metadata/Metadata.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 53 53 } 54 54 55 @N ullable55 @NotNull 56 56 @SuppressWarnings("unchecked") 57 57 public <T extends Directory> Collection<T> getDirectoriesOfType(Class<T> type) -
trunk/src/com/drew/metadata/MetadataException.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/metadata/Tag.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 30 30 * @author Drew Noakes https://drewnoakes.com 31 31 */ 32 @SuppressWarnings("unused") 32 33 public class Tag 33 34 { … … 84 85 * @return whether this tag has a name 85 86 */ 86 @NotNull87 87 public boolean hasTagName() 88 88 { -
trunk/src/com/drew/metadata/TagDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 29 29 import java.lang.reflect.Array; 30 30 import java.math.RoundingMode; 31 import java.nio.charset.Charset; 31 32 import java.text.DecimalFormat; 32 33 import java.text.SimpleDateFormat; … … 74 75 final int length = Array.getLength(object); 75 76 if (length > 16) { 76 return String.format("[%d %s]", length, length == 1 ? "value" : "values");77 return String.format("[%d values]", length); 77 78 } 78 79 } … … 269 270 270 271 @Nullable 271 protected String get AsciiStringFromBytes(int tag)272 protected String getStringFromBytes(int tag, Charset cs) 272 273 { 273 274 byte[] values = _directory.getByteArray(tag); … … 277 278 278 279 try { 279 return new String(values, "ASCII").trim();280 return new String(values, cs.name()).trim(); 280 281 } catch (UnsupportedEncodingException e) { 281 282 return null; … … 321 322 Rational[] values = _directory.getRationalArray(tag); 322 323 323 if (values == null || values.length != 4 || (values[0]. doubleValue() == 0 && values[2].doubleValue() == 0))324 if (values == null || values.length != 4 || (values[0].isZero() && values[2].isZero())) 324 325 return null; 325 326 … … 331 332 sb.append(values[0].toSimpleString(true)).append('-').append(values[1].toSimpleString(true)).append("mm"); 332 333 333 if ( values[2].doubleValue() != 0) {334 if (!values[2].isZero()) { 334 335 sb.append(' '); 335 336 … … 345 346 return sb.toString(); 346 347 } 348 349 @Nullable 350 protected String getOrientationDescription(int tag) 351 { 352 return getIndexedDescription(tag, 1, 353 "Top, left side (Horizontal / normal)", 354 "Top, right side (Mirror horizontal)", 355 "Bottom, right side (Rotate 180)", 356 "Bottom, left side (Mirror vertical)", 357 "Left side, top (Mirror horizontal and rotate 270 CW)", 358 "Right side, top (Rotate 90 CW)", 359 "Right side, bottom (Mirror horizontal and rotate 90 CW)", 360 "Left side, bottom (Rotate 270 CW)"); 361 } 362 363 @Nullable 364 protected String getShutterSpeedDescription(int tag) 365 { 366 // I believe this method to now be stable, but am leaving some alternative snippets of 367 // code in here, to assist anyone who's looking into this (given that I don't have a public CVS). 368 369 // float apexValue = _directory.getFloat(ExifSubIFDDirectory.TAG_SHUTTER_SPEED); 370 // int apexPower = (int)Math.pow(2.0, apexValue); 371 // return "1/" + apexPower + " sec"; 372 // TODO test this method 373 // thanks to Mark Edwards for spotting and patching a bug in the calculation of this 374 // description (spotted bug using a Canon EOS 300D) 375 // thanks also to Gli Blr for spotting this bug 376 Float apexValue = _directory.getFloatObject(tag); 377 if (apexValue == null) 378 return null; 379 if (apexValue <= 1) { 380 float apexPower = (float)(1 / (Math.exp(apexValue * Math.log(2)))); 381 long apexPower10 = Math.round((double)apexPower * 10.0); 382 float fApexPower = (float)apexPower10 / 10.0f; 383 DecimalFormat format = new DecimalFormat("0.##"); 384 format.setRoundingMode(RoundingMode.HALF_UP); 385 return format.format(fApexPower) + " sec"; 386 } else { 387 int apexPower = (int)((Math.exp(apexValue * Math.log(2)))); 388 return "1/" + apexPower + " sec"; 389 } 390 391 /* 392 // This alternative implementation offered by Bill Richards 393 // TODO determine which is the correct / more-correct implementation 394 double apexValue = _directory.getDouble(ExifSubIFDDirectory.TAG_SHUTTER_SPEED); 395 double apexPower = Math.pow(2.0, apexValue); 396 397 StringBuffer sb = new StringBuffer(); 398 if (apexPower > 1) 399 apexPower = Math.floor(apexPower); 400 401 if (apexPower < 1) { 402 sb.append((int)Math.round(1/apexPower)); 403 } else { 404 sb.append("1/"); 405 sb.append((int)apexPower); 406 } 407 sb.append(" sec"); 408 return sb.toString(); 409 */ 410 } 411 412 // EXIF LightSource 413 @Nullable 414 protected String getLightSourceDescription(short wbtype) 415 { 416 switch (wbtype) 417 { 418 case 0: 419 return "Unknown"; 420 case 1: 421 return "Daylight"; 422 case 2: 423 return "Fluorescent"; 424 case 3: 425 return "Tungsten (Incandescent)"; 426 case 4: 427 return "Flash"; 428 case 9: 429 return "Fine Weather"; 430 case 10: 431 return "Cloudy"; 432 case 11: 433 return "Shade"; 434 case 12: 435 return "Daylight Fluorescent"; // (D 5700 - 7100K) 436 case 13: 437 return "Day White Fluorescent"; // (N 4600 - 5500K) 438 case 14: 439 return "Cool White Fluorescent"; // (W 3800 - 4500K) 440 case 15: 441 return "White Fluorescent"; // (WW 3250 - 3800K) 442 case 16: 443 return "Warm White Fluorescent"; // (L 2600 - 3250K) 444 case 17: 445 return "Standard Light A"; 446 case 18: 447 return "Standard Light B"; 448 case 19: 449 return "Standard Light C"; 450 case 20: 451 return "D55"; 452 case 21: 453 return "D65"; 454 case 22: 455 return "D75"; 456 case 23: 457 return "D50"; 458 case 24: 459 return "ISO Studio Tungsten"; 460 case 255: 461 return "Other"; 462 } 463 464 return getDescription(wbtype); 465 } 347 466 } -
trunk/src/com/drew/metadata/exif/ExifDescriptorBase.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 26 26 import com.drew.lang.annotations.NotNull; 27 27 import com.drew.lang.annotations.Nullable; 28 import com.drew.lang.ByteArrayReader; 28 29 import com.drew.metadata.Directory; 29 30 import com.drew.metadata.TagDescriptor; 30 31 32 import java.io.IOException; 31 33 import java.io.UnsupportedEncodingException; 32 import java.math.RoundingMode;33 34 import java.text.DecimalFormat; 34 35 import java.util.HashMap; … … 42 43 * @author Drew Noakes https://drewnoakes.com 43 44 */ 45 @SuppressWarnings("WeakerAccess") 44 46 public abstract class ExifDescriptorBase<T extends Directory> extends TagDescriptor<T> 45 47 { … … 49 51 */ 50 52 private final boolean _allowDecimalRepresentationOfRationals = true; 51 52 @NotNull53 private static final java.text.DecimalFormat SimpleDecimalFormatter = new DecimalFormat("0.#");54 53 55 54 // Note for the potential addition of brightness presentation in eV: … … 123 122 case TAG_FILL_ORDER: 124 123 return getFillOrderDescription(); 124 case TAG_CFA_PATTERN_2: 125 return getCfaPattern2Description(); 125 126 case TAG_EXPOSURE_TIME: 126 127 return getExposureTimeDescription(); … … 167 168 case TAG_SCENE_TYPE: 168 169 return getSceneTypeDescription(); 170 case TAG_CFA_PATTERN: 171 return getCfaPatternDescription(); 169 172 case TAG_COMPONENTS_CONFIGURATION: 170 173 return getComponentConfigurationDescription(); … … 234 237 public String getReferenceBlackWhiteDescription() 235 238 { 239 // For some reason, sometimes this is read as a long[] and 240 // getIntArray isn't able to deal with it 236 241 int[] ints = _directory.getIntArray(TAG_REFERENCE_BLACK_WHITE); 237 242 if (ints==null || ints.length < 6) 238 return null; 243 { 244 Object o = _directory.getObject(TAG_REFERENCE_BLACK_WHITE); 245 if (o != null && (o instanceof long[])) 246 { 247 long[] longs = (long[])o; 248 if (longs.length < 6) 249 return null; 250 251 ints = new int[longs.length]; 252 for (int i = 0; i < longs.length; i++) 253 ints[i] = (int)longs[i]; 254 } 255 else 256 return null; 257 } 258 239 259 int blackR = ints[0]; 240 260 int whiteR = ints[1]; … … 279 299 public String getOrientationDescription() 280 300 { 281 return getIndexedDescription(TAG_ORIENTATION, 1, 282 "Top, left side (Horizontal / normal)", 283 "Top, right side (Mirror horizontal)", 284 "Bottom, right side (Rotate 180)", 285 "Bottom, left side (Mirror vertical)", 286 "Left side, top (Mirror horizontal and rotate 270 CW)", 287 "Right side, top (Rotate 90 CW)", 288 "Right side, bottom (Mirror horizontal and rotate 90 CW)", 289 "Left side, bottom (Rotate 270 CW)"); 301 return super.getOrientationDescription(TAG_ORIENTATION); 290 302 } 291 303 … … 443 455 public String getNewSubfileTypeDescription() 444 456 { 445 return getIndexedDescription(TAG_NEW_SUBFILE_TYPE, 1,457 return getIndexedDescription(TAG_NEW_SUBFILE_TYPE, 0, 446 458 "Full-resolution image", 447 459 "Reduced-resolution image", 460 "Single page of multi-page image", 448 461 "Single page of multi-page reduced-resolution image", 449 462 "Transparency mask", … … 587 600 : value.getNumerator() == 0 588 601 ? "Digital zoom not used" 589 : SimpleDecimalFormatter.format(value.doubleValue());602 : new DecimalFormat("0.#").format(value.doubleValue()); 590 603 } 591 604 … … 689 702 "Directly photographed image" 690 703 ); 704 } 705 706 /// <summary> 707 /// String description of CFA Pattern 708 /// </summary> 709 /// <remarks> 710 /// Converted from Exiftool version 10.33 created by Phil Harvey 711 /// http://www.sno.phy.queensu.ca/~phil/exiftool/ 712 /// lib\Image\ExifTool\Exif.pm 713 /// 714 /// Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used. 715 /// It does not apply to all sensing methods. 716 /// </remarks> 717 @Nullable 718 public String getCfaPatternDescription() 719 { 720 return formatCFAPattern(decodeCfaPattern(TAG_CFA_PATTERN)); 721 } 722 723 /// <summary> 724 /// String description of CFA Pattern 725 /// </summary> 726 /// <remarks> 727 /// Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used. 728 /// It does not apply to all sensing methods. 729 /// 730 /// ExifDirectoryBase.TAG_CFA_PATTERN_2 holds only the pixel pattern. ExifDirectoryBase.TAG_CFA_REPEAT_PATTERN_DIM is expected to exist and pass 731 /// some conditional tests. 732 /// </remarks> 733 @Nullable 734 public String getCfaPattern2Description() 735 { 736 byte[] values = _directory.getByteArray(TAG_CFA_PATTERN_2); 737 if (values == null) 738 return null; 739 740 int[] repeatPattern = _directory.getIntArray(TAG_CFA_REPEAT_PATTERN_DIM); 741 if (repeatPattern == null) 742 return String.format("Repeat Pattern not found for CFAPattern (%s)", super.getDescription(TAG_CFA_PATTERN_2)); 743 744 if (repeatPattern.length == 2 && values.length == (repeatPattern[0] * repeatPattern[1])) 745 { 746 int[] intpattern = new int[2 + values.length]; 747 intpattern[0] = repeatPattern[0]; 748 intpattern[1] = repeatPattern[1]; 749 750 for (int i = 0; i < values.length; i++) 751 intpattern[i + 2] = values[i] & 0xFF; // convert the values[i] byte to unsigned 752 753 return formatCFAPattern(intpattern); 754 } 755 756 return String.format("Unknown Pattern (%s)", super.getDescription(TAG_CFA_PATTERN_2)); 757 } 758 759 @Nullable 760 private static String formatCFAPattern(@Nullable int[] pattern) 761 { 762 if (pattern == null) 763 return null; 764 if (pattern.length < 2) 765 return "<truncated data>"; 766 if (pattern[0] == 0 && pattern[1] == 0) 767 return "<zero pattern size>"; 768 769 int end = 2 + pattern[0] * pattern[1]; 770 if (end > pattern.length) 771 return "<invalid pattern size>"; 772 773 String[] cfaColors = { "Red", "Green", "Blue", "Cyan", "Magenta", "Yellow", "White" }; 774 775 StringBuilder ret = new StringBuilder(); 776 ret.append("["); 777 for (int pos = 2; pos < end; pos++) 778 { 779 if (pattern[pos] <= cfaColors.length - 1) 780 ret.append(cfaColors[pattern[pos]]); 781 else 782 ret.append("Unknown"); // indicated pattern position is outside the array bounds 783 784 if ((pos - 2) % pattern[1] == 0) 785 ret.append(","); 786 else if(pos != end - 1) 787 ret.append("]["); 788 } 789 ret.append("]"); 790 791 return ret.toString(); 792 } 793 794 /// <summary> 795 /// Decode raw CFAPattern value 796 /// </summary> 797 /// <remarks> 798 /// Converted from Exiftool version 10.33 created by Phil Harvey 799 /// http://www.sno.phy.queensu.ca/~phil/exiftool/ 800 /// lib\Image\ExifTool\Exif.pm 801 /// 802 /// The value consists of: 803 /// - Two short, being the grid width and height of the repeated pattern. 804 /// - Next, for every pixel in that pattern, an identification code. 805 /// </remarks> 806 @Nullable 807 private int[] decodeCfaPattern(int tagType) 808 { 809 int[] ret; 810 811 byte[] values = _directory.getByteArray(tagType); 812 if (values == null) 813 return null; 814 815 if (values.length < 4) 816 { 817 ret = new int[values.length]; 818 for (int i = 0; i < values.length; i++) 819 ret[i] = values[i]; 820 return ret; 821 } 822 823 ret = new int[values.length - 2]; 824 825 try { 826 ByteArrayReader reader = new ByteArrayReader(values); 827 828 // first two values should be read as 16-bits (2 bytes) 829 short item0 = reader.getInt16(0); 830 short item1 = reader.getInt16(2); 831 832 Boolean copyArray = false; 833 int end = 2 + item0 * item1; 834 if (end > values.length) // sanity check in case of byte order problems; calculated 'end' should be <= length of the values 835 { 836 // try swapping byte order (I have seen this order different than in EXIF) 837 reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder()); 838 item0 = reader.getInt16(0); 839 item1 = reader.getInt16(2); 840 841 if (values.length >= (2 + item0 * item1)) 842 copyArray = true; 843 } 844 else 845 copyArray = true; 846 847 if(copyArray) 848 { 849 ret[0] = item0; 850 ret[1] = item1; 851 852 for (int i = 4; i < values.length; i++) 853 ret[i - 2] = reader.getInt8(i); 854 } 855 } catch (IOException ex) { 856 _directory.addError("IO exception processing data: " + ex.getMessage()); 857 } 858 859 return ret; 691 860 } 692 861 … … 1002 1171 public String getShutterSpeedDescription() 1003 1172 { 1004 // I believe this method to now be stable, but am leaving some alternative snippets of 1005 // code in here, to assist anyone who's looking into this (given that I don't have a public CVS). 1006 1007 // float apexValue = _directory.getFloat(ExifSubIFDDirectory.TAG_SHUTTER_SPEED); 1008 // int apexPower = (int)Math.pow(2.0, apexValue); 1009 // return "1/" + apexPower + " sec"; 1010 // TODO test this method 1011 // thanks to Mark Edwards for spotting and patching a bug in the calculation of this 1012 // description (spotted bug using a Canon EOS 300D) 1013 // thanks also to Gli Blr for spotting this bug 1014 Float apexValue = _directory.getFloatObject(TAG_SHUTTER_SPEED); 1015 if (apexValue == null) 1016 return null; 1017 if (apexValue <= 1) { 1018 float apexPower = (float)(1 / (Math.exp(apexValue * Math.log(2)))); 1019 long apexPower10 = Math.round((double)apexPower * 10.0); 1020 float fApexPower = (float)apexPower10 / 10.0f; 1021 DecimalFormat format = new DecimalFormat("0.##"); 1022 format.setRoundingMode(RoundingMode.HALF_UP); 1023 return format.format(fApexPower) + " sec"; 1024 } else { 1025 int apexPower = (int)((Math.exp(apexValue * Math.log(2)))); 1026 return "1/" + apexPower + " sec"; 1027 } 1028 1029 /* 1030 // This alternative implementation offered by Bill Richards 1031 // TODO determine which is the correct / more-correct implementation 1032 double apexValue = _directory.getDouble(ExifSubIFDDirectory.TAG_SHUTTER_SPEED); 1033 double apexPower = Math.pow(2.0, apexValue); 1034 1035 StringBuffer sb = new StringBuffer(); 1036 if (apexPower > 1) 1037 apexPower = Math.floor(apexPower); 1038 1039 if (apexPower < 1) { 1040 sb.append((int)Math.round(1/apexPower)); 1041 } else { 1042 sb.append("1/"); 1043 sb.append((int)apexPower); 1044 } 1045 sb.append(" sec"); 1046 return sb.toString(); 1047 */ 1173 return super.getShutterSpeedDescription(TAG_SHUTTER_SPEED); 1048 1174 } 1049 1175 -
trunk/src/com/drew/metadata/exif/ExifDirectoryBase.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public abstract class ExifDirectoryBase extends Directory 34 35 { … … 126 127 127 128 public static final int TAG_RESOLUTION_UNIT = 0x0128; 129 public static final int TAG_PAGE_NUMBER = 0x0129; 130 128 131 public static final int TAG_TRANSFER_FUNCTION = 0x012D; 129 132 public static final int TAG_SOFTWARE = 0x0131; … … 149 152 public static final int TAG_JPEG_TABLES = 0x015B; 150 153 public static final int TAG_JPEG_PROC = 0x0200; 154 155 // 0x0201 can have all kinds of descriptions for thumbnail starting index 156 // 0x0202 can have all kinds of descriptions for thumbnail length 157 public static final int TAG_JPEG_RESTART_INTERVAL = 0x0203; 158 public static final int TAG_JPEG_LOSSLESS_PREDICTORS = 0x0205; 159 public static final int TAG_JPEG_POINT_TRANSFORMS = 0x0206; 160 public static final int TAG_JPEG_Q_TABLES = 0x0207; 161 public static final int TAG_JPEG_DC_TABLES = 0x0208; 162 public static final int TAG_JPEG_AC_TABLES = 0x0209; 151 163 152 164 public static final int TAG_YCBCR_COEFFICIENTS = 0x0211; … … 266 278 public static final int TAG_METERING_MODE = 0x9207; 267 279 280 /** 281 * @deprecated use {@link com.drew.metadata.exif.ExifDirectoryBase#TAG_WHITE_BALANCE} instead. 282 */ 283 @Deprecated 284 public static final int TAG_LIGHT_SOURCE = 0x9208; 268 285 /** 269 286 * White balance (aka light source). '0' means unknown, '1' daylight, … … 574 591 public static final int TAG_GAMMA = 0xA500; 575 592 576 public static final int TAG_PRINT_IM 593 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0xC4A5; 577 594 578 595 public static final int TAG_PANASONIC_TITLE = 0xC6D2; … … 612 629 map.put(TAG_PAGE_NAME, "Page Name"); 613 630 map.put(TAG_RESOLUTION_UNIT, "Resolution Unit"); 631 map.put(TAG_PAGE_NUMBER, "Page Number"); 614 632 map.put(TAG_TRANSFER_FUNCTION, "Transfer Function"); 615 633 map.put(TAG_SOFTWARE, "Software"); … … 628 646 map.put(TAG_JPEG_TABLES, "JPEG Tables"); 629 647 map.put(TAG_JPEG_PROC, "JPEG Proc"); 648 649 map.put(TAG_JPEG_RESTART_INTERVAL, "JPEG Restart Interval"); 650 map.put(TAG_JPEG_LOSSLESS_PREDICTORS, "JPEG Lossless Predictors"); 651 map.put(TAG_JPEG_POINT_TRANSFORMS, "JPEG Point Transforms"); 652 map.put(TAG_JPEG_Q_TABLES, "JPEGQ Tables"); 653 map.put(TAG_JPEG_DC_TABLES, "JPEGDC Tables"); 654 map.put(TAG_JPEG_AC_TABLES, "JPEGAC Tables"); 655 630 656 map.put(TAG_YCBCR_COEFFICIENTS, "YCbCr Coefficients"); 631 657 map.put(TAG_YCBCR_SUBSAMPLING, "YCbCr Sub-Sampling"); … … 730 756 map.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number"); 731 757 map.put(TAG_GAMMA, "Gamma"); 732 map.put(TAG_PRINT_IM , "Print IM");758 map.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 733 759 map.put(TAG_PANASONIC_TITLE, "Panasonic Title"); 734 760 map.put(TAG_PANASONIC_TITLE_2, "Panasonic Title (2)"); -
trunk/src/com/drew/metadata/exif/ExifIFD0Descriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 29 29 * @author Drew Noakes https://drewnoakes.com 30 30 */ 31 @SuppressWarnings("WeakerAccess") 31 32 public class ExifIFD0Descriptor extends ExifDescriptorBase<ExifIFD0Directory> 32 33 { -
trunk/src/com/drew/metadata/exif/ExifIFD0Directory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class ExifIFD0Directory extends ExifDirectoryBase 34 35 { -
trunk/src/com/drew/metadata/exif/ExifInteropDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 28 28 * @author Drew Noakes https://drewnoakes.com 29 29 */ 30 @SuppressWarnings("WeakerAccess") 30 31 public class ExifInteropDescriptor extends ExifDescriptorBase<ExifInteropDirectory> 31 32 { -
trunk/src/com/drew/metadata/exif/ExifInteropDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 30 30 * @author Drew Noakes https://drewnoakes.com 31 31 */ 32 @SuppressWarnings("WeakerAccess") 32 33 public class ExifInteropDirectory extends ExifDirectoryBase 33 34 { -
trunk/src/com/drew/metadata/exif/ExifReader.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 42 42 * @author Drew Noakes https://drewnoakes.com 43 43 */ 44 @SuppressWarnings("WeakerAccess") 44 45 public class ExifReader implements JpegSegmentMetadataReader 45 46 { 46 47 /** Exif data stored in JPEG files' APP1 segment are preceded by this six character preamble. */ 47 48 public static final String JPEG_SEGMENT_PREAMBLE = "Exif\0\0"; 48 49 private boolean _storeThumbnailBytes = true;50 51 public boolean isStoreThumbnailBytes()52 {53 return _storeThumbnailBytes;54 }55 56 public void setStoreThumbnailBytes(boolean storeThumbnailBytes)57 {58 _storeThumbnailBytes = storeThumbnailBytes;59 }60 49 61 50 @NotNull … … 89 78 } 90 79 91 /** Reads TIFF formatted Exif data a specified offset within a {@link RandomAccessReader}. */80 /** Reads TIFF formatted Exif data at a specified offset within a {@link RandomAccessReader}. */ 92 81 public void extract(@NotNull final RandomAccessReader reader, @NotNull final Metadata metadata, int readerOffset, @Nullable Directory parentDirectory) 93 82 { 83 ExifTiffHandler exifTiffHandler = new ExifTiffHandler(metadata, parentDirectory); 84 94 85 try { 95 86 // Read the TIFF-formatted Exif data 96 87 new TiffReader().processTiff( 97 88 reader, 98 new ExifTiffHandler(metadata, _storeThumbnailBytes, parentDirectory),89 exifTiffHandler, 99 90 readerOffset 100 91 ); 101 92 } catch (TiffProcessingException e) { 93 exifTiffHandler.error("Exception processing TIFF data: " + e.getMessage()); 102 94 // TODO what do to with this error state? 103 95 e.printStackTrace(System.err); 104 96 } catch (IOException e) { 97 exifTiffHandler.error("Exception processing TIFF data: " + e.getMessage()); 105 98 // TODO what do to with this error state? 106 99 e.printStackTrace(System.err); -
trunk/src/com/drew/metadata/exif/ExifSubIFDDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 28 28 * @author Drew Noakes https://drewnoakes.com 29 29 */ 30 @SuppressWarnings("WeakerAccess") 30 31 public class ExifSubIFDDescriptor extends ExifDescriptorBase<ExifSubIFDDirectory> 31 32 { -
trunk/src/com/drew/metadata/exif/ExifSubIFDDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 21 21 package com.drew.metadata.exif; 22 22 23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 25 23 26 import java.util.Date; 24 27 import java.util.HashMap; 25 28 import java.util.TimeZone; 26 27 import com.drew.lang.annotations.NotNull;28 import com.drew.lang.annotations.Nullable;29 29 30 30 /** … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class ExifSubIFDDirectory extends ExifDirectoryBase 36 37 { … … 88 89 */ 89 90 @Nullable 90 public Date getDateOriginal( TimeZone timeZone)91 public Date getDateOriginal(@Nullable TimeZone timeZone) 91 92 { 92 93 return getDate(TAG_DATETIME_ORIGINAL, getString(TAG_SUBSECOND_TIME_ORIGINAL), timeZone); … … 116 117 */ 117 118 @Nullable 118 public Date getDateDigitized( TimeZone timeZone)119 public Date getDateDigitized(@Nullable TimeZone timeZone) 119 120 { 120 121 return getDate(TAG_DATETIME_DIGITIZED, getString(TAG_SUBSECOND_TIME_DIGITIZED), timeZone); -
trunk/src/com/drew/metadata/exif/ExifThumbnailDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class ExifThumbnailDescriptor extends ExifDescriptorBase<ExifThumbnailDirectory> 36 37 { -
trunk/src/com/drew/metadata/exif/ExifThumbnailDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 22 22 package com.drew.metadata.exif; 23 23 24 import java.io.FileOutputStream;25 import java.io.IOException; 24 import com.drew.lang.annotations.NotNull; 25 26 26 import java.util.HashMap; 27 28 import com.drew.lang.annotations.NotNull;29 import com.drew.lang.annotations.Nullable;30 import com.drew.metadata.MetadataException;31 27 32 28 /** … … 35 31 * @author Drew Noakes https://drewnoakes.com 36 32 */ 33 @SuppressWarnings("WeakerAccess") 37 34 public class ExifThumbnailDirectory extends ExifDirectoryBase 38 35 { … … 46 43 public static final int TAG_THUMBNAIL_LENGTH = 0x0202; 47 44 45 /** 46 * @deprecated use {@link com.drew.metadata.exif.ExifDirectoryBase#TAG_COMPRESSION} instead. 47 */ 48 @Deprecated 49 public static final int TAG_THUMBNAIL_COMPRESSION = 0x0103; 50 48 51 @NotNull 49 52 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); … … 56 59 _tagNameMap.put(TAG_THUMBNAIL_LENGTH, "Thumbnail Length"); 57 60 } 58 59 @Nullable60 private byte[] _thumbnailData;61 61 62 62 public ExifThumbnailDirectory() … … 78 78 return _tagNameMap; 79 79 } 80 81 public boolean hasThumbnailData()82 {83 return _thumbnailData != null;84 }85 86 @Nullable87 public byte[] getThumbnailData()88 {89 return _thumbnailData;90 }91 92 public void setThumbnailData(@Nullable byte[] data)93 {94 _thumbnailData = data;95 }96 97 public void writeThumbnail(@NotNull String filename) throws MetadataException, IOException98 {99 byte[] data = _thumbnailData;100 101 if (data == null)102 throw new MetadataException("No thumbnail data exists.");103 104 FileOutputStream stream = null;105 try {106 stream = new FileOutputStream(filename);107 stream.write(data);108 } finally {109 if (stream != null)110 stream.close();111 }112 }113 114 /*115 // This thumbnail extraction code is not complete, and is included to assist anyone who feels like looking into116 // it. Please share any progress with the original author, and hence the community. Thanks.117 118 public Image getThumbnailImage() throws MetadataException119 {120 if (!hasThumbnailData())121 return null;122 123 int compression = 0;124 try {125 compression = this.getInt(ExifSubIFDDirectory.TAG_COMPRESSION);126 } catch (Throwable e) {127 this.addError("Unable to determine thumbnail type " + e.getMessage());128 }129 130 final byte[] thumbnailBytes = getThumbnailData();131 132 if (compression == ExifSubIFDDirectory.COMPRESSION_JPEG)133 {134 // JPEG Thumbnail135 // operate directly on thumbnailBytes136 return decodeBytesAsImage(thumbnailBytes);137 }138 else if (compression == ExifSubIFDDirectory.COMPRESSION_NONE)139 {140 // uncompressed thumbnail (raw RGB data)141 if (!this.containsTag(ExifSubIFDDirectory.TAG_PHOTOMETRIC_INTERPRETATION))142 return null;143 144 try145 {146 // If the image is RGB format, then convert it to a bitmap147 final int photometricInterpretation = this.getInt(ExifSubIFDDirectory.TAG_PHOTOMETRIC_INTERPRETATION);148 if (photometricInterpretation == ExifSubIFDDirectory.PHOTOMETRIC_INTERPRETATION_RGB)149 {150 // RGB151 Image image = createImageFromRawRgb(thumbnailBytes);152 return image;153 }154 else if (photometricInterpretation == ExifSubIFDDirectory.PHOTOMETRIC_INTERPRETATION_YCBCR)155 {156 // YCbCr157 Image image = createImageFromRawYCbCr(thumbnailBytes);158 return image;159 }160 else if (photometricInterpretation == ExifSubIFDDirectory.PHOTOMETRIC_INTERPRETATION_MONOCHROME)161 {162 // Monochrome163 return null;164 }165 } catch (Throwable e) {166 this.addError("Unable to extract thumbnail: " + e.getMessage());167 }168 }169 return null;170 }171 172 /**173 * Handle the YCbCr thumbnail encoding used by Ricoh RDC4200/4300, Fuji DS-7/300 and DX-5/7/9 cameras.174 *175 * At DX-5/7/9, YCbCrSubsampling(0x0212) has values of '2,1', PlanarConfiguration(0x011c) has a value '1'. So the176 * data align of this image is below.177 *178 * Y(0,0),Y(1,0),Cb(0,0),Cr(0,0), Y(2,0),Y(3,0),Cb(2,0),Cr(3.0), Y(4,0),Y(5,0),Cb(4,0),Cr(4,0). . . .179 *180 * The numbers in parenthesis are pixel coordinates. DX series' YCbCrCoefficients(0x0211) has values '0.299/0.587/0.114',181 * ReferenceBlackWhite(0x0214) has values '0,255,128,255,128,255'. Therefore to convert from Y/Cb/Cr to RGB is;182 *183 * B(0,0)=(Cb-128)*(2-0.114*2)+Y(0,0)184 * R(0,0)=(Cr-128)*(2-0.299*2)+Y(0,0)185 * G(0,0)=(Y(0,0)-0.114*B(0,0)-0.299*R(0,0))/0.587186 *187 * Horizontal subsampling is a value '2', so you can calculate B(1,0)/R(1,0)/G(1,0) by using the Y(1,0) and Cr(0,0)/Cb(0,0).188 * Repeat this conversion by value of ImageWidth(0x0100) and ImageLength(0x0101).189 *190 * @param thumbnailBytes191 * @return192 * @throws com.drew.metadata.MetadataException193 * /194 private Image createImageFromRawYCbCr(byte[] thumbnailBytes) throws MetadataException195 {196 /*197 Y = 0.257R + 0.504G + 0.098B + 16198 Cb = -0.148R - 0.291G + 0.439B + 128199 Cr = 0.439R - 0.368G - 0.071B + 128200 201 G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128)202 R = 1.164(Y-16) + 1.596(Cr-128)203 B = 1.164(Y-16) + 2.018(Cb-128)204 205 R, G and B range from 0 to 255.206 Y ranges from 16 to 235.207 Cb and Cr range from 16 to 240.208 209 http://www.faqs.org/faqs/graphics/colorspace-faq/210 * /211 212 int length = thumbnailBytes.length; // this.getInt(ExifSubIFDDirectory.TAG_STRIP_BYTE_COUNTS);213 final int imageWidth = this.getInt(ExifSubIFDDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);214 final int imageHeight = this.getInt(ExifSubIFDDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);215 // final int headerLength = 54;216 // byte[] result = new byte[length + headerLength];217 // // Add a windows BMP header described:218 // // http://www.onicos.com/staff/iz/formats/bmp.html219 // result[0] = 'B';220 // result[1] = 'M'; // File Type identifier221 // result[3] = (byte)(result.length / 256);222 // result[2] = (byte)result.length;223 // result[10] = (byte)headerLength;224 // result[14] = 40; // MS Windows BMP header225 // result[18] = (byte)imageWidth;226 // result[22] = (byte)imageHeight;227 // result[26] = 1; // 1 Plane228 // result[28] = 24; // Colour depth229 // result[34] = (byte)length;230 // result[35] = (byte)(length / 256);231 232 final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);233 234 // order is YCbCr and image is upside down, bitmaps are BGR235 //// for (int i = headerLength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)236 // {237 // final int y = thumbnailBytes[dataOffset - 2] & 0xFF;238 // final int cb = thumbnailBytes[dataOffset - 1] & 0xFF;239 // final int cr = thumbnailBytes[dataOffset] & 0xFF;240 // if (y<16 || y>235 || cb<16 || cb>240 || cr<16 || cr>240)241 // "".toString();242 //243 // int g = (int)(1.164*(y-16) - 0.391*(cb-128) - 0.813*(cr-128));244 // int r = (int)(1.164*(y-16) + 1.596*(cr-128));245 // int b = (int)(1.164*(y-16) + 2.018*(cb-128));246 //247 //// result[i] = (byte)b;248 //// result[i + 1] = (byte)g;249 //// result[i + 2] = (byte)r;250 //251 // // TODO compose the image here252 // image.setRGB(1, 2, 3);253 // }254 255 return image;256 }257 258 /**259 * Creates a thumbnail image in (Windows) BMP format from raw RGB data.260 * @param thumbnailBytes261 * @return262 * @throws com.drew.metadata.MetadataException263 * /264 private Image createImageFromRawRgb(byte[] thumbnailBytes) throws MetadataException265 {266 final int length = thumbnailBytes.length; // this.getInt(ExifSubIFDDirectory.TAG_STRIP_BYTE_COUNTS);267 final int imageWidth = this.getInt(ExifSubIFDDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);268 final int imageHeight = this.getInt(ExifSubIFDDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);269 // final int headerLength = 54;270 // final byte[] result = new byte[length + headerLength];271 // // Add a windows BMP header described:272 // // http://www.onicos.com/staff/iz/formats/bmp.html273 // result[0] = 'B';274 // result[1] = 'M'; // File Type identifier275 // result[3] = (byte)(result.length / 256);276 // result[2] = (byte)result.length;277 // result[10] = (byte)headerLength;278 // result[14] = 40; // MS Windows BMP header279 // result[18] = (byte)imageWidth;280 // result[22] = (byte)imageHeight;281 // result[26] = 1; // 1 Plane282 // result[28] = 24; // Colour depth283 // result[34] = (byte)length;284 // result[35] = (byte)(length / 256);285 286 final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);287 288 // order is RGB and image is upside down, bitmaps are BGR289 // for (int i = headerLength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)290 // {291 // byte b = thumbnailBytes[dataOffset - 2];292 // byte g = thumbnailBytes[dataOffset - 1];293 // byte r = thumbnailBytes[dataOffset];294 //295 // // TODO compose the image here296 // image.setRGB(1, 2, 3);297 // }298 299 return image;300 }301 */302 80 } -
trunk/src/com/drew/metadata/exif/ExifTiffHandler.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 21 21 package com.drew.metadata.exif; 22 22 23 import java.io.ByteArrayInputStream; 24 import java.io.IOException; 25 import java.util.Arrays; 26 import java.util.Set; 27 28 import com.drew.imaging.jpeg.JpegMetadataReader; 29 import com.drew.imaging.jpeg.JpegProcessingException; 23 30 import com.drew.imaging.tiff.TiffProcessingException; 24 31 import com.drew.imaging.tiff.TiffReader; 32 import com.drew.lang.Charsets; 25 33 import com.drew.lang.RandomAccessReader; 26 34 import com.drew.lang.SequentialByteArrayReader; … … 29 37 import com.drew.metadata.Directory; 30 38 import com.drew.metadata.Metadata; 39 import com.drew.metadata.StringValue; 31 40 import com.drew.metadata.exif.makernotes.*; 32 41 import com.drew.metadata.iptc.IptcReader; 33 42 import com.drew.metadata.tiff.DirectoryTiffHandler; 34 35 import java.io.IOException;36 import java.util.Set;37 43 38 44 /** … … 46 52 public class ExifTiffHandler extends DirectoryTiffHandler 47 53 { 48 private final boolean _storeThumbnailBytes; 49 50 public ExifTiffHandler(@NotNull Metadata metadata, boolean storeThumbnailBytes, @Nullable Directory parentDirectory) 51 { 52 super(metadata, ExifIFD0Directory.class); 53 _storeThumbnailBytes = storeThumbnailBytes; 54 public ExifTiffHandler(@NotNull Metadata metadata, @Nullable Directory parentDirectory) 55 { 56 super(metadata); 54 57 55 58 if (parentDirectory != null) … … 64 67 final int panasonicRawTiffMarker = 0x0055; // for RW2 files 65 68 66 if (marker != standardTiffMarker && marker != olympusRawTiffMarker && marker != olympusRawTiffMarker2 && marker != panasonicRawTiffMarker) { 67 throw new TiffProcessingException("Unexpected TIFF marker: 0x" + Integer.toHexString(marker)); 69 switch (marker) 70 { 71 case standardTiffMarker: 72 case olympusRawTiffMarker: // Todo: implement an IFD0, if there is one 73 case olympusRawTiffMarker2: // Todo: implement an IFD0, if there is one 74 pushDirectory(ExifIFD0Directory.class); 75 break; 76 case panasonicRawTiffMarker: 77 pushDirectory(PanasonicRawIFD0Directory.class); 78 break; 79 default: 80 throw new TiffProcessingException(String.format("Unexpected TIFF marker: 0x%X", marker)); 68 81 } 69 82 } … … 76 89 } 77 90 78 if (_currentDirectory instanceof ExifIFD0Directory ) {91 if (_currentDirectory instanceof ExifIFD0Directory || _currentDirectory instanceof PanasonicRawIFD0Directory) { 79 92 if (tagId == ExifIFD0Directory.TAG_EXIF_SUB_IFD_OFFSET) { 80 93 pushDirectory(ExifSubIFDDirectory.class); … … 96 109 97 110 if (_currentDirectory instanceof OlympusMakernoteDirectory) { 98 if (tagId == OlympusMakernoteDirectory.TAG_EQUIPMENT) { 99 pushDirectory(OlympusEquipmentMakernoteDirectory.class); 100 return true; 101 } 102 103 if (tagId == OlympusMakernoteDirectory.TAG_CAMERA_SETTINGS) { 104 pushDirectory(OlympusCameraSettingsMakernoteDirectory.class); 105 return true; 111 // Note: these also appear in customProcessTag because some are IFD pointers while others begin immediately 112 // for the same directories 113 switch(tagId) { 114 case OlympusMakernoteDirectory.TAG_EQUIPMENT: 115 pushDirectory(OlympusEquipmentMakernoteDirectory.class); 116 return true; 117 case OlympusMakernoteDirectory.TAG_CAMERA_SETTINGS: 118 pushDirectory(OlympusCameraSettingsMakernoteDirectory.class); 119 return true; 120 case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT: 121 pushDirectory(OlympusRawDevelopmentMakernoteDirectory.class); 122 return true; 123 case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT_2: 124 pushDirectory(OlympusRawDevelopment2MakernoteDirectory.class); 125 return true; 126 case OlympusMakernoteDirectory.TAG_IMAGE_PROCESSING: 127 pushDirectory(OlympusImageProcessingMakernoteDirectory.class); 128 return true; 129 case OlympusMakernoteDirectory.TAG_FOCUS_INFO: 130 pushDirectory(OlympusFocusInfoMakernoteDirectory.class); 131 return true; 132 case OlympusMakernoteDirectory.TAG_RAW_INFO: 133 pushDirectory(OlympusRawInfoMakernoteDirectory.class); 134 return true; 135 case OlympusMakernoteDirectory.TAG_MAIN_INFO: 136 pushDirectory(OlympusMakernoteDirectory.class); 137 return true; 106 138 } 107 139 } … … 113 145 { 114 146 // In Exif, the only known 'follower' IFD is the thumbnail one, however this may not be the case. 115 if (_currentDirectory instanceof ExifIFD0Directory) { 116 pushDirectory(ExifThumbnailDirectory.class); 147 // UPDATE: In multipage TIFFs, the 'follower' IFD points to the next image in the set 148 if (_currentDirectory instanceof ExifIFD0Directory || _currentDirectory instanceof ExifImageDirectory) { 149 // If the PageNumber tag is defined, assume this is a multipage TIFF or similar 150 // TODO: Find better ways to know which follower Directory should be used 151 if (_currentDirectory.containsTag(ExifDirectoryBase.TAG_PAGE_NUMBER)) 152 pushDirectory(ExifImageDirectory.class); 153 else 154 pushDirectory(ExifThumbnailDirectory.class); 117 155 return true; 118 156 } … … 132 170 if (formatCode == 13) 133 171 return componentCount * 4; 172 173 // an unknown (0) formatCode needs to be potentially handled later as a highly custom directory tag 174 if(formatCode == 0) 175 return 0L; 134 176 135 177 return null; … … 143 185 final int byteCount) throws IOException 144 186 { 187 // Some 0x0000 tags have a 0 byteCount. Determine whether it's bad. 188 if (tagId == 0) 189 { 190 if (_currentDirectory.containsTag(tagId)) 191 { 192 // Let it go through for now. Some directories handle it, some don't 193 return false; 194 } 195 196 // Skip over 0x0000 tags that don't have any associated bytes. No idea what it contains in this case, if anything. 197 if (byteCount == 0) 198 return true; 199 } 200 145 201 // Custom processing for the Makernote tag 146 202 if (tagId == ExifSubIFDDirectory.TAG_MAKERNOTE && _currentDirectory instanceof ExifSubIFDDirectory) { … … 159 215 } 160 216 217 if (HandlePrintIM(_currentDirectory, tagId)) 218 { 219 PrintIMDirectory printIMDirectory = new PrintIMDirectory(); 220 printIMDirectory.setParent(_currentDirectory); 221 _metadata.addDirectory(printIMDirectory); 222 ProcessPrintIM(printIMDirectory, tagOffset, reader, byteCount); 223 return true; 224 } 225 226 // Note: these also appear in tryEnterSubIfd because some are IFD pointers while others begin immediately 227 // for the same directories 228 if(_currentDirectory instanceof OlympusMakernoteDirectory) 229 { 230 switch (tagId) 231 { 232 case OlympusMakernoteDirectory.TAG_EQUIPMENT: 233 pushDirectory(OlympusEquipmentMakernoteDirectory.class); 234 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 235 return true; 236 case OlympusMakernoteDirectory.TAG_CAMERA_SETTINGS: 237 pushDirectory(OlympusCameraSettingsMakernoteDirectory.class); 238 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 239 return true; 240 case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT: 241 pushDirectory(OlympusRawDevelopmentMakernoteDirectory.class); 242 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 243 return true; 244 case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT_2: 245 pushDirectory(OlympusRawDevelopment2MakernoteDirectory.class); 246 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 247 return true; 248 case OlympusMakernoteDirectory.TAG_IMAGE_PROCESSING: 249 pushDirectory(OlympusImageProcessingMakernoteDirectory.class); 250 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 251 return true; 252 case OlympusMakernoteDirectory.TAG_FOCUS_INFO: 253 pushDirectory(OlympusFocusInfoMakernoteDirectory.class); 254 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 255 return true; 256 case OlympusMakernoteDirectory.TAG_RAW_INFO: 257 pushDirectory(OlympusRawInfoMakernoteDirectory.class); 258 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 259 return true; 260 case OlympusMakernoteDirectory.TAG_MAIN_INFO: 261 pushDirectory(OlympusMakernoteDirectory.class); 262 TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset); 263 return true; 264 } 265 } 266 267 if (_currentDirectory instanceof PanasonicRawIFD0Directory) 268 { 269 // these contain binary data with specific offsets, and can't be processed as regular ifd's. 270 // The binary data is broken into 'fake' tags and there is a pattern. 271 switch (tagId) 272 { 273 case PanasonicRawIFD0Directory.TagWbInfo: 274 PanasonicRawWbInfoDirectory dirWbInfo = new PanasonicRawWbInfoDirectory(); 275 dirWbInfo.setParent(_currentDirectory); 276 _metadata.addDirectory(dirWbInfo); 277 ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2); 278 return true; 279 case PanasonicRawIFD0Directory.TagWbInfo2: 280 PanasonicRawWbInfo2Directory dirWbInfo2 = new PanasonicRawWbInfo2Directory(); 281 dirWbInfo2.setParent(_currentDirectory); 282 _metadata.addDirectory(dirWbInfo2); 283 ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3); 284 return true; 285 case PanasonicRawIFD0Directory.TagDistortionInfo: 286 PanasonicRawDistortionDirectory dirDistort = new PanasonicRawDistortionDirectory(); 287 dirDistort.setParent(_currentDirectory); 288 _metadata.addDirectory(dirDistort); 289 ProcessBinary(dirDistort, tagOffset, reader, byteCount, true, 1); 290 return true; 291 } 292 } 293 294 // Panasonic RAW sometimes contains an embedded version of the data as a JPG file. 295 if (tagId == PanasonicRawIFD0Directory.TagJpgFromRaw && _currentDirectory instanceof PanasonicRawIFD0Directory) 296 { 297 byte[] jpegrawbytes = reader.getBytes(tagOffset, byteCount); 298 299 // Extract information from embedded image since it is metadata-rich 300 ByteArrayInputStream jpegmem = new ByteArrayInputStream(jpegrawbytes); 301 try { 302 Metadata jpegDirectory = JpegMetadataReader.readMetadata(jpegmem); 303 for (Directory directory : jpegDirectory.getDirectories()) { 304 directory.setParent(_currentDirectory); 305 _metadata.addDirectory(directory); 306 } 307 return true; 308 } catch (JpegProcessingException e) { 309 _currentDirectory.addError("Error processing JpgFromRaw: " + e.getMessage()); 310 } catch (IOException e) { 311 _currentDirectory.addError("Error reading JpgFromRaw: " + e.getMessage()); 312 } 313 } 314 161 315 return false; 162 316 } 163 317 164 public void completed(@NotNull final RandomAccessReader reader, final int tiffHeaderOffset) 165 { 166 if (_storeThumbnailBytes) { 167 // after the extraction process, if we have the correct tags, we may be able to store thumbnail information 168 ExifThumbnailDirectory thumbnailDirectory = _metadata.getFirstDirectoryOfType(ExifThumbnailDirectory.class); 169 if (thumbnailDirectory != null && thumbnailDirectory.containsTag(ExifThumbnailDirectory.TAG_COMPRESSION)) { 170 Integer offset = thumbnailDirectory.getInteger(ExifThumbnailDirectory.TAG_THUMBNAIL_OFFSET); 171 Integer length = thumbnailDirectory.getInteger(ExifThumbnailDirectory.TAG_THUMBNAIL_LENGTH); 172 if (offset != null && length != null) { 173 try { 174 byte[] thumbnailData = reader.getBytes(tiffHeaderOffset + offset, length); 175 thumbnailDirectory.setThumbnailData(thumbnailData); 176 } catch (IOException ex) { 177 thumbnailDirectory.addError("Invalid thumbnail data specification: " + ex.getMessage()); 318 private static void ProcessBinary(@NotNull final Directory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount, final Boolean issigned, final int arrayLength) throws IOException 319 { 320 // expects signed/unsigned int16 (for now) 321 //int byteSize = issigned ? sizeof(short) : sizeof(ushort); 322 int byteSize = 2; 323 324 // 'directory' is assumed to contain tags that correspond to the byte position unless it's a set of bytes 325 for (int i = 0; i < byteCount; i++) 326 { 327 if (directory.hasTagName(i)) 328 { 329 // only process this tag if the 'next' integral tag exists. Otherwise, it's a set of bytes 330 if (i < byteCount - 1 && directory.hasTagName(i + 1)) 331 { 332 if(issigned) 333 directory.setObject(i, reader.getInt16(tagValueOffset + (i* byteSize))); 334 else 335 directory.setObject(i, reader.getUInt16(tagValueOffset + (i* byteSize))); 336 } 337 else 338 { 339 // the next arrayLength bytes are a multi-byte value 340 if (issigned) 341 { 342 short[] val = new short[arrayLength]; 343 for (int j = 0; j<val.length; j++) 344 val[j] = reader.getInt16(tagValueOffset + ((i + j) * byteSize)); 345 directory.setObjectArray(i, val); 178 346 } 347 else 348 { 349 int[] val = new int[arrayLength]; 350 for (int j = 0; j<val.length; j++) 351 val[j] = reader.getUInt16(tagValueOffset + ((i + j) * byteSize)); 352 directory.setObjectArray(i, val); 353 } 354 355 i += arrayLength - 1; 179 356 } 180 357 } … … 190 367 Directory ifd0Directory = _metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); 191 368 192 if (ifd0Directory == null) 193 return false; 194 195 String cameraMake = ifd0Directory.getString(ExifIFD0Directory.TAG_MAKE); 196 197 final String firstTwoChars = reader.getString(makernoteOffset, 2); 198 final String firstThreeChars = reader.getString(makernoteOffset, 3); 199 final String firstFourChars = reader.getString(makernoteOffset, 4); 200 final String firstFiveChars = reader.getString(makernoteOffset, 5); 201 final String firstSixChars = reader.getString(makernoteOffset, 6); 202 final String firstSevenChars = reader.getString(makernoteOffset, 7); 203 final String firstEightChars = reader.getString(makernoteOffset, 8); 204 final String firstTenChars = reader.getString(makernoteOffset, 10); 205 final String firstTwelveChars = reader.getString(makernoteOffset, 12); 369 String cameraMake = ifd0Directory == null ? null : ifd0Directory.getString(ExifIFD0Directory.TAG_MAKE); 370 371 final String firstTwoChars = reader.getString(makernoteOffset, 2, Charsets.UTF_8); 372 final String firstThreeChars = reader.getString(makernoteOffset, 3, Charsets.UTF_8); 373 final String firstFourChars = reader.getString(makernoteOffset, 4, Charsets.UTF_8); 374 final String firstFiveChars = reader.getString(makernoteOffset, 5, Charsets.UTF_8); 375 final String firstSixChars = reader.getString(makernoteOffset, 6, Charsets.UTF_8); 376 final String firstSevenChars = reader.getString(makernoteOffset, 7, Charsets.UTF_8); 377 final String firstEightChars = reader.getString(makernoteOffset, 8, Charsets.UTF_8); 378 final String firstNineChars = reader.getString(makernoteOffset, 9, Charsets.UTF_8); 379 final String firstTenChars = reader.getString(makernoteOffset, 10, Charsets.UTF_8); 380 final String firstTwelveChars = reader.getString(makernoteOffset, 12, Charsets.UTF_8); 206 381 207 382 boolean byteOrderBefore = reader.isMotorolaByteOrder(); … … 243 418 break; 244 419 default: 245 ifd0Directory.addError("Unsupported Nikon makernote data ignored.");420 _currentDirectory.addError("Unsupported Nikon makernote data ignored."); 246 421 break; 247 422 } … … 254 429 pushDirectory(SonyType1MakernoteDirectory.class); 255 430 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, tiffHeaderOffset); 431 // Do this check LAST after most other Sony checks 432 } else if (cameraMake != null && cameraMake.startsWith("SONY") && 433 !Arrays.equals(reader.getBytes(makernoteOffset, 2), new byte[]{ 0x01, 0x00 }) ) { 434 // The IFD begins with the first Makernote byte (no ASCII name). Used in SR2 and ARW images 435 pushDirectory(SonyType1MakernoteDirectory.class); 436 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset); 256 437 } else if ("SEMC MS\u0000\u0000\u0000\u0000\u0000".equals(firstTwelveChars)) { 257 438 // force MM for this directory … … 294 475 } else if ("LEICA".equals(firstFiveChars)) { 295 476 reader.setMotorolaByteOrder(false); 296 if ("Leica Camera AG".equals(cameraMake)) { 477 478 // used by the X1/X2/X VARIO/T 479 // (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG") 480 // (X2 starts with "LEICA\0\x05\0", Make is "LEICA CAMERA AG") 481 // (X VARIO starts with "LEICA\0\x04\0", Make is "LEICA CAMERA AG") 482 // (T (Typ 701) starts with "LEICA\0\0x6", Make is "LEICA CAMERA AG") 483 // (X (Typ 113) starts with "LEICA\0\0x7", Make is "LEICA CAMERA AG") 484 485 if ("LEICA\0\u0001\0".equals(firstEightChars) || 486 "LEICA\0\u0004\0".equals(firstEightChars) || 487 "LEICA\0\u0005\0".equals(firstEightChars) || 488 "LEICA\0\u0006\0".equals(firstEightChars) || 489 "LEICA\0\u0007\0".equals(firstEightChars)) 490 { 491 pushDirectory(LeicaType5MakernoteDirectory.class); 492 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset); 493 } else if ("Leica Camera AG".equals(cameraMake)) { 297 494 pushDirectory(LeicaMakernoteDirectory.class); 298 495 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset); … … 304 501 return false; 305 502 } 306 } else if ("Panasonic\u0000\u0000\u0000".equals(reader.getString(makernoteOffset, 12 ))) {503 } else if ("Panasonic\u0000\u0000\u0000".equals(reader.getString(makernoteOffset, 12, Charsets.UTF_8))) { 307 504 // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD 308 505 // Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment … … 349 546 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset); 350 547 } 548 } else if (firstTenChars.equals("Apple iOS\0")) { 549 // Always in Motorola byte order 550 boolean orderBefore = reader.isMotorolaByteOrder(); 551 reader.setMotorolaByteOrder(true); 552 pushDirectory(AppleMakernoteDirectory.class); 553 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 14, makernoteOffset); 554 reader.setMotorolaByteOrder(orderBefore); 555 } else if (reader.getUInt16(makernoteOffset) == ReconyxHyperFireMakernoteDirectory.MAKERNOTE_VERSION) { 556 ReconyxHyperFireMakernoteDirectory directory = new ReconyxHyperFireMakernoteDirectory(); 557 _metadata.addDirectory(directory); 558 processReconyxHyperFireMakernote(directory, makernoteOffset, reader); 559 } else if (firstNineChars.equalsIgnoreCase("RECONYXUF")) { 560 ReconyxUltraFireMakernoteDirectory directory = new ReconyxUltraFireMakernoteDirectory(); 561 _metadata.addDirectory(directory); 562 processReconyxUltraFireMakernote(directory, makernoteOffset, reader); 563 } else if ("SAMSUNG".equals(cameraMake)) { 564 // Only handles Type2 notes correctly. Others aren't implemented, and it's complex to determine which ones to use 565 pushDirectory(SamsungType2MakernoteDirectory.class); 566 TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset); 351 567 } else { 352 568 // The makernote is not comprehended by this library. … … 359 575 } 360 576 577 private static Boolean HandlePrintIM(@NotNull final Directory directory, final int tagId) 578 { 579 if (tagId == ExifDirectoryBase.TAG_PRINT_IMAGE_MATCHING_INFO) 580 return true; 581 582 if (tagId == 0x0E00) 583 { 584 // Tempting to say every tagid of 0x0E00 is a PIM tag, but can't be 100% sure 585 if (directory instanceof CasioType2MakernoteDirectory || 586 directory instanceof KyoceraMakernoteDirectory || 587 directory instanceof NikonType2MakernoteDirectory || 588 directory instanceof OlympusMakernoteDirectory || 589 directory instanceof PanasonicMakernoteDirectory || 590 directory instanceof PentaxMakernoteDirectory || 591 directory instanceof RicohMakernoteDirectory || 592 directory instanceof SanyoMakernoteDirectory || 593 directory instanceof SonyType1MakernoteDirectory) 594 return true; 595 } 596 597 return false; 598 } 599 600 /// <summary> 601 /// Process PrintIM IFD 602 /// </summary> 603 /// <remarks> 604 /// Converted from Exiftool version 10.33 created by Phil Harvey 605 /// http://www.sno.phy.queensu.ca/~phil/exiftool/ 606 /// lib\Image\ExifTool\PrintIM.pm 607 /// </remarks> 608 private static void ProcessPrintIM(@NotNull final PrintIMDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount) throws IOException 609 { 610 Boolean resetByteOrder = null; 611 612 if (byteCount == 0) 613 { 614 directory.addError("Empty PrintIM data"); 615 return; 616 } 617 618 if (byteCount <= 15) 619 { 620 directory.addError("Bad PrintIM data"); 621 return; 622 } 623 624 String header = reader.getString(tagValueOffset, 12, Charsets.UTF_8); 625 626 if (!header.startsWith("PrintIM")) //, StringComparison.Ordinal)) 627 { 628 directory.addError("Invalid PrintIM header"); 629 return; 630 } 631 632 // check size of PrintIM block 633 int num = reader.getUInt16(tagValueOffset + 14); 634 if (byteCount < 16 + num * 6) 635 { 636 // size is too big, maybe byte ordering is wrong 637 resetByteOrder = reader.isMotorolaByteOrder(); 638 reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder()); 639 num = reader.getUInt16(tagValueOffset + 14); 640 if (byteCount < 16 + num * 6) 641 { 642 directory.addError("Bad PrintIM size"); 643 return; 644 } 645 } 646 647 directory.setObject(PrintIMDirectory.TagPrintImVersion, header.substring(8, 12)); 648 649 for (int n = 0; n < num; n++) 650 { 651 int pos = tagValueOffset + 16 + n * 6; 652 int tag = reader.getUInt16(pos); 653 long val = reader.getUInt32(pos + 2); 654 655 directory.setObject(tag, val); 656 } 657 658 if (resetByteOrder != null) 659 reader.setMotorolaByteOrder(resetByteOrder); 660 } 661 361 662 private static void processKodakMakernote(@NotNull final KodakMakernoteDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader) 362 663 { … … 364 665 int dataOffset = tagValueOffset + 8; 365 666 try { 366 directory.setString (KodakMakernoteDirectory.TAG_KODAK_MODEL, reader.getString(dataOffset,8));667 directory.setStringValue(KodakMakernoteDirectory.TAG_KODAK_MODEL, reader.getStringValue(dataOffset, 8, Charsets.UTF_8)); 367 668 directory.setInt(KodakMakernoteDirectory.TAG_QUALITY, reader.getUInt8(dataOffset + 9)); 368 669 directory.setInt(KodakMakernoteDirectory.TAG_BURST_MODE, reader.getUInt8(dataOffset + 10)); … … 394 695 } 395 696 } 697 698 private static void processReconyxHyperFireMakernote(@NotNull final ReconyxHyperFireMakernoteDirectory directory, final int makernoteOffset, @NotNull final RandomAccessReader reader) throws IOException 699 { 700 directory.setObject(ReconyxHyperFireMakernoteDirectory.TAG_MAKERNOTE_VERSION, reader.getUInt16(makernoteOffset)); 701 702 int major = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION); 703 int minor = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 2); 704 int revision = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 4); 705 String buildYear = String.format("%04X", reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 6)); 706 String buildDate = String.format("%04X", reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 8)); 707 String buildYearAndDate = buildYear + buildDate; 708 Integer build; 709 try { 710 build = Integer.parseInt(buildYearAndDate); 711 } catch (NumberFormatException e) { 712 build = null; 713 } 714 if (build != null) 715 { 716 directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d.%s", major, minor, revision, build)); 717 } 718 else 719 { 720 directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d", major, minor, revision)); 721 directory.addError("Error processing Reconyx HyperFire makernote data: build '" + buildYearAndDate + "' is not in the expected format and will be omitted from Firmware Version."); 722 } 723 724 directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_TRIGGER_MODE, String.valueOf((char)reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_TRIGGER_MODE))); 725 directory.setIntArray(ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE, 726 new int[] 727 { 728 reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE), 729 reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE + 2) 730 }); 731 732 int eventNumberHigh = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER); 733 int eventNumberLow = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER + 2); 734 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER, (eventNumberHigh << 16) + eventNumberLow); 735 736 int seconds = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL); 737 int minutes = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 2); 738 int hour = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 4); 739 int month = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 6); 740 int day = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 8); 741 int year = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 10); 742 743 if ((seconds >= 0 && seconds < 60) && 744 (minutes >= 0 && minutes < 60) && 745 (hour >= 0 && hour < 24) && 746 (month >= 1 && month < 13) && 747 (day >= 1 && day < 32) && 748 (year >= 1 && year <= 9999)) 749 { 750 directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL, 751 String.format("%4d:%2d:%2d %2d:%2d:%2d", year, month, day, hour, minutes, seconds)); 752 } 753 else 754 { 755 directory.addError("Error processing Reconyx HyperFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time."); 756 } 757 758 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_MOON_PHASE, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_MOON_PHASE)); 759 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE_FAHRENHEIT, reader.getInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE_FAHRENHEIT)); 760 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE, reader.getInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE)); 761 //directory.setByteArray(ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, reader.getBytes(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, 28)); 762 directory.setStringValue(ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, new StringValue(reader.getBytes(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, 28), Charsets.UTF_16LE)); 763 // two unread bytes: the serial number's terminating null 764 765 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_CONTRAST, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_CONTRAST)); 766 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_BRIGHTNESS, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_BRIGHTNESS)); 767 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_SHARPNESS, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SHARPNESS)); 768 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_SATURATION, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SATURATION)); 769 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_INFRARED_ILLUMINATOR, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_INFRARED_ILLUMINATOR)); 770 directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_MOTION_SENSITIVITY, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_MOTION_SENSITIVITY)); 771 directory.setDouble(ReconyxHyperFireMakernoteDirectory.TAG_BATTERY_VOLTAGE, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_BATTERY_VOLTAGE) / 1000.0); 772 directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_USER_LABEL, reader.getNullTerminatedString(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_USER_LABEL, 44, Charsets.UTF_8)); 773 } 774 775 private static void processReconyxUltraFireMakernote(@NotNull final ReconyxUltraFireMakernoteDirectory directory, final int makernoteOffset, @NotNull final RandomAccessReader reader) throws IOException 776 { 777 directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_LABEL, reader.getString(makernoteOffset, 9, Charsets.UTF_8)); 778 /*uint makernoteID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernoteID)); 779 directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernoteID, makernoteID); 780 if (makernoteID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_ID) 781 { 782 directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote ID 0x" + makernoteID.ToString("x8")); 783 return; 784 } 785 directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernoteSize, ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernoteSize))); 786 uint makernotePublicID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID)); 787 directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID, makernotePublicID); 788 if (makernotePublicID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_PUBLIC_ID) 789 { 790 directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote Public ID 0x" + makernotePublicID.ToString("x8")); 791 return; 792 }*/ 793 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernotePublicSize, ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernotePublicSize))); 794 795 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagCameraVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagCameraVersion, reader)); 796 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagUibVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagUibVersion, reader)); 797 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagBtlVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagBtlVersion, reader)); 798 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagPexVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagPexVersion, reader)); 799 800 directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_EVENT_TYPE, reader.getString(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_EVENT_TYPE, 1, Charsets.UTF_8)); 801 directory.setIntArray(ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE, 802 new int[] 803 { 804 reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE), 805 reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE + 1) 806 }); 807 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagEventNumber, ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagEventNumber))); 808 809 byte seconds = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL); 810 byte minutes = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 1); 811 byte hour = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 2); 812 byte day = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 3); 813 byte month = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 4); 814 /*ushort year = ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagDateTimeOriginal + 5)); 815 if ((seconds >= 0 && seconds < 60) && 816 (minutes >= 0 && minutes < 60) && 817 (hour >= 0 && hour < 24) && 818 (month >= 1 && month < 13) && 819 (day >= 1 && day < 32) && 820 (year >= 1 && year <= 9999)) 821 { 822 directory.Set(ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL, new DateTime(year, month, day, hour, minutes, seconds, DateTimeKind.Unspecified)); 823 } 824 else 825 { 826 directory.addError("Error processing Reconyx UltraFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time."); 827 }*/ 828 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagDayOfWeek, reader.GetByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagDayOfWeek)); 829 830 directory.setInt(ReconyxUltraFireMakernoteDirectory.TAG_MOON_PHASE, reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_MOON_PHASE)); 831 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagAmbientTemperatureFahrenheit, ByteConvert.FromBigEndianToNative(reader.GetInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagAmbientTemperatureFahrenheit))); 832 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagAmbientTemperature, ByteConvert.FromBigEndianToNative(reader.GetInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagAmbientTemperature))); 833 834 directory.setInt(ReconyxUltraFireMakernoteDirectory.TAG_FLASH, reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_FLASH)); 835 //directory.Set(ReconyxUltraFireMakernoteDirectory.TagBatteryVoltage, ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagBatteryVoltage)) / 1000.0); 836 directory.setStringValue(ReconyxUltraFireMakernoteDirectory.TAG_SERIAL_NUMBER, new StringValue(reader.getBytes(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SERIAL_NUMBER, 14), Charsets.UTF_8)); 837 // unread byte: the serial number's terminating null 838 directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_USER_LABEL, reader.getNullTerminatedString(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_USER_LABEL, 20, Charsets.UTF_8)); 839 } 396 840 } 397 841 -
trunk/src/com/drew/metadata/exif/GpsDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 36 36 * @author Drew Noakes https://drewnoakes.com 37 37 */ 38 @SuppressWarnings("WeakerAccess") 38 39 public class GpsDescriptor extends TagDescriptor<GpsDirectory> 39 40 { -
trunk/src/com/drew/metadata/exif/GpsDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 38 38 * @author Drew Noakes https://drewnoakes.com 39 39 */ 40 @SuppressWarnings("WeakerAccess") 40 41 public class GpsDirectory extends ExifDirectoryBase 41 42 { -
trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 26 26 27 27 import java.text.DecimalFormat; 28 import java.util.HashMap; 28 29 29 30 import static com.drew.metadata.exif.makernotes.CanonMakernoteDirectory.*; … … 34 35 * @author Drew Noakes https://drewnoakes.com 35 36 */ 37 @SuppressWarnings("WeakerAccess") 36 38 public class CanonMakernoteDescriptor extends TagDescriptor<CanonMakernoteDirectory> 37 39 { … … 54 56 case CameraSettings.TAG_DIGITAL_ZOOM: 55 57 return getDigitalZoomDescription(); 58 case CameraSettings.TAG_RECORD_MODE: 59 return getRecordModeDescription(); 56 60 case CameraSettings.TAG_QUALITY: 57 61 return getQualityDescription(); … … 102 106 case FocalLength.TAG_FLASH_BIAS: 103 107 return getFlashBiasDescription(); 108 case AFInfo.TAG_AF_POINTS_IN_FOCUS: 109 return getTagAfPointsInFocus(); 110 case CameraSettings.TAG_MAX_APERTURE: 111 return getMaxApertureDescription(); 112 case CameraSettings.TAG_MIN_APERTURE: 113 return getMinApertureDescription(); 114 case CameraSettings.TAG_FOCUS_CONTINUOUS: 115 return getFocusContinuousDescription(); 116 case CameraSettings.TAG_AE_SETTING: 117 return getAESettingDescription(); 118 case CanonMakernoteDirectory.CameraSettings.TAG_DISPLAY_APERTURE: 119 return getDisplayApertureDescription(); 120 case CanonMakernoteDirectory.CameraSettings.TAG_SPOT_METERING_MODE: 121 return getSpotMeteringModeDescription(); 122 case CanonMakernoteDirectory.CameraSettings.TAG_PHOTO_EFFECT: 123 return getPhotoEffectDescription(); 124 case CanonMakernoteDirectory.CameraSettings.TAG_MANUAL_FLASH_OUTPUT: 125 return getManualFlashOutputDescription(); 126 case CanonMakernoteDirectory.CameraSettings.TAG_COLOR_TONE: 127 return getColorToneDescription(); 128 case CanonMakernoteDirectory.CameraSettings.TAG_SRAW_QUALITY: 129 return getSRawQualityDescription(); 104 130 105 131 // It turns out that these values are dependent upon the camera model and therefore the below code was … … 346 372 // 0, 0.33, 0.5, 0.66, 1 347 373 348 return ( (isNegative)? "-" : "") + Float.toString(value / 32f) + " EV";374 return (isNegative ? "-" : "") + Float.toString(value / 32f) + " EV"; 349 375 } 350 376 … … 364 390 return "Unknown (" + value + ")"; 365 391 } 392 } 393 394 @Nullable 395 public String getTagAfPointsInFocus() 396 { 397 Integer value = _directory.getInteger(AFInfo.TAG_AF_POINTS_IN_FOCUS); 398 if (value == null) 399 return null; 400 401 StringBuilder sb = new StringBuilder(); 402 403 for (int i = 0; i < 16; i++) 404 { 405 if ((value & 1 << i) != 0) 406 { 407 if (sb.length() != 0) 408 sb.append(','); 409 sb.append(i); 410 } 411 } 412 413 return sb.length() == 0 ? "None" : sb.toString(); 366 414 } 367 415 … … 393 441 if (value == null) 394 442 return null; 395 if (((value >> 14) & 1) >0) {443 if (((value >> 14) & 1) != 0) { 396 444 return "External E-TTL"; 397 445 } 398 if (((value >> 13) & 1) >0) {446 if (((value >> 13) & 1) != 0) { 399 447 return "Internal flash"; 400 448 } 401 if (((value >> 11) & 1) >0) {449 if (((value >> 11) & 1) != 0) { 402 450 return "FP sync used"; 403 451 } 404 if (((value >> 4) & 1) >0) {452 if (((value >> 4) & 1) != 0) { 405 453 return "FP sync enabled"; 406 454 } … … 461 509 return null; 462 510 463 return "Lens type: " + Integer.toString(value); 511 return _lensTypeById.containsKey(value) 512 ? _lensTypeById.get(value) 513 : String.format("Unknown (%d)", value); 514 } 515 516 @Nullable 517 public String getMaxApertureDescription() 518 { 519 Integer value = _directory.getInteger(CameraSettings.TAG_MAX_APERTURE); 520 if (value == null) 521 return null; 522 if (value > 512) 523 return String.format("Unknown (%d)", value); 524 return getFStopDescription(Math.exp(decodeCanonEv(value) * Math.log(2.0) / 2.0)); 525 } 526 527 @Nullable 528 public String getMinApertureDescription() 529 { 530 Integer value = _directory.getInteger(CameraSettings.TAG_MIN_APERTURE); 531 if (value == null) 532 return null; 533 if (value > 512) 534 return String.format("Unknown (%d)", value); 535 return getFStopDescription(Math.exp(decodeCanonEv(value) * Math.log(2.0) / 2.0)); 464 536 } 465 537 … … 499 571 // Canon PowerShot S3 is special 500 572 int canonMask = 0x4000; 501 if ((value & canonMask) >0)573 if ((value & canonMask) != 0) 502 574 return "" + (value & ~canonMask); 503 575 … … 700 772 701 773 @Nullable 774 public String getRecordModeDescription() 775 { 776 return getIndexedDescription(CameraSettings.TAG_RECORD_MODE, 1, "JPEG", "CRW+THM", "AVI+THM", "TIF", "TIF+JPEG", "CR2", "CR2+JPEG", null, "MOV", "MP4"); 777 } 778 779 @Nullable 702 780 public String getFocusTypeDescription() 703 781 { … … 724 802 return getIndexedDescription(CameraSettings.TAG_FLASH_ACTIVITY, "Flash did not fire", "Flash fired"); 725 803 } 804 805 @Nullable 806 public String getFocusContinuousDescription() 807 { 808 return getIndexedDescription(CameraSettings.TAG_FOCUS_CONTINUOUS, 0, 809 "Single", "Continuous", null, null, null, null, null, null, "Manual"); 810 } 811 812 @Nullable 813 public String getAESettingDescription() 814 { 815 return getIndexedDescription(CameraSettings.TAG_AE_SETTING, 0, 816 "Normal AE", "Exposure Compensation", "AE Lock", "AE Lock + Exposure Comp.", "No AE"); 817 } 818 819 @Nullable 820 public String getDisplayApertureDescription() 821 { 822 Integer value = _directory.getInteger(CameraSettings.TAG_DISPLAY_APERTURE); 823 if (value == null) 824 return null; 825 826 if (value == 0xFFFF) 827 return value.toString(); 828 return getFStopDescription(value / 10f); 829 } 830 831 @Nullable 832 public String getSpotMeteringModeDescription() 833 { 834 return getIndexedDescription(CanonMakernoteDirectory.CameraSettings.TAG_SPOT_METERING_MODE, 0, 835 "Center", "AF Point"); 836 } 837 838 @Nullable 839 public String getPhotoEffectDescription() 840 { 841 Integer value = _directory.getInteger(CameraSettings.TAG_PHOTO_EFFECT); 842 if (value == null) 843 return null; 844 845 switch (value) 846 { 847 case 0: 848 return "Off"; 849 case 1: 850 return "Vivid"; 851 case 2: 852 return "Neutral"; 853 case 3: 854 return "Smooth"; 855 case 4: 856 return "Sepia"; 857 case 5: 858 return "B&W"; 859 case 6: 860 return "Custom"; 861 case 100: 862 return "My Color Data"; 863 default: 864 return "Unknown (" + value + ")"; 865 } 866 } 867 868 @Nullable 869 public String getManualFlashOutputDescription() 870 { 871 Integer value = _directory.getInteger(CameraSettings.TAG_MANUAL_FLASH_OUTPUT); 872 if (value == null) 873 return null; 874 875 switch (value) 876 { 877 case 0: 878 return "n/a"; 879 case 0x500: 880 return "Full"; 881 case 0x502: 882 return "Medium"; 883 case 0x504: 884 return "Low"; 885 case 0x7fff: 886 return "n/a"; // (EOS models) 887 default: 888 return "Unknown (" + value + ")"; 889 } 890 } 891 892 @Nullable 893 public String getColorToneDescription() 894 { 895 Integer value = _directory.getInteger(CameraSettings.TAG_COLOR_TONE); 896 if (value == null) 897 return null; 898 899 return value == 0x7fff ? "n/a" : value.toString(); 900 } 901 902 @Nullable 903 public String getSRawQualityDescription() 904 { 905 return getIndexedDescription(CanonMakernoteDirectory.CameraSettings.TAG_SRAW_QUALITY, 0, "n/a", "sRAW1 (mRAW)", "sRAW2 (sRAW)"); 906 } 907 908 /** 909 * Canon hex-based EV (modulo 0x20) to real number. 910 * 911 * Converted from Exiftool version 10.10 created by Phil Harvey 912 * http://www.sno.phy.queensu.ca/~phil/exiftool/ 913 * lib\Image\ExifTool\Canon.pm 914 * 915 * eg) 0x00 -> 0 916 * 0x0c -> 0.33333 917 * 0x10 -> 0.5 918 * 0x14 -> 0.66666 919 * 0x20 -> 1 ... etc 920 */ 921 private double decodeCanonEv(int val) 922 { 923 int sign = 1; 924 if (val < 0) 925 { 926 val = -val; 927 sign = -1; 928 } 929 930 int frac = val & 0x1f; 931 val -= frac; 932 933 if (frac == 0x0c) 934 frac = 0x20 / 3; 935 else if (frac == 0x14) 936 frac = 0x40 / 3; 937 938 return sign * (val + frac) / (double)0x20; 939 } 940 941 /** 942 * Map from <see cref="CanonMakernoteDirectory.CameraSettings.TagLensType"/> to string descriptions. 943 * 944 * Data sourced from http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html#LensType 945 * 946 * Note that only Canon lenses are listed. Lenses from other manufacturers may identify themselves to the camera 947 * as being from this set, but in fact may be quite different. This limits the usefulness of this data, 948 * unfortunately. 949 */ 950 private static final HashMap<Integer, String> _lensTypeById = new HashMap<Integer, String>(); 951 952 static { 953 _lensTypeById.put(1, "Canon EF 50mm f/1.8"); 954 _lensTypeById.put(2, "Canon EF 28mm f/2.8"); 955 _lensTypeById.put(3, "Canon EF 135mm f/2.8 Soft"); 956 _lensTypeById.put(4, "Canon EF 35-105mm f/3.5-4.5 or Sigma Lens"); 957 _lensTypeById.put(5, "Canon EF 35-70mm f/3.5-4.5"); 958 _lensTypeById.put(6, "Canon EF 28-70mm f/3.5-4.5 or Sigma or Tokina Lens"); 959 _lensTypeById.put(7, "Canon EF 100-300mm f/5.6L"); 960 _lensTypeById.put(8, "Canon EF 100-300mm f/5.6 or Sigma or Tokina Lens"); 961 _lensTypeById.put(9, "Canon EF 70-210mm f/4"); 962 _lensTypeById.put(10, "Canon EF 50mm f/2.5 Macro or Sigma Lens"); 963 _lensTypeById.put(11, "Canon EF 35mm f/2"); 964 _lensTypeById.put(13, "Canon EF 15mm f/2.8 Fisheye"); 965 _lensTypeById.put(14, "Canon EF 50-200mm f/3.5-4.5L"); 966 _lensTypeById.put(15, "Canon EF 50-200mm f/3.5-4.5"); 967 _lensTypeById.put(16, "Canon EF 35-135mm f/3.5-4.5"); 968 _lensTypeById.put(17, "Canon EF 35-70mm f/3.5-4.5A"); 969 _lensTypeById.put(18, "Canon EF 28-70mm f/3.5-4.5"); 970 _lensTypeById.put(20, "Canon EF 100-200mm f/4.5A"); 971 _lensTypeById.put(21, "Canon EF 80-200mm f/2.8L"); 972 _lensTypeById.put(22, "Canon EF 20-35mm f/2.8L or Tokina Lens"); 973 _lensTypeById.put(23, "Canon EF 35-105mm f/3.5-4.5"); 974 _lensTypeById.put(24, "Canon EF 35-80mm f/4-5.6 Power Zoom"); 975 _lensTypeById.put(25, "Canon EF 35-80mm f/4-5.6 Power Zoom"); 976 _lensTypeById.put(26, "Canon EF 100mm f/2.8 Macro or Other Lens"); 977 _lensTypeById.put(27, "Canon EF 35-80mm f/4-5.6"); 978 _lensTypeById.put(28, "Canon EF 80-200mm f/4.5-5.6 or Tamron Lens"); 979 _lensTypeById.put(29, "Canon EF 50mm f/1.8 II"); 980 _lensTypeById.put(30, "Canon EF 35-105mm f/4.5-5.6"); 981 _lensTypeById.put(31, "Canon EF 75-300mm f/4-5.6 or Tamron Lens"); 982 _lensTypeById.put(32, "Canon EF 24mm f/2.8 or Sigma Lens"); 983 _lensTypeById.put(33, "Voigtlander or Carl Zeiss Lens"); 984 _lensTypeById.put(35, "Canon EF 35-80mm f/4-5.6"); 985 _lensTypeById.put(36, "Canon EF 38-76mm f/4.5-5.6"); 986 _lensTypeById.put(37, "Canon EF 35-80mm f/4-5.6 or Tamron Lens"); 987 _lensTypeById.put(38, "Canon EF 80-200mm f/4.5-5.6"); 988 _lensTypeById.put(39, "Canon EF 75-300mm f/4-5.6"); 989 _lensTypeById.put(40, "Canon EF 28-80mm f/3.5-5.6"); 990 _lensTypeById.put(41, "Canon EF 28-90mm f/4-5.6"); 991 _lensTypeById.put(42, "Canon EF 28-200mm f/3.5-5.6 or Tamron Lens"); 992 _lensTypeById.put(43, "Canon EF 28-105mm f/4-5.6"); 993 _lensTypeById.put(44, "Canon EF 90-300mm f/4.5-5.6"); 994 _lensTypeById.put(45, "Canon EF-S 18-55mm f/3.5-5.6 [II]"); 995 _lensTypeById.put(46, "Canon EF 28-90mm f/4-5.6"); 996 _lensTypeById.put(47, "Zeiss Milvus 35mm f/2 or 50mm f/2"); 997 _lensTypeById.put(48, "Canon EF-S 18-55mm f/3.5-5.6 IS"); 998 _lensTypeById.put(49, "Canon EF-S 55-250mm f/4-5.6 IS"); 999 _lensTypeById.put(50, "Canon EF-S 18-200mm f/3.5-5.6 IS"); 1000 _lensTypeById.put(51, "Canon EF-S 18-135mm f/3.5-5.6 IS"); 1001 _lensTypeById.put(52, "Canon EF-S 18-55mm f/3.5-5.6 IS II"); 1002 _lensTypeById.put(53, "Canon EF-S 18-55mm f/3.5-5.6 III"); 1003 _lensTypeById.put(54, "Canon EF-S 55-250mm f/4-5.6 IS II"); 1004 _lensTypeById.put(94, "Canon TS-E 17mm f/4L"); 1005 _lensTypeById.put(95, "Canon TS-E 24.0mm f/3.5 L II"); 1006 _lensTypeById.put(124, "Canon MP-E 65mm f/2.8 1-5x Macro Photo"); 1007 _lensTypeById.put(125, "Canon TS-E 24mm f/3.5L"); 1008 _lensTypeById.put(126, "Canon TS-E 45mm f/2.8"); 1009 _lensTypeById.put(127, "Canon TS-E 90mm f/2.8"); 1010 _lensTypeById.put(129, "Canon EF 300mm f/2.8L"); 1011 _lensTypeById.put(130, "Canon EF 50mm f/1.0L"); 1012 _lensTypeById.put(131, "Canon EF 28-80mm f/2.8-4L or Sigma Lens"); 1013 _lensTypeById.put(132, "Canon EF 1200mm f/5.6L"); 1014 _lensTypeById.put(134, "Canon EF 600mm f/4L IS"); 1015 _lensTypeById.put(135, "Canon EF 200mm f/1.8L"); 1016 _lensTypeById.put(136, "Canon EF 300mm f/2.8L"); 1017 _lensTypeById.put(137, "Canon EF 85mm f/1.2L or Sigma or Tamron Lens"); 1018 _lensTypeById.put(138, "Canon EF 28-80mm f/2.8-4L"); 1019 _lensTypeById.put(139, "Canon EF 400mm f/2.8L"); 1020 _lensTypeById.put(140, "Canon EF 500mm f/4.5L"); 1021 _lensTypeById.put(141, "Canon EF 500mm f/4.5L"); 1022 _lensTypeById.put(142, "Canon EF 300mm f/2.8L IS"); 1023 _lensTypeById.put(143, "Canon EF 500mm f/4L IS or Sigma Lens"); 1024 _lensTypeById.put(144, "Canon EF 35-135mm f/4-5.6 USM"); 1025 _lensTypeById.put(145, "Canon EF 100-300mm f/4.5-5.6 USM"); 1026 _lensTypeById.put(146, "Canon EF 70-210mm f/3.5-4.5 USM"); 1027 _lensTypeById.put(147, "Canon EF 35-135mm f/4-5.6 USM"); 1028 _lensTypeById.put(148, "Canon EF 28-80mm f/3.5-5.6 USM"); 1029 _lensTypeById.put(149, "Canon EF 100mm f/2 USM"); 1030 _lensTypeById.put(150, "Canon EF 14mm f/2.8L or Sigma Lens"); 1031 _lensTypeById.put(151, "Canon EF 200mm f/2.8L"); 1032 _lensTypeById.put(152, "Canon EF 300mm f/4L IS or Sigma Lens"); 1033 _lensTypeById.put(153, "Canon EF 35-350mm f/3.5-5.6L or Sigma or Tamron Lens"); 1034 _lensTypeById.put(154, "Canon EF 20mm f/2.8 USM or Zeiss Lens"); 1035 _lensTypeById.put(155, "Canon EF 85mm f/1.8 USM"); 1036 _lensTypeById.put(156, "Canon EF 28-105mm f/3.5-4.5 USM or Tamron Lens"); 1037 _lensTypeById.put(160, "Canon EF 20-35mm f/3.5-4.5 USM or Tamron or Tokina Lens"); 1038 _lensTypeById.put(161, "Canon EF 28-70mm f/2.8L or Sigma or Tamron Lens"); 1039 _lensTypeById.put(162, "Canon EF 200mm f/2.8L"); 1040 _lensTypeById.put(163, "Canon EF 300mm f/4L"); 1041 _lensTypeById.put(164, "Canon EF 400mm f/5.6L"); 1042 _lensTypeById.put(165, "Canon EF 70-200mm f/2.8 L"); 1043 _lensTypeById.put(166, "Canon EF 70-200mm f/2.8 L + 1.4x"); 1044 _lensTypeById.put(167, "Canon EF 70-200mm f/2.8 L + 2x"); 1045 _lensTypeById.put(168, "Canon EF 28mm f/1.8 USM or Sigma Lens"); 1046 _lensTypeById.put(169, "Canon EF 17-35mm f/2.8L or Sigma Lens"); 1047 _lensTypeById.put(170, "Canon EF 200mm f/2.8L II"); 1048 _lensTypeById.put(171, "Canon EF 300mm f/4L"); 1049 _lensTypeById.put(172, "Canon EF 400mm f/5.6L or Sigma Lens"); 1050 _lensTypeById.put(173, "Canon EF 180mm Macro f/3.5L or Sigma Lens"); 1051 _lensTypeById.put(174, "Canon EF 135mm f/2L or Other Lens"); 1052 _lensTypeById.put(175, "Canon EF 400mm f/2.8L"); 1053 _lensTypeById.put(176, "Canon EF 24-85mm f/3.5-4.5 USM"); 1054 _lensTypeById.put(177, "Canon EF 300mm f/4L IS"); 1055 _lensTypeById.put(178, "Canon EF 28-135mm f/3.5-5.6 IS"); 1056 _lensTypeById.put(179, "Canon EF 24mm f/1.4L"); 1057 _lensTypeById.put(180, "Canon EF 35mm f/1.4L or Other Lens"); 1058 _lensTypeById.put(181, "Canon EF 100-400mm f/4.5-5.6L IS + 1.4x or Sigma Lens"); 1059 _lensTypeById.put(182, "Canon EF 100-400mm f/4.5-5.6L IS + 2x or Sigma Lens"); 1060 _lensTypeById.put(183, "Canon EF 100-400mm f/4.5-5.6L IS or Sigma Lens"); 1061 _lensTypeById.put(184, "Canon EF 400mm f/2.8L + 2x"); 1062 _lensTypeById.put(185, "Canon EF 600mm f/4L IS"); 1063 _lensTypeById.put(186, "Canon EF 70-200mm f/4L"); 1064 _lensTypeById.put(187, "Canon EF 70-200mm f/4L + 1.4x"); 1065 _lensTypeById.put(188, "Canon EF 70-200mm f/4L + 2x"); 1066 _lensTypeById.put(189, "Canon EF 70-200mm f/4L + 2.8x"); 1067 _lensTypeById.put(190, "Canon EF 100mm f/2.8 Macro USM"); 1068 _lensTypeById.put(191, "Canon EF 400mm f/4 DO IS"); 1069 _lensTypeById.put(193, "Canon EF 35-80mm f/4-5.6 USM"); 1070 _lensTypeById.put(194, "Canon EF 80-200mm f/4.5-5.6 USM"); 1071 _lensTypeById.put(195, "Canon EF 35-105mm f/4.5-5.6 USM"); 1072 _lensTypeById.put(196, "Canon EF 75-300mm f/4-5.6 USM"); 1073 _lensTypeById.put(197, "Canon EF 75-300mm f/4-5.6 IS USM"); 1074 _lensTypeById.put(198, "Canon EF 50mm f/1.4 USM or Zeiss Lens"); 1075 _lensTypeById.put(199, "Canon EF 28-80mm f/3.5-5.6 USM"); 1076 _lensTypeById.put(200, "Canon EF 75-300mm f/4-5.6 USM"); 1077 _lensTypeById.put(201, "Canon EF 28-80mm f/3.5-5.6 USM"); 1078 _lensTypeById.put(202, "Canon EF 28-80mm f/3.5-5.6 USM IV"); 1079 _lensTypeById.put(208, "Canon EF 22-55mm f/4-5.6 USM"); 1080 _lensTypeById.put(209, "Canon EF 55-200mm f/4.5-5.6"); 1081 _lensTypeById.put(210, "Canon EF 28-90mm f/4-5.6 USM"); 1082 _lensTypeById.put(211, "Canon EF 28-200mm f/3.5-5.6 USM"); 1083 _lensTypeById.put(212, "Canon EF 28-105mm f/4-5.6 USM"); 1084 _lensTypeById.put(213, "Canon EF 90-300mm f/4.5-5.6 USM or Tamron Lens"); 1085 _lensTypeById.put(214, "Canon EF-S 18-55mm f/3.5-5.6 USM"); 1086 _lensTypeById.put(215, "Canon EF 55-200mm f/4.5-5.6 II USM"); 1087 _lensTypeById.put(217, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD"); 1088 _lensTypeById.put(224, "Canon EF 70-200mm f/2.8L IS"); 1089 _lensTypeById.put(225, "Canon EF 70-200mm f/2.8L IS + 1.4x"); 1090 _lensTypeById.put(226, "Canon EF 70-200mm f/2.8L IS + 2x"); 1091 _lensTypeById.put(227, "Canon EF 70-200mm f/2.8L IS + 2.8x"); 1092 _lensTypeById.put(228, "Canon EF 28-105mm f/3.5-4.5 USM"); 1093 _lensTypeById.put(229, "Canon EF 16-35mm f/2.8L"); 1094 _lensTypeById.put(230, "Canon EF 24-70mm f/2.8L"); 1095 _lensTypeById.put(231, "Canon EF 17-40mm f/4L"); 1096 _lensTypeById.put(232, "Canon EF 70-300mm f/4.5-5.6 DO IS USM"); 1097 _lensTypeById.put(233, "Canon EF 28-300mm f/3.5-5.6L IS"); 1098 _lensTypeById.put(234, "Canon EF-S 17-85mm f/4-5.6 IS USM or Tokina Lens"); 1099 _lensTypeById.put(235, "Canon EF-S 10-22mm f/3.5-4.5 USM"); 1100 _lensTypeById.put(236, "Canon EF-S 60mm f/2.8 Macro USM"); 1101 _lensTypeById.put(237, "Canon EF 24-105mm f/4L IS"); 1102 _lensTypeById.put(238, "Canon EF 70-300mm f/4-5.6 IS USM"); 1103 _lensTypeById.put(239, "Canon EF 85mm f/1.2L II"); 1104 _lensTypeById.put(240, "Canon EF-S 17-55mm f/2.8 IS USM"); 1105 _lensTypeById.put(241, "Canon EF 50mm f/1.2L"); 1106 _lensTypeById.put(242, "Canon EF 70-200mm f/4L IS"); 1107 _lensTypeById.put(243, "Canon EF 70-200mm f/4L IS + 1.4x"); 1108 _lensTypeById.put(244, "Canon EF 70-200mm f/4L IS + 2x"); 1109 _lensTypeById.put(245, "Canon EF 70-200mm f/4L IS + 2.8x"); 1110 _lensTypeById.put(246, "Canon EF 16-35mm f/2.8L II"); 1111 _lensTypeById.put(247, "Canon EF 14mm f/2.8L II USM"); 1112 _lensTypeById.put(248, "Canon EF 200mm f/2L IS or Sigma Lens"); 1113 _lensTypeById.put(249, "Canon EF 800mm f/5.6L IS"); 1114 _lensTypeById.put(250, "Canon EF 24mm f/1.4L II or Sigma Lens"); 1115 _lensTypeById.put(251, "Canon EF 70-200mm f/2.8L IS II USM"); 1116 _lensTypeById.put(252, "Canon EF 70-200mm f/2.8L IS II USM + 1.4x"); 1117 _lensTypeById.put(253, "Canon EF 70-200mm f/2.8L IS II USM + 2x"); 1118 _lensTypeById.put(254, "Canon EF 100mm f/2.8L Macro IS USM"); 1119 _lensTypeById.put(255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens"); 1120 _lensTypeById.put(488, "Canon EF-S 15-85mm f/3.5-5.6 IS USM"); 1121 _lensTypeById.put(489, "Canon EF 70-300mm f/4-5.6L IS USM"); 1122 _lensTypeById.put(490, "Canon EF 8-15mm f/4L Fisheye USM"); 1123 _lensTypeById.put(491, "Canon EF 300mm f/2.8L IS II USM"); 1124 _lensTypeById.put(492, "Canon EF 400mm f/2.8L IS II USM"); 1125 _lensTypeById.put(493, "Canon EF 500mm f/4L IS II USM or EF 24-105mm f4L IS USM"); 1126 _lensTypeById.put(494, "Canon EF 600mm f/4.0L IS II USM"); 1127 _lensTypeById.put(495, "Canon EF 24-70mm f/2.8L II USM"); 1128 _lensTypeById.put(496, "Canon EF 200-400mm f/4L IS USM"); 1129 _lensTypeById.put(499, "Canon EF 200-400mm f/4L IS USM + 1.4x"); 1130 _lensTypeById.put(502, "Canon EF 28mm f/2.8 IS USM"); 1131 _lensTypeById.put(503, "Canon EF 24mm f/2.8 IS USM"); 1132 _lensTypeById.put(504, "Canon EF 24-70mm f/4L IS USM"); 1133 _lensTypeById.put(505, "Canon EF 35mm f/2 IS USM"); 1134 _lensTypeById.put(506, "Canon EF 400mm f/4 DO IS II USM"); 1135 _lensTypeById.put(507, "Canon EF 16-35mm f/4L IS USM"); 1136 _lensTypeById.put(508, "Canon EF 11-24mm f/4L USM"); 1137 _lensTypeById.put(747, "Canon EF 100-400mm f/4.5-5.6L IS II USM"); 1138 _lensTypeById.put(750, "Canon EF 35mm f/1.4L II USM"); 1139 _lensTypeById.put(4142, "Canon EF-S 18-135mm f/3.5-5.6 IS STM"); 1140 _lensTypeById.put(4143, "Canon EF-M 18-55mm f/3.5-5.6 IS STM or Tamron Lens"); 1141 _lensTypeById.put(4144, "Canon EF 40mm f/2.8 STM"); 1142 _lensTypeById.put(4145, "Canon EF-M 22mm f/2 STM"); 1143 _lensTypeById.put(4146, "Canon EF-S 18-55mm f/3.5-5.6 IS STM"); 1144 _lensTypeById.put(4147, "Canon EF-M 11-22mm f/4-5.6 IS STM"); 1145 _lensTypeById.put(4148, "Canon EF-S 55-250mm f/4-5.6 IS STM"); 1146 _lensTypeById.put(4149, "Canon EF-M 55-200mm f/4.5-6.3 IS STM"); 1147 _lensTypeById.put(4150, "Canon EF-S 10-18mm f/4.5-5.6 IS STM"); 1148 _lensTypeById.put(4152, "Canon EF 24-105mm f/3.5-5.6 IS STM"); 1149 _lensTypeById.put(4153, "Canon EF-M 15-45mm f/3.5-6.3 IS STM"); 1150 _lensTypeById.put(4154, "Canon EF-S 24mm f/2.8 STM"); 1151 _lensTypeById.put(4156, "Canon EF 50mm f/1.8 STM"); 1152 _lensTypeById.put(36912, "Canon EF-S 18-135mm f/3.5-5.6 IS USM"); 1153 _lensTypeById.put(65535, "N/A"); 1154 } 726 1155 } -
trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 35 35 * @author Drew Noakes https://drewnoakes.com 36 36 */ 37 @SuppressWarnings("WeakerAccess") 37 38 public class CanonMakernoteDirectory extends Directory 38 39 { … … 159 160 public static final int TAG_FOCUS_MODE_1 = OFFSET + 0x07; 160 161 public static final int TAG_UNKNOWN_3 = OFFSET + 0x08; 161 public static final int TAG_ UNKNOWN_4= OFFSET + 0x09;162 public static final int TAG_RECORD_MODE = OFFSET + 0x09; 162 163 /** 163 164 * 0 = Large … … 249 250 public static final int TAG_SHORT_FOCAL_LENGTH = OFFSET + 0x18; 250 251 public static final int TAG_FOCAL_UNITS_PER_MM = OFFSET + 0x19; 251 public static final int TAG_ UNKNOWN_9= OFFSET + 0x1A;252 public static final int TAG_ UNKNOWN_10= OFFSET + 0x1B;252 public static final int TAG_MAX_APERTURE = OFFSET + 0x1A; 253 public static final int TAG_MIN_APERTURE = OFFSET + 0x1B; 253 254 /** 254 255 * 0 = Flash Did Not Fire … … 257 258 public static final int TAG_FLASH_ACTIVITY = OFFSET + 0x1C; 258 259 public static final int TAG_FLASH_DETAILS = OFFSET + 0x1D; 259 public static final int TAG_ UNKNOWN_12= OFFSET + 0x1E;260 public static final int TAG_ UNKNOWN_13= OFFSET + 0x1F;260 public static final int TAG_FOCUS_CONTINUOUS = OFFSET + 0x1E; 261 public static final int TAG_AE_SETTING = OFFSET + 0x1F; 261 262 /** 262 263 * 0 = Focus Mode: Single … … 264 265 */ 265 266 public static final int TAG_FOCUS_MODE_2 = OFFSET + 0x20; 267 268 public static final int TAG_DISPLAY_APERTURE = OFFSET + 0x21; 269 public static final int TAG_ZOOM_SOURCE_WIDTH = OFFSET + 0x22; 270 public static final int TAG_ZOOM_TARGET_WIDTH = OFFSET + 0x23; 271 272 public static final int TAG_SPOT_METERING_MODE = OFFSET + 0x25; 273 public static final int TAG_PHOTO_EFFECT = OFFSET + 0x26; 274 public static final int TAG_MANUAL_FLASH_OUTPUT = OFFSET + 0x27; 275 276 public static final int TAG_COLOR_TONE = OFFSET + 0x29; 277 public static final int TAG_SRAW_QUALITY = OFFSET + 0x2D; 266 278 } 267 279 … … 515 527 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_2, "Unknown Camera Setting 2"); 516 528 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_3, "Unknown Camera Setting 3"); 517 _tagNameMap.put(CameraSettings.TAG_ UNKNOWN_4, "Unknown Camera Setting 4");529 _tagNameMap.put(CameraSettings.TAG_RECORD_MODE, "Record Mode"); 518 530 _tagNameMap.put(CameraSettings.TAG_DIGITAL_ZOOM, "Digital Zoom"); 519 531 _tagNameMap.put(CameraSettings.TAG_FOCUS_TYPE, "Focus Type"); 520 532 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_7, "Unknown Camera Setting 7"); 521 533 _tagNameMap.put(CameraSettings.TAG_LENS_TYPE, "Lens Type"); 522 _tagNameMap.put(CameraSettings.TAG_ UNKNOWN_9, "Unknown Camera Setting 9");523 _tagNameMap.put(CameraSettings.TAG_ UNKNOWN_10, "Unknown Camera Setting 10");534 _tagNameMap.put(CameraSettings.TAG_MAX_APERTURE, "Max Aperture"); 535 _tagNameMap.put(CameraSettings.TAG_MIN_APERTURE, "Min Aperture"); 524 536 _tagNameMap.put(CameraSettings.TAG_FLASH_ACTIVITY, "Flash Activity"); 525 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_12, "Unknown Camera Setting 12"); 526 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_13, "Unknown Camera Setting 13"); 537 _tagNameMap.put(CameraSettings.TAG_FOCUS_CONTINUOUS, "Focus Continuous"); 538 _tagNameMap.put(CameraSettings.TAG_AE_SETTING, "AE Setting"); 539 _tagNameMap.put(CameraSettings.TAG_DISPLAY_APERTURE, "Display Aperture"); 540 _tagNameMap.put(CameraSettings.TAG_ZOOM_SOURCE_WIDTH, "Zoom Source Width"); 541 _tagNameMap.put(CameraSettings.TAG_ZOOM_TARGET_WIDTH, "Zoom Target Width"); 542 _tagNameMap.put(CameraSettings.TAG_SPOT_METERING_MODE, "Spot Metering Mode"); 543 _tagNameMap.put(CameraSettings.TAG_PHOTO_EFFECT, "Photo Effect"); 544 _tagNameMap.put(CameraSettings.TAG_MANUAL_FLASH_OUTPUT, "Manual Flash Output"); 545 _tagNameMap.put(CameraSettings.TAG_COLOR_TONE, "Color Tone"); 546 _tagNameMap.put(CameraSettings.TAG_SRAW_QUALITY, "SRAW Quality"); 527 547 528 548 _tagNameMap.put(FocalLength.TAG_WHITE_BALANCE, "White Balance"); … … 576 596 _tagNameMap.put(AFInfo.TAG_AF_AREA_X_POSITIONS, "AF Area X Positions"); 577 597 _tagNameMap.put(AFInfo.TAG_AF_AREA_Y_POSITIONS, "AF Area Y Positions"); 578 _tagNameMap.put(AFInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus Count");598 _tagNameMap.put(AFInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus"); 579 599 _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_1, "Primary AF Point 1"); 580 600 _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_2, "Primary AF Point 2"); … … 672 692 // TODO is there some way to drop out 'null' or 'zero' values that are present in the array to reduce the noise? 673 693 694 if (!(array instanceof int[])) { 695 // no special handling... 696 super.setObjectArray(tagType, array); 697 return; 698 } 699 674 700 // Certain Canon tags contain arrays of values that we split into 'fake' tags as each 675 701 // index in the array has its own meaning and decoding. … … 709 735 // break; 710 736 case TAG_AF_INFO_ARRAY: { 711 int[] ints = (int[])array; 712 for (int i = 0; i < ints.length; i++) 713 setInt(AFInfo.OFFSET + i, ints[i]); 737 // Notes from Exiftool 10.10 by Phil Harvey, lib\Image\Exiftool\Canon.pm: 738 // Auto-focus information used by many older Canon models. The values in this 739 // record are sequential, and some have variable sizes based on the value of 740 // numafpoints (which may be 1,5,7,9,15,45, or 53). The AFArea coordinates are 741 // given in a system where the image has dimensions given by AFImageWidth and 742 // AFImageHeight, and 0,0 is the image center. The direction of the Y axis 743 // depends on the camera model, with positive Y upwards for EOS models, but 744 // apparently downwards for PowerShot models. 745 746 // AFInfo is another array with 'fake' tags. The first int of the array contains 747 // the number of AF points. Iterate through the array one byte at a time, generally 748 // assuming one byte corresponds to one tag UNLESS certain tag numbers are encountered. 749 // For these, read specific subsequent bytes from the array based on the tag type. The 750 // number of bytes read can vary. 751 752 int[] values = (int[])array; 753 int numafpoints = values[0]; 754 int tagnumber = 0; 755 for (int i = 0; i < values.length; i++) 756 { 757 // These two tags store 'numafpoints' bytes of data in the array 758 if (AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_AREA_X_POSITIONS || 759 AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_AREA_Y_POSITIONS) 760 { 761 // There could be incorrect data in the array, so boundary check 762 if (values.length - 1 >= (i + numafpoints)) 763 { 764 short[] areaPositions = new short[numafpoints]; 765 for (int j = 0; j < areaPositions.length; j++) 766 areaPositions[j] = (short)values[i + j]; 767 768 super.setObjectArray(AFInfo.OFFSET + tagnumber, areaPositions); 769 } 770 i += numafpoints - 1; // assume these bytes are processed and skip 771 } 772 else if (AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_POINTS_IN_FOCUS) 773 { 774 short[] pointsInFocus = new short[((numafpoints + 15) / 16)]; 775 776 // There could be incorrect data in the array, so boundary check 777 if (values.length - 1 >= (i + pointsInFocus.length)) 778 { 779 for (int j = 0; j < pointsInFocus.length; j++) 780 pointsInFocus[j] = (short)values[i + j]; 781 782 super.setObjectArray(AFInfo.OFFSET + tagnumber, pointsInFocus); 783 } 784 i += pointsInFocus.length - 1; // assume these bytes are processed and skip 785 } 786 else 787 super.setObjectArray(AFInfo.OFFSET + tagnumber, values[i]); 788 tagnumber++; 789 } 714 790 break; 715 791 } -
trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class CasioType1MakernoteDescriptor extends TagDescriptor<CasioType1MakernoteDirectory> 35 36 { -
trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 34 34 * @author Drew Noakes https://drewnoakes.com 35 35 */ 36 @SuppressWarnings("WeakerAccess") 36 37 public class CasioType1MakernoteDirectory extends Directory 37 38 { -
trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class CasioType2MakernoteDescriptor extends TagDescriptor<CasioType2MakernoteDirectory> 35 36 { … … 68 69 case TAG_SHARPNESS: 69 70 return getSharpnessDescription(); 70 case TAG_PRINT_IMAGE_MATCHING_INFO:71 return getPrintImageMatchingInfoDescription();72 71 case TAG_PREVIEW_THUMBNAIL: 73 72 return getCasioPreviewThumbnailDescription(); … … 212 211 213 212 @Nullable 214 public String getPrintImageMatchingInfoDescription()215 {216 // TODO research PIM specification http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html217 return _directory.getString(TAG_PRINT_IMAGE_MATCHING_INFO);218 }219 220 @Nullable221 213 public String getSharpnessDescription() 222 214 { -
trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 34 34 * @author Drew Noakes https://drewnoakes.com 35 35 */ 36 @SuppressWarnings("WeakerAccess") 36 37 public class CasioType2MakernoteDirectory extends Directory 37 38 { -
trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 49 49 * @author Drew Noakes https://drewnoakes.com 50 50 */ 51 @SuppressWarnings("WeakerAccess") 51 52 public class FujifilmMakernoteDescriptor extends TagDescriptor<FujifilmMakernoteDirectory> 52 53 { -
trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class FujifilmMakernoteDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class KodakMakernoteDescriptor extends TagDescriptor<KodakMakernoteDirectory> 35 36 { -
trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class KodakMakernoteDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 39 39 * @author Drew Noakes https://drewnoakes.com 40 40 */ 41 @SuppressWarnings("WeakerAccess") 41 42 public class KyoceraMakernoteDescriptor extends TagDescriptor<KyoceraMakernoteDirectory> 42 43 { … … 51 52 { 52 53 switch (tagType) { 53 case TAG_PRINT_IMAGE_MATCHING_INFO:54 return getPrintImageMatchingInfoDescription();55 54 case TAG_PROPRIETARY_THUMBNAIL: 56 55 return getProprietaryThumbnailDataDescription(); … … 61 60 62 61 @Nullable 63 public String getPrintImageMatchingInfoDescription()64 {65 return getByteLengthDescription(TAG_PRINT_IMAGE_MATCHING_INFO);66 }67 68 @Nullable69 62 public String getProprietaryThumbnailDataDescription() 70 63 { -
trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class KyoceraMakernoteDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 34 34 * @author Drew Noakes https://drewnoakes.com 35 35 */ 36 @SuppressWarnings("WeakerAccess") 36 37 public class LeicaMakernoteDescriptor extends TagDescriptor<LeicaMakernoteDirectory> 37 38 { -
trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class LeicaMakernoteDirectory extends Directory 36 37 { -
trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 44 44 * @author Drew Noakes https://drewnoakes.com 45 45 */ 46 @SuppressWarnings("WeakerAccess") 46 47 public class NikonType1MakernoteDescriptor extends TagDescriptor<NikonType1MakernoteDirectory> 47 48 { -
trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 40 40 * @author Drew Noakes https://drewnoakes.com 41 41 */ 42 @SuppressWarnings("WeakerAccess") 42 43 public class NikonType1MakernoteDirectory extends Directory 43 44 { -
trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 37 37 * @author Drew Noakes https://drewnoakes.com 38 38 */ 39 @SuppressWarnings("WeakerAccess") 39 40 public class NikonType2MakernoteDescriptor extends TagDescriptor<NikonType2MakernoteDirectory> 40 41 { -
trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 45 45 * @author Drew Noakes https://drewnoakes.com 46 46 */ 47 @SuppressWarnings("WeakerAccess") 47 48 public class NikonType2MakernoteDirectory extends Directory 48 49 { … … 760 761 public static final int TAG_UNKNOWN_50 = 0x00BD; 761 762 public static final int TAG_UNKNOWN_51 = 0x0103; 762 public static final int TAG_PRINT_IM = 0x0E00;763 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 763 764 764 765 /** … … 893 894 _tagNameMap.put(TAG_UNKNOWN_50, "Unknown 50"); 894 895 _tagNameMap.put(TAG_UNKNOWN_51, "Unknown 51"); 895 _tagNameMap.put(TAG_PRINT_IM , "Print IM");896 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print IM"); 896 897 _tagNameMap.put(TAG_UNKNOWN_52, "Unknown 52"); 897 898 _tagNameMap.put(TAG_UNKNOWN_53, "Unknown 53"); -
trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.java
r10862 r13061 41 41 * @author Drew Noakes https://drewnoakes.com 42 42 */ 43 @SuppressWarnings("WeakerAccess") 43 44 public class OlympusCameraSettingsMakernoteDescriptor extends TagDescriptor<OlympusCameraSettingsMakernoteDirectory> 44 45 { … … 143 144 case TagArtFilterEffect: 144 145 return getArtFilterEffectDescription(); 146 case TagColorCreatorEffect: 147 return getColorCreatorEffectDescription(); 145 148 146 149 case TagDriveMode: … … 407 410 int p4 = (int)(values[index + 3].doubleValue() * 100); 408 411 412 if(p1 + p2 + p3 + p4 == 0) 413 return "n/a"; 414 409 415 return String.format("(%d%%,%d%%) (%d%%,%d%%)", p1, p2, p3, p4); 410 411 416 } 412 417 … … 1019 1024 StringBuilder sb = new StringBuilder(); 1020 1025 for (int i = 0; i < values.length; i++) { 1021 if (i == 1) 1022 sb.append("Highlights "); 1023 else if (i == 5) 1024 sb.append("Shadows "); 1025 1026 sb.append(values[i]).append("; "); 1026 if (i == 0 || i == 4 || i == 8 || i == 12 || i == 16 || i == 20 || i == 24) 1027 sb.append(_toneLevelType.get(values[i])).append("; "); 1028 else 1029 sb.append(values[i]).append("; "); 1027 1030 } 1028 1031 … … 1034 1037 { 1035 1038 int[] values = _directory.getIntArray(TagArtFilterEffect); 1036 if (values == null || values.length == 0)1039 if (values == null) 1037 1040 return null; 1038 1041 … … 1040 1043 for (int i = 0; i < values.length; i++) { 1041 1044 if (i == 0) { 1042 sb.append((_filters.containsKey(values[i]) ? _filters.get(values[i]) : "[unknown]")); 1045 sb.append((_filters.containsKey(values[i]) ? _filters.get(values[i]) : "[unknown]")).append("; "); 1046 } else if (i == 3) { 1047 sb.append("Partial Color ").append(values[i]).append("; "); 1043 1048 } else if (i == 4) { 1044 1049 switch (values[i]) { … … 1068 1073 break; 1069 1074 } 1075 sb.append("; "); 1076 } else if (i == 6) { 1077 switch (values[i]) { 1078 case 0: 1079 sb.append("No Color Filter"); 1080 break; 1081 case 1: 1082 sb.append("Yellow Color Filter"); 1083 break; 1084 case 2: 1085 sb.append("Orange Color Filter"); 1086 break; 1087 case 3: 1088 sb.append("Red Color Filter"); 1089 break; 1090 case 4: 1091 sb.append("Green Color Filter"); 1092 break; 1093 default: 1094 sb.append("Unknown (").append(values[i]).append(")"); 1095 break; 1096 } 1097 sb.append("; "); 1070 1098 } else { 1071 sb.append(values[i]) ;1099 sb.append(values[i]).append("; "); 1072 1100 } 1073 sb.append("; "); 1101 } 1102 1103 return sb.substring(0, sb.length() - 2); 1104 } 1105 1106 @Nullable 1107 public String getColorCreatorEffectDescription() 1108 { 1109 int[] values = _directory.getIntArray(TagColorCreatorEffect); 1110 if (values == null) 1111 return null; 1112 1113 StringBuilder sb = new StringBuilder(); 1114 for (int i = 0; i < values.length; i++) { 1115 if (i == 0) { 1116 sb.append("Color ").append(values[i]).append("; "); 1117 } else if (i == 3) { 1118 sb.append("Strength ").append(values[i]).append("; "); 1119 } else { 1120 sb.append(values[i]).append("; "); 1121 } 1074 1122 } 1075 1123 … … 1294 1342 } 1295 1343 1344 @Nullable 1296 1345 private String getFiltersDescription(int tagId) 1297 1346 { … … 1312 1361 } 1313 1362 1363 private static final HashMap<Integer, String> _toneLevelType = new HashMap<Integer, String>(); 1314 1364 // ArtFilter, ArtFilterEffect and MagicFilter values 1315 1365 private static final HashMap<Integer, String> _filters = new HashMap<Integer, String>(); … … 1354 1404 _filters.put(40, "Partial Color II"); 1355 1405 _filters.put(41, "Partial Color III"); 1406 1407 _toneLevelType.put(0, "0"); 1408 _toneLevelType.put(-31999, "Highlights "); 1409 _toneLevelType.put(-31998, "Shadows "); 1410 _toneLevelType.put(-31997, "Midtones "); 1356 1411 } 1357 1412 } -
trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDirectory.java
r10862 r13061 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class OlympusCameraSettingsMakernoteDirectory extends Directory 36 37 { … … 89 90 public static final int TagToneLevel = 0x52e; 90 91 public static final int TagArtFilterEffect = 0x52f; 92 public static final int TagColorCreatorEffect = 0x532; 91 93 92 94 public static final int TagDriveMode = 0x600; … … 162 164 _tagNameMap.put(TagToneLevel, "Tone Level"); 163 165 _tagNameMap.put(TagArtFilterEffect, "Art Filter Effect"); 166 _tagNameMap.put(TagColorCreatorEffect, "Color Creator Effect"); 164 167 165 168 _tagNameMap.put(TagDriveMode, "Drive Mode"); -
trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDescriptor.java
r10862 r13061 40 40 * @author Drew Noakes https://drewnoakes.com 41 41 */ 42 @SuppressWarnings("WeakerAccess") 42 43 public class OlympusEquipmentMakernoteDescriptor extends TagDescriptor<OlympusEquipmentMakernoteDirectory> 43 44 { … … 53 54 switch (tagType) { 54 55 case TAG_EQUIPMENT_VERSION: 55 return GetEquipmentVersionDescription(); 56 return getEquipmentVersionDescription(); 57 case TAG_CAMERA_TYPE_2: 58 return getCameraType2Description(); 56 59 case TAG_FOCAL_PLANE_DIAGONAL: 57 return GetFocalPlaneDiagonalDescription();60 return getFocalPlaneDiagonalDescription(); 58 61 case TAG_BODY_FIRMWARE_VERSION: 59 return GetBodyFirmwareVersionDescription();62 return getBodyFirmwareVersionDescription(); 60 63 case TAG_LENS_TYPE: 61 return GetLensTypeDescription();64 return getLensTypeDescription(); 62 65 case TAG_LENS_FIRMWARE_VERSION: 63 return GetLensFirmwareVersionDescription();66 return getLensFirmwareVersionDescription(); 64 67 case TAG_MAX_APERTURE_AT_MIN_FOCAL: 65 return GetMaxApertureAtMinFocalDescription();68 return getMaxApertureAtMinFocalDescription(); 66 69 case TAG_MAX_APERTURE_AT_MAX_FOCAL: 67 return GetMaxApertureAtMaxFocalDescription();70 return getMaxApertureAtMaxFocalDescription(); 68 71 case TAG_MAX_APERTURE: 69 return GetMaxApertureDescription();72 return getMaxApertureDescription(); 70 73 case TAG_LENS_PROPERTIES: 71 return GetLensPropertiesDescription();74 return getLensPropertiesDescription(); 72 75 case TAG_EXTENDER: 73 return GetExtenderDescription();76 return getExtenderDescription(); 74 77 case TAG_FLASH_TYPE: 75 return GetFlashTypeDescription();78 return getFlashTypeDescription(); 76 79 case TAG_FLASH_MODEL: 77 return GetFlashModelDescription();80 return getFlashModelDescription(); 78 81 default: 79 82 return super.getDescription(tagType); … … 82 85 83 86 @Nullable 84 public String GetEquipmentVersionDescription()87 public String getEquipmentVersionDescription() 85 88 { 86 89 return getVersionBytesDescription(TAG_EQUIPMENT_VERSION, 4); … … 88 91 89 92 @Nullable 90 public String GetFocalPlaneDiagonalDescription() 93 public String getCameraType2Description() 94 { 95 String cameratype = _directory.getString(TAG_CAMERA_TYPE_2); 96 if(cameratype == null) 97 return null; 98 99 if(OlympusMakernoteDirectory.OlympusCameraTypes.containsKey(cameratype)) 100 return OlympusMakernoteDirectory.OlympusCameraTypes.get(cameratype); 101 102 return cameratype; 103 } 104 105 @Nullable 106 public String getFocalPlaneDiagonalDescription() 91 107 { 92 108 return _directory.getString(TAG_FOCAL_PLANE_DIAGONAL) + " mm"; … … 94 110 95 111 @Nullable 96 public String GetBodyFirmwareVersionDescription()112 public String getBodyFirmwareVersionDescription() 97 113 { 98 114 Integer value = _directory.getInteger(TAG_BODY_FIRMWARE_VERSION); … … 107 123 108 124 @Nullable 109 public String GetLensTypeDescription()125 public String getLensTypeDescription() 110 126 { 111 127 String str = _directory.getString(TAG_LENS_TYPE); … … 140 156 141 157 @Nullable 142 public String GetLensFirmwareVersionDescription()158 public String getLensFirmwareVersionDescription() 143 159 { 144 160 Integer value = _directory.getInteger(TAG_LENS_FIRMWARE_VERSION); … … 153 169 154 170 @Nullable 155 public String GetMaxApertureAtMinFocalDescription()171 public String getMaxApertureAtMinFocalDescription() 156 172 { 157 173 Integer value = _directory.getInteger(TAG_MAX_APERTURE_AT_MIN_FOCAL); … … 164 180 165 181 @Nullable 166 public String GetMaxApertureAtMaxFocalDescription()182 public String getMaxApertureAtMaxFocalDescription() 167 183 { 168 184 Integer value = _directory.getInteger(TAG_MAX_APERTURE_AT_MAX_FOCAL); … … 175 191 176 192 @Nullable 177 public String GetMaxApertureDescription()193 public String getMaxApertureDescription() 178 194 { 179 195 Integer value = _directory.getInteger(TAG_MAX_APERTURE); … … 191 207 192 208 @Nullable 193 public String GetLensPropertiesDescription()209 public String getLensPropertiesDescription() 194 210 { 195 211 Integer value = _directory.getInteger(TAG_LENS_PROPERTIES); … … 201 217 202 218 @Nullable 203 public String GetExtenderDescription()219 public String getExtenderDescription() 204 220 { 205 221 String str = _directory.getString(TAG_EXTENDER); … … 234 250 235 251 @Nullable 236 public String GetFlashTypeDescription()252 public String getFlashTypeDescription() 237 253 { 238 254 return getIndexedDescription(TAG_FLASH_TYPE, … … 241 257 242 258 @Nullable 243 public String GetFlashModelDescription()259 public String getFlashModelDescription() 244 260 { 245 261 return getIndexedDescription(TAG_FLASH_MODEL, -
trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDirectory.java
r10862 r13061 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class OlympusEquipmentMakernoteDirectory extends Directory 36 37 { -
trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 21 21 package com.drew.metadata.exif.makernotes; 22 22 23 import com.drew.imaging.PhotographicConversions; 24 import com.drew.lang.Rational; 23 25 import com.drew.lang.DateUtil; 24 26 import com.drew.lang.annotations.NotNull; … … 36 38 * @author Drew Noakes https://drewnoakes.com 37 39 */ 40 @SuppressWarnings("WeakerAccess") 38 41 public class OlympusMakernoteDescriptor extends TagDescriptor<OlympusMakernoteDirectory> 39 42 { … … 66 69 case TAG_BW_MODE: 67 70 return getBWModeDescription(); 68 case TAG_DIGI_ZOOM_RATIO: 69 return getDigiZoomRatioDescription(); 71 case TAG_DIGITAL_ZOOM: 72 return getDigitalZoomDescription(); 73 case TAG_FOCAL_PLANE_DIAGONAL: 74 return getFocalPlaneDiagonalDescription(); 75 case TAG_CAMERA_TYPE: 76 return getCameraTypeDescription(); 70 77 case TAG_CAMERA_ID: 71 78 return getCameraIdDescription(); 79 case TAG_ONE_TOUCH_WB: 80 return getOneTouchWbDescription(); 81 case TAG_SHUTTER_SPEED_VALUE: 82 return getShutterSpeedDescription(); 83 case TAG_ISO_VALUE: 84 return getIsoValueDescription(); 85 case TAG_APERTURE_VALUE: 86 return getApertureValueDescription(); 72 87 case TAG_FLASH_MODE: 73 88 return getFlashModeDescription(); … … 78 93 case TAG_SHARPNESS: 79 94 return getSharpnessDescription(); 95 case TAG_COLOUR_MATRIX: 96 return getColorMatrixDescription(); 97 case TAG_WB_MODE: 98 return getWbModeDescription(); 99 case TAG_RED_BALANCE: 100 return getRedBalanceDescription(); 101 case TAG_BLUE_BALANCE: 102 return getBlueBalanceDescription(); 103 case TAG_CONTRAST: 104 return getContrastDescription(); 105 case TAG_PREVIEW_IMAGE_VALID: 106 return getPreviewImageValidDescription(); 80 107 81 108 case CameraSettings.TAG_EXPOSURE_MODE: … … 102 129 return getMacroModeCameraSettingDescription(); 103 130 case CameraSettings.TAG_DIGITAL_ZOOM: 104 return getDigitalZoom Description();131 return getDigitalZoomCameraSettingDescription(); 105 132 case CameraSettings.TAG_EXPOSURE_COMPENSATION: 106 133 return getExposureCompensationDescription(); … … 138 165 return getSaturationDescription(); 139 166 case CameraSettings.TAG_CONTRAST: 140 return getContrast Description();167 return getContrastCameraSettingDescription(); 141 168 case CameraSettings.TAG_SHARPNESS: 142 169 return getSharpnessCameraSettingDescription(); … … 305 332 306 333 @Nullable 307 public String getDigitalZoom Description()334 public String getDigitalZoomCameraSettingDescription() 308 335 { 309 336 return getIndexedDescription(CameraSettings.TAG_DIGITAL_ZOOM, "Off", "Electronic magnification", "Digital zoom 2x"); … … 468 495 469 496 @Nullable 470 public String getContrast Description()497 public String getContrastCameraSettingDescription() 471 498 { 472 499 Long value = _directory.getLongObject(CameraSettings.TAG_CONTRAST); … … 647 674 648 675 @Nullable 676 public String getColorMatrixDescription() 677 { 678 int[] obj = _directory.getIntArray(TAG_COLOUR_MATRIX); 679 if (obj == null) 680 return null; 681 682 StringBuilder sb = new StringBuilder(); 683 for (int i = 0; i < obj.length; i++) { 684 sb.append((short)obj[i]); 685 if (i < obj.length - 1) 686 sb.append(" "); 687 } 688 return sb.length() == 0 ? null : sb.toString(); 689 } 690 691 @Nullable 692 public String getWbModeDescription() 693 { 694 int[] obj = _directory.getIntArray(TAG_WB_MODE); 695 if (obj == null) 696 return null; 697 698 String val = String.format("%d %d", obj[0], obj[1]); 699 700 if(val.equals("1 0")) 701 return "Auto"; 702 else if(val.equals("1 2")) 703 return "Auto (2)"; 704 else if(val.equals("1 4")) 705 return "Auto (4)"; 706 else if(val.equals("2 2")) 707 return "3000 Kelvin"; 708 else if(val.equals("2 3")) 709 return "3700 Kelvin"; 710 else if(val.equals("2 4")) 711 return "4000 Kelvin"; 712 else if(val.equals("2 5")) 713 return "4500 Kelvin"; 714 else if(val.equals("2 6")) 715 return "5500 Kelvin"; 716 else if(val.equals("2 7")) 717 return "6500 Kelvin"; 718 else if(val.equals("2 8")) 719 return "7500 Kelvin"; 720 else if(val.equals("3 0")) 721 return "One-touch"; 722 else 723 return "Unknown " + val; 724 } 725 726 @Nullable 727 public String getRedBalanceDescription() 728 { 729 int[] values = _directory.getIntArray(TAG_RED_BALANCE); 730 if (values == null) 731 return null; 732 733 short value = (short)values[0]; 734 735 return String.valueOf((double)value/256d); 736 } 737 738 @Nullable 739 public String getBlueBalanceDescription() 740 { 741 int[] values = _directory.getIntArray(TAG_BLUE_BALANCE); 742 if (values == null) 743 return null; 744 745 short value = (short)values[0]; 746 747 return String.valueOf((double)value/256d); 748 } 749 750 @Nullable 751 public String getContrastDescription() 752 { 753 return getIndexedDescription(TAG_CONTRAST, "High", "Normal", "Low"); 754 } 755 756 @Nullable 757 public String getPreviewImageValidDescription() 758 { 759 return getIndexedDescription(TAG_PREVIEW_IMAGE_VALID, "No", "Yes"); 760 } 761 762 @Nullable 649 763 public String getFocusModeDescription() 650 764 { … … 665 779 666 780 @Nullable 667 public String getDigiZoomRatioDescription() 668 { 669 return getIndexedDescription(TAG_DIGI_ZOOM_RATIO, "Normal", null, "Digital 2x Zoom"); 781 public String getDigitalZoomDescription() 782 { 783 Rational value = _directory.getRational(TAG_DIGITAL_ZOOM); 784 if (value == null) 785 return null; 786 return value.toSimpleString(false); 787 } 788 789 @Nullable 790 public String getFocalPlaneDiagonalDescription() 791 { 792 Rational value = _directory.getRational(TAG_FOCAL_PLANE_DIAGONAL); 793 if (value == null) 794 return null; 795 796 DecimalFormat format = new DecimalFormat("0.###"); 797 return format.format(value.doubleValue()) + " mm"; 798 } 799 800 @Nullable 801 public String getCameraTypeDescription() 802 { 803 String cameratype = _directory.getString(TAG_CAMERA_TYPE); 804 if(cameratype == null) 805 return null; 806 807 if(OlympusMakernoteDirectory.OlympusCameraTypes.containsKey(cameratype)) 808 return OlympusMakernoteDirectory.OlympusCameraTypes.get(cameratype); 809 810 return cameratype; 670 811 } 671 812 … … 680 821 681 822 @Nullable 823 public String getOneTouchWbDescription() 824 { 825 return getIndexedDescription(TAG_ONE_TOUCH_WB, "Off", "On", "On (Preset)"); 826 } 827 828 @Nullable 829 public String getShutterSpeedDescription() 830 { 831 return super.getShutterSpeedDescription(TAG_SHUTTER_SPEED_VALUE); 832 } 833 834 @Nullable 835 public String getIsoValueDescription() 836 { 837 Rational value = _directory.getRational(TAG_ISO_VALUE); 838 if (value == null) 839 return null; 840 841 return String.valueOf(Math.round(Math.pow(2, value.doubleValue() - 5) * 100)); 842 } 843 844 @Nullable 845 public String getApertureValueDescription() 846 { 847 Double aperture = _directory.getDoubleObject(TAG_APERTURE_VALUE); 848 if (aperture == null) 849 return null; 850 double fStop = PhotographicConversions.apertureToFStop(aperture); 851 return getFStopDescription(fStop); 852 } 853 854 @Nullable 682 855 public String getMacroModeDescription() 683 856 { … … 694 867 public String getJpegQualityDescription() 695 868 { 696 return getIndexedDescription(TAG_JPEG_QUALITY, 869 String cameratype = _directory.getString(TAG_CAMERA_TYPE); 870 871 if(cameratype != null) 872 { 873 Integer value = _directory.getInteger(TAG_JPEG_QUALITY); 874 if(value == null) 875 return null; 876 877 if((cameratype.startsWith("SX") && !cameratype.startsWith("SX151")) 878 || cameratype.startsWith("D4322")) 879 { 880 switch (value) 881 { 882 case 0: 883 return "Standard Quality (Low)"; 884 case 1: 885 return "High Quality (Normal)"; 886 case 2: 887 return "Super High Quality (Fine)"; 888 case 6: 889 return "RAW"; 890 default: 891 return "Unknown (" + value.toString() + ")"; 892 } 893 } 894 else 895 { 896 switch (value) 897 { 898 case 0: 899 return "Standard Quality (Low)"; 900 case 1: 901 return "High Quality (Normal)"; 902 case 2: 903 return "Super High Quality (Fine)"; 904 case 4: 905 return "RAW"; 906 case 5: 907 return "Medium-Fine"; 908 case 6: 909 return "Small-Fine"; 910 case 33: 911 return "Uncompressed"; 912 default: 913 return "Unknown (" + value.toString() + ")"; 914 } 915 } 916 } 917 else 918 return getIndexedDescription(TAG_JPEG_QUALITY, 697 919 1, 698 920 "Standard Quality", -
trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 34 34 * @author Drew Noakes https://drewnoakes.com 35 35 */ 36 @SuppressWarnings("WeakerAccess") 36 37 public class OlympusMakernoteDirectory extends Directory 37 38 { … … 117 118 118 119 /** Zoom Factor (0 or 1 = normal) */ 119 public static final int TAG_DIGI _ZOOM_RATIO= 0x0204;120 public static final int TAG_DIGITAL_ZOOM = 0x0204; 120 121 public static final int TAG_FOCAL_PLANE_DIAGONAL = 0x0205; 121 122 public static final int TAG_LENS_DISTORTION_PARAMETERS = 0x0206; 122 public static final int TAG_ FIRMWARE_VERSION= 0x0207;123 public static final int TAG_CAMERA_TYPE = 0x0207; 123 124 public static final int TAG_PICT_INFO = 0x0208; 124 125 public static final int TAG_CAMERA_ID = 0x0209; … … 146 147 public static final int TAG_WHITE_BALANCE_BIAS = 0x0304; 147 148 public static final int TAG_SCENE_MODE = 0x0403; 148 public static final int TAG_FIRMWARE = 0x0404; 149 public static final int TAG_SERIAL_NUMBER_1 = 0x0404; 150 public static final int TAG_FIRMWARE = 0x0405; 149 151 150 152 /** … … 176 178 public static final int TAG_COLOUR_MATRIX = 0x1011; 177 179 public static final int TAG_BLACK_LEVEL = 0x1012; 178 // public static final int TAG_= 0x1013;179 // public static final int TAG_= 0x1014;180 public static final int TAG_W HITE_BALANCE = 0x1015;180 public static final int TAG_COLOR_TEMPERATURE_BG = 0x1013; 181 public static final int TAG_COLOR_TEMPERATURE_RG = 0x1014; 182 public static final int TAG_WB_MODE = 0x1015; 181 183 // public static final int TAG_ = 0x1016; 182 public static final int TAG_RED_B IAS= 0x1017;183 public static final int TAG_BLUE_B IAS= 0x1018;184 public static final int TAG_RED_BALANCE = 0x1017; 185 public static final int TAG_BLUE_BALANCE = 0x1018; 184 186 public static final int TAG_COLOR_MATRIX_NUMBER = 0x1019; 185 public static final int TAG_SERIAL_NUMBER = 0x101A; 186 // public static final int TAG_ = 0x101B; 187 // public static final int TAG_ = 0x101C; 188 // public static final int TAG_ = 0x101D; 189 // public static final int TAG_ = 0x101E; 190 // public static final int TAG_ = 0x101F; 191 // public static final int TAG_ = 0x1020; 192 // public static final int TAG_ = 0x1021; 193 // public static final int TAG_ = 0x1022; 187 public static final int TAG_SERIAL_NUMBER_2 = 0x101A; 188 189 public static final int TAG_EXTERNAL_FLASH_AE1_0 = 0x101B; 190 public static final int TAG_EXTERNAL_FLASH_AE2_0 = 0x101C; 191 public static final int TAG_INTERNAL_FLASH_AE1_0 = 0x101D; 192 public static final int TAG_INTERNAL_FLASH_AE2_0 = 0x101E; 193 public static final int TAG_EXTERNAL_FLASH_AE1 = 0x101F; 194 public static final int TAG_EXTERNAL_FLASH_AE2 = 0x1020; 195 public static final int TAG_INTERNAL_FLASH_AE1 = 0x1021; 196 public static final int TAG_INTERNAL_FLASH_AE2 = 0x1022; 197 194 198 public static final int TAG_FLASH_BIAS = 0x1023; 195 // public static final int TAG_= 0x1024;196 // public static final int TAG_= 0x1025;199 public static final int TAG_INTERNAL_FLASH_TABLE = 0x1024; 200 public static final int TAG_EXTERNAL_FLASH_G_VALUE = 0x1025; 197 201 public static final int TAG_EXTERNAL_FLASH_BOUNCE = 0x1026; 198 202 public static final int TAG_EXTERNAL_FLASH_ZOOM = 0x1027; … … 203 207 public static final int TAG_VALID_BITS = 0x102C; 204 208 public static final int TAG_CORING_FILTER = 0x102D; 205 public static final int TAG_ FINAL_WIDTH = 0x102E;206 public static final int TAG_ FINAL_HEIGHT = 0x102F;207 // public static final int TAG_= 0x1030;208 // public static final int TAG_= 0x1031;209 public static final int TAG_OLYMPUS_IMAGE_WIDTH = 0x102E; 210 public static final int TAG_OLYMPUS_IMAGE_HEIGHT = 0x102F; 211 public static final int TAG_SCENE_DETECT = 0x1030; 212 public static final int TAG_SCENE_AREA = 0x1031; 209 213 // public static final int TAG_ = 0x1032; 210 // public static final int TAG_= 0x1033;214 public static final int TAG_SCENE_DETECT_DATA = 0x1033; 211 215 public static final int TAG_COMPRESSION_RATIO = 0x1034; 212 public static final int TAG_ THUMBNAIL= 0x1035;213 public static final int TAG_ THUMBNAIL_OFFSET = 0x1036;214 public static final int TAG_ THUMBNAIL_LENGTH = 0x1037;215 // public static final int TAG_= 0x1038;216 public static final int TAG_PREVIEW_IMAGE_VALID = 0x1035; 217 public static final int TAG_PREVIEW_IMAGE_START = 0x1036; 218 public static final int TAG_PREVIEW_IMAGE_LENGTH = 0x1037; 219 public static final int TAG_AF_RESULT = 0x1038; 216 220 public static final int TAG_CCD_SCAN_MODE = 0x1039; 217 221 public static final int TAG_NOISE_REDUCTION = 0x103A; 218 222 public static final int TAG_INFINITY_LENS_STEP = 0x103B; 219 223 public static final int TAG_NEAR_LENS_STEP = 0x103C; 224 public static final int TAG_LIGHT_VALUE_CENTER = 0x103D; 225 public static final int TAG_LIGHT_VALUE_PERIPHERY = 0x103E; 226 public static final int TAG_FIELD_COUNT = 0x103F; 220 227 public static final int TAG_EQUIPMENT = 0x2010; 221 228 public static final int TAG_CAMERA_SETTINGS = 0x2020; … … 225 232 public static final int TAG_FOCUS_INFO = 0x2050; 226 233 public static final int TAG_RAW_INFO = 0x3000; 234 public static final int TAG_MAIN_INFO = 0x4000; 227 235 228 236 public final static class CameraSettings … … 302 310 _tagNameMap.put(TAG_MACRO_MODE, "Macro"); 303 311 _tagNameMap.put(TAG_BW_MODE, "BW Mode"); 304 _tagNameMap.put(TAG_DIGI _ZOOM_RATIO, "DigiZoom Ratio");312 _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom"); 305 313 _tagNameMap.put(TAG_FOCAL_PLANE_DIAGONAL, "Focal Plane Diagonal"); 306 314 _tagNameMap.put(TAG_LENS_DISTORTION_PARAMETERS, "Lens Distortion Parameters"); 307 _tagNameMap.put(TAG_ FIRMWARE_VERSION, "Firmware Version");315 _tagNameMap.put(TAG_CAMERA_TYPE, "Camera Type"); 308 316 _tagNameMap.put(TAG_PICT_INFO, "Pict Info"); 309 317 _tagNameMap.put(TAG_CAMERA_ID, "Camera Id"); … … 318 326 _tagNameMap.put(TAG_WHITE_BALANCE_BIAS, "White Balance Bias"); 319 327 _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode"); 328 _tagNameMap.put(TAG_SERIAL_NUMBER_1, "Serial Number"); 320 329 _tagNameMap.put(TAG_FIRMWARE, "Firmware"); 321 330 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); … … 341 350 _tagNameMap.put(TAG_COLOUR_MATRIX, "Colour Matrix"); 342 351 _tagNameMap.put(TAG_BLACK_LEVEL, "Black Level"); 343 _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance"); 344 _tagNameMap.put(TAG_RED_BIAS, "Red Bias"); 345 _tagNameMap.put(TAG_BLUE_BIAS, "Blue Bias"); 352 _tagNameMap.put(TAG_COLOR_TEMPERATURE_BG, "Color Temperature BG"); 353 _tagNameMap.put(TAG_COLOR_TEMPERATURE_RG, "Color Temperature RG"); 354 _tagNameMap.put(TAG_WB_MODE, "White Balance Mode"); 355 _tagNameMap.put(TAG_RED_BALANCE, "Red Balance"); 356 _tagNameMap.put(TAG_BLUE_BALANCE, "Blue Balance"); 346 357 _tagNameMap.put(TAG_COLOR_MATRIX_NUMBER, "Color Matrix Number"); 347 _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number"); 358 _tagNameMap.put(TAG_SERIAL_NUMBER_2, "Serial Number"); 359 _tagNameMap.put(TAG_EXTERNAL_FLASH_AE1_0, "External Flash AE1 0"); 360 _tagNameMap.put(TAG_EXTERNAL_FLASH_AE2_0, "External Flash AE2 0"); 361 _tagNameMap.put(TAG_INTERNAL_FLASH_AE1_0, "Internal Flash AE1 0"); 362 _tagNameMap.put(TAG_INTERNAL_FLASH_AE2_0, "Internal Flash AE2 0"); 363 _tagNameMap.put(TAG_EXTERNAL_FLASH_AE1, "External Flash AE1"); 364 _tagNameMap.put(TAG_EXTERNAL_FLASH_AE2, "External Flash AE2"); 365 _tagNameMap.put(TAG_INTERNAL_FLASH_AE1, "Internal Flash AE1"); 366 _tagNameMap.put(TAG_INTERNAL_FLASH_AE2, "Internal Flash AE2"); 348 367 _tagNameMap.put(TAG_FLASH_BIAS, "Flash Bias"); 368 _tagNameMap.put(TAG_INTERNAL_FLASH_TABLE, "Internal Flash Table"); 369 _tagNameMap.put(TAG_EXTERNAL_FLASH_G_VALUE, "External Flash G Value"); 349 370 _tagNameMap.put(TAG_EXTERNAL_FLASH_BOUNCE, "External Flash Bounce"); 350 371 _tagNameMap.put(TAG_EXTERNAL_FLASH_ZOOM, "External Flash Zoom"); … … 355 376 _tagNameMap.put(TAG_VALID_BITS, "Valid Bits"); 356 377 _tagNameMap.put(TAG_CORING_FILTER, "Coring Filter"); 357 _tagNameMap.put(TAG_FINAL_WIDTH, "Final Width"); 358 _tagNameMap.put(TAG_FINAL_HEIGHT, "Final Height"); 378 _tagNameMap.put(TAG_OLYMPUS_IMAGE_WIDTH, "Olympus Image Width"); 379 _tagNameMap.put(TAG_OLYMPUS_IMAGE_HEIGHT, "Olympus Image Height"); 380 _tagNameMap.put(TAG_SCENE_DETECT, "Scene Detect"); 381 _tagNameMap.put(TAG_SCENE_AREA, "Scene Area"); 382 _tagNameMap.put(TAG_SCENE_DETECT_DATA, "Scene Detect Data"); 359 383 _tagNameMap.put(TAG_COMPRESSION_RATIO, "Compression Ratio"); 360 _tagNameMap.put(TAG_THUMBNAIL, "Thumbnail"); 361 _tagNameMap.put(TAG_THUMBNAIL_OFFSET, "Thumbnail Offset"); 362 _tagNameMap.put(TAG_THUMBNAIL_LENGTH, "Thumbnail Length"); 384 _tagNameMap.put(TAG_PREVIEW_IMAGE_VALID, "Preview Image Valid"); 385 _tagNameMap.put(TAG_PREVIEW_IMAGE_START, "Preview Image Start"); 386 _tagNameMap.put(TAG_PREVIEW_IMAGE_LENGTH, "Preview Image Length"); 387 _tagNameMap.put(TAG_AF_RESULT, "AF Result"); 363 388 _tagNameMap.put(TAG_CCD_SCAN_MODE, "CCD Scan Mode"); 364 389 _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction"); 365 390 _tagNameMap.put(TAG_INFINITY_LENS_STEP, "Infinity Lens Step"); 366 391 _tagNameMap.put(TAG_NEAR_LENS_STEP, "Near Lens Step"); 392 _tagNameMap.put(TAG_LIGHT_VALUE_CENTER, "Light Value Center"); 393 _tagNameMap.put(TAG_LIGHT_VALUE_PERIPHERY, "Light Value Periphery"); 394 _tagNameMap.put(TAG_FIELD_COUNT, "Field Count"); 367 395 _tagNameMap.put(TAG_EQUIPMENT, "Equipment"); 368 396 _tagNameMap.put(TAG_CAMERA_SETTINGS, "Camera Settings"); … … 372 400 _tagNameMap.put(TAG_FOCUS_INFO, "Focus Info"); 373 401 _tagNameMap.put(TAG_RAW_INFO, "Raw Info"); 402 _tagNameMap.put(TAG_MAIN_INFO, "Main Info"); 374 403 375 404 _tagNameMap.put(CameraSettings.TAG_EXPOSURE_MODE, "Exposure Mode"); … … 476 505 return _tagNameMap; 477 506 } 507 508 // <summary> 509 // These values are currently decoded only for Olympus models. Models with 510 // Olympus-style maker notes from other brands such as Acer, BenQ, Hitachi, HP, 511 // Premier, Konica-Minolta, Maginon, Ricoh, Rollei, SeaLife, Sony, Supra, 512 // Vivitar are not listed. 513 // </summary> 514 // <remarks> 515 // Converted from Exiftool version 10.33 created by Phil Harvey 516 // http://www.sno.phy.queensu.ca/~phil/exiftool/ 517 // lib\Image\ExifTool\Olympus.pm 518 // </remarks> 519 public static final HashMap<String, String> OlympusCameraTypes = new HashMap<String, String>(); 520 521 static { 522 OlympusCameraTypes.put("D4028", "X-2,C-50Z"); 523 OlympusCameraTypes.put("D4029", "E-20,E-20N,E-20P"); 524 OlympusCameraTypes.put("D4034", "C720UZ"); 525 OlympusCameraTypes.put("D4040", "E-1"); 526 OlympusCameraTypes.put("D4041", "E-300"); 527 OlympusCameraTypes.put("D4083", "C2Z,D520Z,C220Z"); 528 OlympusCameraTypes.put("D4106", "u20D,S400D,u400D"); 529 OlympusCameraTypes.put("D4120", "X-1"); 530 OlympusCameraTypes.put("D4122", "u10D,S300D,u300D"); 531 OlympusCameraTypes.put("D4125", "AZ-1"); 532 OlympusCameraTypes.put("D4141", "C150,D390"); 533 OlympusCameraTypes.put("D4193", "C-5000Z"); 534 OlympusCameraTypes.put("D4194", "X-3,C-60Z"); 535 OlympusCameraTypes.put("D4199", "u30D,S410D,u410D"); 536 OlympusCameraTypes.put("D4205", "X450,D535Z,C370Z"); 537 OlympusCameraTypes.put("D4210", "C160,D395"); 538 OlympusCameraTypes.put("D4211", "C725UZ"); 539 OlympusCameraTypes.put("D4213", "FerrariMODEL2003"); 540 OlympusCameraTypes.put("D4216", "u15D"); 541 OlympusCameraTypes.put("D4217", "u25D"); 542 OlympusCameraTypes.put("D4220", "u-miniD,Stylus V"); 543 OlympusCameraTypes.put("D4221", "u40D,S500,uD500"); 544 OlympusCameraTypes.put("D4231", "FerrariMODEL2004"); 545 OlympusCameraTypes.put("D4240", "X500,D590Z,C470Z"); 546 OlympusCameraTypes.put("D4244", "uD800,S800"); 547 OlympusCameraTypes.put("D4256", "u720SW,S720SW"); 548 OlympusCameraTypes.put("D4261", "X600,D630,FE5500"); 549 OlympusCameraTypes.put("D4262", "uD600,S600"); 550 OlympusCameraTypes.put("D4301", "u810/S810"); // (yes, "/". Olympus is not consistent in the notation) 551 OlympusCameraTypes.put("D4302", "u710,S710"); 552 OlympusCameraTypes.put("D4303", "u700,S700"); 553 OlympusCameraTypes.put("D4304", "FE100,X710"); 554 OlympusCameraTypes.put("D4305", "FE110,X705"); 555 OlympusCameraTypes.put("D4310", "FE-130,X-720"); 556 OlympusCameraTypes.put("D4311", "FE-140,X-725"); 557 OlympusCameraTypes.put("D4312", "FE150,X730"); 558 OlympusCameraTypes.put("D4313", "FE160,X735"); 559 OlympusCameraTypes.put("D4314", "u740,S740"); 560 OlympusCameraTypes.put("D4315", "u750,S750"); 561 OlympusCameraTypes.put("D4316", "u730/S730"); 562 OlympusCameraTypes.put("D4317", "FE115,X715"); 563 OlympusCameraTypes.put("D4321", "SP550UZ"); 564 OlympusCameraTypes.put("D4322", "SP510UZ"); 565 OlympusCameraTypes.put("D4324", "FE170,X760"); 566 OlympusCameraTypes.put("D4326", "FE200"); 567 OlympusCameraTypes.put("D4327", "FE190/X750"); // (also SX876) 568 OlympusCameraTypes.put("D4328", "u760,S760"); 569 OlympusCameraTypes.put("D4330", "FE180/X745"); // (also SX875) 570 OlympusCameraTypes.put("D4331", "u1000/S1000"); 571 OlympusCameraTypes.put("D4332", "u770SW,S770SW"); 572 OlympusCameraTypes.put("D4333", "FE240/X795"); 573 OlympusCameraTypes.put("D4334", "FE210,X775"); 574 OlympusCameraTypes.put("D4336", "FE230/X790"); 575 OlympusCameraTypes.put("D4337", "FE220,X785"); 576 OlympusCameraTypes.put("D4338", "u725SW,S725SW"); 577 OlympusCameraTypes.put("D4339", "FE250/X800"); 578 OlympusCameraTypes.put("D4341", "u780,S780"); 579 OlympusCameraTypes.put("D4343", "u790SW,S790SW"); 580 OlympusCameraTypes.put("D4344", "u1020,S1020"); 581 OlympusCameraTypes.put("D4346", "FE15,X10"); 582 OlympusCameraTypes.put("D4348", "FE280,X820,C520"); 583 OlympusCameraTypes.put("D4349", "FE300,X830"); 584 OlympusCameraTypes.put("D4350", "u820,S820"); 585 OlympusCameraTypes.put("D4351", "u1200,S1200"); 586 OlympusCameraTypes.put("D4352", "FE270,X815,C510"); 587 OlympusCameraTypes.put("D4353", "u795SW,S795SW"); 588 OlympusCameraTypes.put("D4354", "u1030SW,S1030SW"); 589 OlympusCameraTypes.put("D4355", "SP560UZ"); 590 OlympusCameraTypes.put("D4356", "u1010,S1010"); 591 OlympusCameraTypes.put("D4357", "u830,S830"); 592 OlympusCameraTypes.put("D4359", "u840,S840"); 593 OlympusCameraTypes.put("D4360", "FE350WIDE,X865"); 594 OlympusCameraTypes.put("D4361", "u850SW,S850SW"); 595 OlympusCameraTypes.put("D4362", "FE340,X855,C560"); 596 OlympusCameraTypes.put("D4363", "FE320,X835,C540"); 597 OlympusCameraTypes.put("D4364", "SP570UZ"); 598 OlympusCameraTypes.put("D4366", "FE330,X845,C550"); 599 OlympusCameraTypes.put("D4368", "FE310,X840,C530"); 600 OlympusCameraTypes.put("D4370", "u1050SW,S1050SW"); 601 OlympusCameraTypes.put("D4371", "u1060,S1060"); 602 OlympusCameraTypes.put("D4372", "FE370,X880,C575"); 603 OlympusCameraTypes.put("D4374", "SP565UZ"); 604 OlympusCameraTypes.put("D4377", "u1040,S1040"); 605 OlympusCameraTypes.put("D4378", "FE360,X875,C570"); 606 OlympusCameraTypes.put("D4379", "FE20,X15,C25"); 607 OlympusCameraTypes.put("D4380", "uT6000,ST6000"); 608 OlympusCameraTypes.put("D4381", "uT8000,ST8000"); 609 OlympusCameraTypes.put("D4382", "u9000,S9000"); 610 OlympusCameraTypes.put("D4384", "SP590UZ"); 611 OlympusCameraTypes.put("D4385", "FE3010,X895"); 612 OlympusCameraTypes.put("D4386", "FE3000,X890"); 613 OlympusCameraTypes.put("D4387", "FE35,X30"); 614 OlympusCameraTypes.put("D4388", "u550WP,S550WP"); 615 OlympusCameraTypes.put("D4390", "FE5000,X905"); 616 OlympusCameraTypes.put("D4391", "u5000"); 617 OlympusCameraTypes.put("D4392", "u7000,S7000"); 618 OlympusCameraTypes.put("D4396", "FE5010,X915"); 619 OlympusCameraTypes.put("D4397", "FE25,X20"); 620 OlympusCameraTypes.put("D4398", "FE45,X40"); 621 OlympusCameraTypes.put("D4401", "XZ-1"); 622 OlympusCameraTypes.put("D4402", "uT6010,ST6010"); 623 OlympusCameraTypes.put("D4406", "u7010,S7010 / u7020,S7020"); 624 OlympusCameraTypes.put("D4407", "FE4010,X930"); 625 OlympusCameraTypes.put("D4408", "X560WP"); 626 OlympusCameraTypes.put("D4409", "FE26,X21"); 627 OlympusCameraTypes.put("D4410", "FE4000,X920,X925"); 628 OlympusCameraTypes.put("D4411", "FE46,X41,X42"); 629 OlympusCameraTypes.put("D4412", "FE5020,X935"); 630 OlympusCameraTypes.put("D4413", "uTough-3000"); 631 OlympusCameraTypes.put("D4414", "StylusTough-6020"); 632 OlympusCameraTypes.put("D4415", "StylusTough-8010"); 633 OlympusCameraTypes.put("D4417", "u5010,S5010"); 634 OlympusCameraTypes.put("D4418", "u7040,S7040"); 635 OlympusCameraTypes.put("D4419", "u9010,S9010"); 636 OlympusCameraTypes.put("D4423", "FE4040"); 637 OlympusCameraTypes.put("D4424", "FE47,X43"); 638 OlympusCameraTypes.put("D4426", "FE4030,X950"); 639 OlympusCameraTypes.put("D4428", "FE5030,X965,X960"); 640 OlympusCameraTypes.put("D4430", "u7030,S7030"); 641 OlympusCameraTypes.put("D4432", "SP600UZ"); 642 OlympusCameraTypes.put("D4434", "SP800UZ"); 643 OlympusCameraTypes.put("D4439", "FE4020,X940"); 644 OlympusCameraTypes.put("D4442", "FE5035"); 645 OlympusCameraTypes.put("D4448", "FE4050,X970"); 646 OlympusCameraTypes.put("D4450", "FE5050,X985"); 647 OlympusCameraTypes.put("D4454", "u-7050"); 648 OlympusCameraTypes.put("D4464", "T10,X27"); 649 OlympusCameraTypes.put("D4470", "FE5040,X980"); 650 OlympusCameraTypes.put("D4472", "TG-310"); 651 OlympusCameraTypes.put("D4474", "TG-610"); 652 OlympusCameraTypes.put("D4476", "TG-810"); 653 OlympusCameraTypes.put("D4478", "VG145,VG140,D715"); 654 OlympusCameraTypes.put("D4479", "VG130,D710"); 655 OlympusCameraTypes.put("D4480", "VG120,D705"); 656 OlympusCameraTypes.put("D4482", "VR310,D720"); 657 OlympusCameraTypes.put("D4484", "VR320,D725"); 658 OlympusCameraTypes.put("D4486", "VR330,D730"); 659 OlympusCameraTypes.put("D4488", "VG110,D700"); 660 OlympusCameraTypes.put("D4490", "SP-610UZ"); 661 OlympusCameraTypes.put("D4492", "SZ-10"); 662 OlympusCameraTypes.put("D4494", "SZ-20"); 663 OlympusCameraTypes.put("D4496", "SZ-30MR"); 664 OlympusCameraTypes.put("D4498", "SP-810UZ"); 665 OlympusCameraTypes.put("D4500", "SZ-11"); 666 OlympusCameraTypes.put("D4504", "TG-615"); 667 OlympusCameraTypes.put("D4508", "TG-620"); 668 OlympusCameraTypes.put("D4510", "TG-820"); 669 OlympusCameraTypes.put("D4512", "TG-1"); 670 OlympusCameraTypes.put("D4516", "SH-21"); 671 OlympusCameraTypes.put("D4519", "SZ-14"); 672 OlympusCameraTypes.put("D4520", "SZ-31MR"); 673 OlympusCameraTypes.put("D4521", "SH-25MR"); 674 OlympusCameraTypes.put("D4523", "SP-720UZ"); 675 OlympusCameraTypes.put("D4529", "VG170"); 676 OlympusCameraTypes.put("D4531", "XZ-2"); 677 OlympusCameraTypes.put("D4535", "SP-620UZ"); 678 OlympusCameraTypes.put("D4536", "TG-320"); 679 OlympusCameraTypes.put("D4537", "VR340,D750"); 680 OlympusCameraTypes.put("D4538", "VG160,X990,D745"); 681 OlympusCameraTypes.put("D4541", "SZ-12"); 682 OlympusCameraTypes.put("D4545", "VH410"); 683 OlympusCameraTypes.put("D4546", "XZ-10"); //IB 684 OlympusCameraTypes.put("D4547", "TG-2"); 685 OlympusCameraTypes.put("D4548", "TG-830"); 686 OlympusCameraTypes.put("D4549", "TG-630"); 687 OlympusCameraTypes.put("D4550", "SH-50"); 688 OlympusCameraTypes.put("D4553", "SZ-16,DZ-105"); 689 OlympusCameraTypes.put("D4562", "SP-820UZ"); 690 OlympusCameraTypes.put("D4566", "SZ-15"); 691 OlympusCameraTypes.put("D4572", "STYLUS1"); 692 OlympusCameraTypes.put("D4574", "TG-3"); 693 OlympusCameraTypes.put("D4575", "TG-850"); 694 OlympusCameraTypes.put("D4579", "SP-100EE"); 695 OlympusCameraTypes.put("D4580", "SH-60"); 696 OlympusCameraTypes.put("D4581", "SH-1"); 697 OlympusCameraTypes.put("D4582", "TG-835"); 698 OlympusCameraTypes.put("D4585", "SH-2 / SH-3"); 699 OlympusCameraTypes.put("D4586", "TG-4"); 700 OlympusCameraTypes.put("D4587", "TG-860"); 701 OlympusCameraTypes.put("D4591", "TG-870"); 702 OlympusCameraTypes.put("D4809", "C2500L"); 703 OlympusCameraTypes.put("D4842", "E-10"); 704 OlympusCameraTypes.put("D4856", "C-1"); 705 OlympusCameraTypes.put("D4857", "C-1Z,D-150Z"); 706 OlympusCameraTypes.put("DCHC", "D500L"); 707 OlympusCameraTypes.put("DCHT", "D600L / D620L"); 708 OlympusCameraTypes.put("K0055", "AIR-A01"); 709 OlympusCameraTypes.put("S0003", "E-330"); 710 OlympusCameraTypes.put("S0004", "E-500"); 711 OlympusCameraTypes.put("S0009", "E-400"); 712 OlympusCameraTypes.put("S0010", "E-510"); 713 OlympusCameraTypes.put("S0011", "E-3"); 714 OlympusCameraTypes.put("S0013", "E-410"); 715 OlympusCameraTypes.put("S0016", "E-420"); 716 OlympusCameraTypes.put("S0017", "E-30"); 717 OlympusCameraTypes.put("S0018", "E-520"); 718 OlympusCameraTypes.put("S0019", "E-P1"); 719 OlympusCameraTypes.put("S0023", "E-620"); 720 OlympusCameraTypes.put("S0026", "E-P2"); 721 OlympusCameraTypes.put("S0027", "E-PL1"); 722 OlympusCameraTypes.put("S0029", "E-450"); 723 OlympusCameraTypes.put("S0030", "E-600"); 724 OlympusCameraTypes.put("S0032", "E-P3"); 725 OlympusCameraTypes.put("S0033", "E-5"); 726 OlympusCameraTypes.put("S0034", "E-PL2"); 727 OlympusCameraTypes.put("S0036", "E-M5"); 728 OlympusCameraTypes.put("S0038", "E-PL3"); 729 OlympusCameraTypes.put("S0039", "E-PM1"); 730 OlympusCameraTypes.put("S0040", "E-PL1s"); 731 OlympusCameraTypes.put("S0042", "E-PL5"); 732 OlympusCameraTypes.put("S0043", "E-PM2"); 733 OlympusCameraTypes.put("S0044", "E-P5"); 734 OlympusCameraTypes.put("S0045", "E-PL6"); 735 OlympusCameraTypes.put("S0046", "E-PL7"); //IB 736 OlympusCameraTypes.put("S0047", "E-M1"); 737 OlympusCameraTypes.put("S0051", "E-M10"); 738 OlympusCameraTypes.put("S0052", "E-M5MarkII"); //IB 739 OlympusCameraTypes.put("S0059", "E-M10MarkII"); 740 OlympusCameraTypes.put("S0061", "PEN-F"); //forum7005 741 OlympusCameraTypes.put("S0065", "E-PL8"); 742 OlympusCameraTypes.put("S0067", "E-M1MarkII"); 743 OlympusCameraTypes.put("SR45", "D220"); 744 OlympusCameraTypes.put("SR55", "D320L"); 745 OlympusCameraTypes.put("SR83", "D340L"); 746 OlympusCameraTypes.put("SR85", "C830L,D340R"); 747 OlympusCameraTypes.put("SR852", "C860L,D360L"); 748 OlympusCameraTypes.put("SR872", "C900Z,D400Z"); 749 OlympusCameraTypes.put("SR874", "C960Z,D460Z"); 750 OlympusCameraTypes.put("SR951", "C2000Z"); 751 OlympusCameraTypes.put("SR952", "C21"); 752 OlympusCameraTypes.put("SR953", "C21T.commu"); 753 OlympusCameraTypes.put("SR954", "C2020Z"); 754 OlympusCameraTypes.put("SR955", "C990Z,D490Z"); 755 OlympusCameraTypes.put("SR956", "C211Z"); 756 OlympusCameraTypes.put("SR959", "C990ZS,D490Z"); 757 OlympusCameraTypes.put("SR95A", "C2100UZ"); 758 OlympusCameraTypes.put("SR971", "C100,D370"); 759 OlympusCameraTypes.put("SR973", "C2,D230"); 760 OlympusCameraTypes.put("SX151", "E100RS"); 761 OlympusCameraTypes.put("SX351", "C3000Z / C3030Z"); 762 OlympusCameraTypes.put("SX354", "C3040Z"); 763 OlympusCameraTypes.put("SX355", "C2040Z"); 764 OlympusCameraTypes.put("SX357", "C700UZ"); 765 OlympusCameraTypes.put("SX358", "C200Z,D510Z"); 766 OlympusCameraTypes.put("SX374", "C3100Z,C3020Z"); 767 OlympusCameraTypes.put("SX552", "C4040Z"); 768 OlympusCameraTypes.put("SX553", "C40Z,D40Z"); 769 OlympusCameraTypes.put("SX556", "C730UZ"); 770 OlympusCameraTypes.put("SX558", "C5050Z"); 771 OlympusCameraTypes.put("SX571", "C120,D380"); 772 OlympusCameraTypes.put("SX574", "C300Z,D550Z"); 773 OlympusCameraTypes.put("SX575", "C4100Z,C4000Z"); 774 OlympusCameraTypes.put("SX751", "X200,D560Z,C350Z"); 775 OlympusCameraTypes.put("SX752", "X300,D565Z,C450Z"); 776 OlympusCameraTypes.put("SX753", "C750UZ"); 777 OlympusCameraTypes.put("SX754", "C740UZ"); 778 OlympusCameraTypes.put("SX755", "C755UZ"); 779 OlympusCameraTypes.put("SX756", "C5060WZ"); 780 OlympusCameraTypes.put("SX757", "C8080WZ"); 781 OlympusCameraTypes.put("SX758", "X350,D575Z,C360Z"); 782 OlympusCameraTypes.put("SX759", "X400,D580Z,C460Z"); 783 OlympusCameraTypes.put("SX75A", "AZ-2ZOOM"); 784 OlympusCameraTypes.put("SX75B", "D595Z,C500Z"); 785 OlympusCameraTypes.put("SX75C", "X550,D545Z,C480Z"); 786 OlympusCameraTypes.put("SX75D", "IR-300"); 787 OlympusCameraTypes.put("SX75F", "C55Z,C5500Z"); 788 OlympusCameraTypes.put("SX75G", "C170,D425"); 789 OlympusCameraTypes.put("SX75J", "C180,D435"); 790 OlympusCameraTypes.put("SX771", "C760UZ"); 791 OlympusCameraTypes.put("SX772", "C770UZ"); 792 OlympusCameraTypes.put("SX773", "C745UZ"); 793 OlympusCameraTypes.put("SX774", "X250,D560Z,C350Z"); 794 OlympusCameraTypes.put("SX775", "X100,D540Z,C310Z"); 795 OlympusCameraTypes.put("SX776", "C460ZdelSol"); 796 OlympusCameraTypes.put("SX777", "C765UZ"); 797 OlympusCameraTypes.put("SX77A", "D555Z,C315Z"); 798 OlympusCameraTypes.put("SX851", "C7070WZ"); 799 OlympusCameraTypes.put("SX852", "C70Z,C7000Z"); 800 OlympusCameraTypes.put("SX853", "SP500UZ"); 801 OlympusCameraTypes.put("SX854", "SP310"); 802 OlympusCameraTypes.put("SX855", "SP350"); 803 OlympusCameraTypes.put("SX873", "SP320"); 804 OlympusCameraTypes.put("SX875", "FE180/X745"); // (also D4330) 805 OlympusCameraTypes.put("SX876", "FE190/X750"); // (also D4327) 806 807 // other brands 808 // 4MP9Q3", "Camera 4MP-9Q3' 809 // 4MP9T2", "BenQ DC C420 / Camera 4MP-9T2' 810 // 5MP9Q3", "Camera 5MP-9Q3" }, 811 // 5MP9X9", "Camera 5MP-9X9" }, 812 // '5MP-9T'=> 'Camera 5MP-9T3" }, 813 // '5MP-9Y'=> 'Camera 5MP-9Y2" }, 814 // '6MP-9U'=> 'Camera 6MP-9U9" }, 815 // 7MP9Q3", "Camera 7MP-9Q3" }, 816 // '8MP-9U'=> 'Camera 8MP-9U4" }, 817 // CE5330", "Acer CE-5330" }, 818 // 'CP-853'=> 'Acer CP-8531" }, 819 // CS5531", "Acer CS5531" }, 820 // DC500 ", "SeaLife DC500" }, 821 // DC7370", "Camera 7MP-9GA" }, 822 // DC7371", "Camera 7MP-9GM" }, 823 // DC7371", "Hitachi HDC-751E" }, 824 // DC7375", "Hitachi HDC-763E / Rollei RCP-7330X / Ricoh Caplio RR770 / Vivitar ViviCam 7330" }, 825 // 'DC E63'=> 'BenQ DC E63+" }, 826 // 'DC P86'=> 'BenQ DC P860" }, 827 // DS5340", "Maginon Performic S5 / Premier 5MP-9M7" }, 828 // DS5341", "BenQ E53+ / Supra TCM X50 / Maginon X50 / Premier 5MP-9P8" }, 829 // DS5346", "Premier 5MP-9Q2" }, 830 // E500 ", "Konica Minolta DiMAGE E500" }, 831 // MAGINO", "Maginon X60" }, 832 // Mz60 ", "HP Photosmart Mz60" }, 833 // Q3DIGI", "Camera 5MP-9Q3" }, 834 // SLIMLI", "Supra Slimline X6" }, 835 // V8300s", "Vivitar V8300s" }, 836 } 478 837 } -
trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 22 22 23 23 import com.drew.lang.ByteArrayReader; 24 import com.drew.lang.Charsets; 24 25 import com.drew.lang.RandomAccessReader; 25 26 import com.drew.lang.annotations.NotNull; … … 29 30 import com.drew.metadata.TagDescriptor; 30 31 32 import java.text.DecimalFormat; 31 33 import java.io.IOException; 32 34 … … 45 47 * @author Philipp Sandhaus 46 48 */ 49 @SuppressWarnings("WeakerAccess") 47 50 public class PanasonicMakernoteDescriptor extends TagDescriptor<PanasonicMakernoteDirectory> 48 51 { … … 109 112 case TAG_TRANSFORM: 110 113 return getTransformDescription(); 111 112 114 case TAG_TRANSFORM_1: 115 return getTransform1Description(); 113 116 case TAG_INTELLIGENT_EXPOSURE: 114 117 return getIntelligentExposureDescription(); … … 127 130 case TAG_FACE_RECOGNITION_INFO: 128 131 return getRecognizedFacesDescription(); 129 case TAG_PRINT_IMAGE_MATCHING_INFO:130 return getPrintImageMatchingInfoDescription();131 132 case TAG_SCENE_MODE: 132 133 return getSceneModeDescription(); … … 134 135 return getFlashFiredDescription(); 135 136 case TAG_TEXT_STAMP: 136 137 138 139 140 141 142 137 return getTextStampDescription(); 138 case TAG_TEXT_STAMP_1: 139 return getTextStamp1Description(); 140 case TAG_TEXT_STAMP_2: 141 return getTextStamp2Description(); 142 case TAG_TEXT_STAMP_3: 143 return getTextStamp3Description(); 143 144 case TAG_MAKERNOTE_VERSION: 144 145 return getMakernoteVersionDescription(); … … 148 149 return getInternalSerialNumberDescription(); 149 150 case TAG_TITLE: 150 return getTitleDescription(); 151 case TAG_BABY_NAME: 152 return getBabyNameDescription(); 153 case TAG_LOCATION: 154 return getLocationDescription(); 155 case TAG_BABY_AGE: 156 return getBabyAgeDescription(); 157 case TAG_BABY_AGE_1: 158 return getBabyAge1Description(); 159 default: 151 return getTitleDescription(); 152 case TAG_BRACKET_SETTINGS: 153 return getBracketSettingsDescription(); 154 case TAG_FLASH_CURTAIN: 155 return getFlashCurtainDescription(); 156 case TAG_LONG_EXPOSURE_NOISE_REDUCTION: 157 return getLongExposureNoiseReductionDescription(); 158 case TAG_BABY_NAME: 159 return getBabyNameDescription(); 160 case TAG_LOCATION: 161 return getLocationDescription(); 162 163 case TAG_LENS_FIRMWARE_VERSION: 164 return getLensFirmwareVersionDescription(); 165 case TAG_INTELLIGENT_D_RANGE: 166 return getIntelligentDRangeDescription(); 167 case TAG_CLEAR_RETOUCH: 168 return getClearRetouchDescription(); 169 case TAG_PHOTO_STYLE: 170 return getPhotoStyleDescription(); 171 case TAG_SHADING_COMPENSATION: 172 return getShadingCompensationDescription(); 173 174 case TAG_ACCELEROMETER_Z: 175 return getAccelerometerZDescription(); 176 case TAG_ACCELEROMETER_X: 177 return getAccelerometerXDescription(); 178 case TAG_ACCELEROMETER_Y: 179 return getAccelerometerYDescription(); 180 case TAG_CAMERA_ORIENTATION: 181 return getCameraOrientationDescription(); 182 case TAG_ROLL_ANGLE: 183 return getRollAngleDescription(); 184 case TAG_PITCH_ANGLE: 185 return getPitchAngleDescription(); 186 case TAG_SWEEP_PANORAMA_DIRECTION: 187 return getSweepPanoramaDirectionDescription(); 188 case TAG_TIMER_RECORDING: 189 return getTimerRecordingDescription(); 190 case TAG_HDR: 191 return getHDRDescription(); 192 case TAG_SHUTTER_TYPE: 193 return getShutterTypeDescription(); 194 case TAG_TOUCH_AE: 195 return getTouchAeDescription(); 196 197 case TAG_BABY_AGE: 198 return getBabyAgeDescription(); 199 case TAG_BABY_AGE_1: 200 return getBabyAge1Description(); 201 default: 160 202 return super.getDescription(tagType); 161 203 } 162 }163 164 @Nullable165 public String getPrintImageMatchingInfoDescription()166 {167 return getByteLengthDescription(TAG_PRINT_IMAGE_MATCHING_INFO);168 204 } 169 205 … … 279 315 280 316 @Nullable 317 private static String trim(@Nullable String s) 318 { 319 return s == null ? null : s.trim(); 320 } 321 322 @Nullable 281 323 public String getCountryDescription() 282 324 { 283 return getAsciiStringFromBytes(TAG_COUNTRY);325 return trim(getStringFromBytes(TAG_COUNTRY, Charsets.UTF_8)); 284 326 } 285 327 … … 287 329 public String getStateDescription() 288 330 { 289 return getAsciiStringFromBytes(TAG_STATE);331 return trim(getStringFromBytes(TAG_STATE, Charsets.UTF_8)); 290 332 } 291 333 … … 293 335 public String getCityDescription() 294 336 { 295 return getAsciiStringFromBytes(TAG_CITY);337 return trim(getStringFromBytes(TAG_CITY, Charsets.UTF_8)); 296 338 } 297 339 … … 299 341 public String getLandmarkDescription() 300 342 { 301 return getAsciiStringFromBytes(TAG_LANDMARK);302 } 303 304 343 return trim(getStringFromBytes(TAG_LANDMARK, Charsets.UTF_8)); 344 } 345 346 @Nullable 305 347 public String getTitleDescription() 306 348 { 307 return getAsciiStringFromBytes(TAG_TITLE); 308 } 309 310 @Nullable 349 return trim(getStringFromBytes(TAG_TITLE, Charsets.UTF_8)); 350 } 351 352 @Nullable 353 public String getBracketSettingsDescription() 354 { 355 return getIndexedDescription(TAG_BRACKET_SETTINGS, 356 "No Bracket", "3 Images, Sequence 0/-/+", "3 Images, Sequence -/0/+", "5 Images, Sequence 0/-/+", 357 "5 Images, Sequence -/0/+", "7 Images, Sequence 0/-/+", "7 Images, Sequence -/0/+"); 358 } 359 360 @Nullable 361 public String getFlashCurtainDescription() 362 { 363 return getIndexedDescription(TAG_FLASH_CURTAIN, 364 "n/a", "1st", "2nd"); 365 } 366 367 @Nullable 368 public String getLongExposureNoiseReductionDescription() 369 { 370 return getIndexedDescription(TAG_LONG_EXPOSURE_NOISE_REDUCTION, 1, 371 "Off", "On"); 372 } 373 374 @Nullable 375 public String getLensFirmwareVersionDescription() 376 { 377 // lens version has 4 parts separated by periods 378 byte[] bytes = _directory.getByteArray(TAG_LENS_FIRMWARE_VERSION); 379 if (bytes == null) 380 return null; 381 382 StringBuilder sb = new StringBuilder(); 383 for (int i = 0; i < bytes.length; i++) { 384 sb.append(bytes[i]); 385 if (i < bytes.length - 1) 386 sb.append("."); 387 } 388 return sb.toString(); 389 //return string.Join(".", bytes.Select(b => b.ToString()).ToArray()); 390 } 391 392 @Nullable 393 public String getIntelligentDRangeDescription() 394 { 395 return getIndexedDescription(TAG_INTELLIGENT_D_RANGE, 396 "Off", "Low", "Standard", "High"); 397 } 398 399 @Nullable 400 public String getClearRetouchDescription() 401 { 402 return getIndexedDescription(TAG_CLEAR_RETOUCH, 403 "Off", "On"); 404 405 } 406 407 @Nullable 408 public String getPhotoStyleDescription() 409 { 410 return getIndexedDescription(TAG_PHOTO_STYLE, 411 "Auto", "Standard or Custom", "Vivid", "Natural", "Monochrome", "Scenery", "Portrait"); 412 } 413 414 @Nullable 415 public String getShadingCompensationDescription() 416 { 417 return getIndexedDescription(TAG_SHADING_COMPENSATION, 418 "Off", "On"); 419 } 420 421 @Nullable 422 public String getAccelerometerZDescription() 423 { 424 Integer value = _directory.getInteger(TAG_ACCELEROMETER_Z); 425 if (value == null) 426 return null; 427 428 // positive is acceleration upwards 429 return String.valueOf(value.shortValue()); 430 } 431 432 @Nullable 433 public String getAccelerometerXDescription() 434 { 435 Integer value = _directory.getInteger(TAG_ACCELEROMETER_X); 436 if (value == null) 437 return null; 438 439 // positive is acceleration to the left 440 return String.valueOf(value.shortValue()); 441 } 442 443 @Nullable 444 public String getAccelerometerYDescription() 445 { 446 Integer value = _directory.getInteger(TAG_ACCELEROMETER_Y); 447 if (value == null) 448 return null; 449 450 // positive is acceleration backwards 451 return String.valueOf(value.shortValue()); 452 } 453 454 @Nullable 455 public String getCameraOrientationDescription() 456 { 457 return getIndexedDescription(TAG_CAMERA_ORIENTATION, 458 "Normal", "Rotate CW", "Rotate 180", "Rotate CCW", "Tilt Upwards", "Tile Downwards"); 459 } 460 461 @Nullable 462 public String getRollAngleDescription() 463 { 464 Integer value = _directory.getInteger(TAG_ROLL_ANGLE); 465 if (value == null) 466 return null; 467 468 DecimalFormat format = new DecimalFormat("0.#"); 469 // converted to degrees of clockwise camera rotation 470 return format.format(value.shortValue() / 10.0); 471 } 472 473 @Nullable 474 public String getPitchAngleDescription() 475 { 476 Integer value = _directory.getInteger(TAG_PITCH_ANGLE); 477 if (value == null) 478 return null; 479 480 DecimalFormat format = new DecimalFormat("0.#"); 481 // converted to degrees of upward camera tilt 482 return format.format(-value.shortValue() / 10.0); 483 } 484 485 @Nullable 486 public String getSweepPanoramaDirectionDescription() 487 { 488 return getIndexedDescription(TAG_SWEEP_PANORAMA_DIRECTION, 489 "Off", "Left to Right", "Right to Left", "Top to Bottom", "Bottom to Top"); 490 } 491 492 @Nullable 493 public String getTimerRecordingDescription() 494 { 495 return getIndexedDescription(TAG_TIMER_RECORDING, 496 "Off", "Time Lapse", "Stop-motion Animation"); 497 } 498 499 @Nullable 500 public String getHDRDescription() 501 { 502 Integer value = _directory.getInteger(TAG_HDR); 503 if (value == null) 504 return null; 505 506 switch (value) 507 { 508 case 0: 509 return "Off"; 510 case 100: 511 return "1 EV"; 512 case 200: 513 return "2 EV"; 514 case 300: 515 return "3 EV"; 516 case 32868: 517 return "1 EV (Auto)"; 518 case 32968: 519 return "2 EV (Auto)"; 520 case 33068: 521 return "3 EV (Auto)"; 522 default: 523 return String.format("Unknown (%d)", value); 524 } 525 } 526 527 @Nullable 528 public String getShutterTypeDescription() 529 { 530 return getIndexedDescription(TAG_SHUTTER_TYPE, 531 "Mechanical", "Electronic", "Hybrid"); 532 } 533 534 @Nullable 535 public String getTouchAeDescription() 536 { 537 return getIndexedDescription(TAG_TOUCH_AE, 538 "Off", "On"); 539 } 540 541 @Nullable 311 542 public String getBabyNameDescription() 312 543 { 313 return getAsciiStringFromBytes(TAG_BABY_NAME);544 return trim(getStringFromBytes(TAG_BABY_NAME, Charsets.UTF_8)); 314 545 } 315 546 … … 317 548 public String getLocationDescription() 318 549 { 319 return getAsciiStringFromBytes(TAG_LOCATION);550 return trim(getStringFromBytes(TAG_LOCATION, Charsets.UTF_8)); 320 551 } 321 552 -
trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 38 38 * @author Philipp Sandhaus 39 39 */ 40 @SuppressWarnings("WeakerAccess") 40 41 public class PanasonicMakernoteDirectory extends Directory 41 42 { … … 354 355 public static final int TAG_FILM_MODE = 0x0042; 355 356 356 /** 357 * WB adjust AB. Positive is a shift toward blue. 358 */ 359 public static final int TAG_WB_ADJUST_AB = 0x0046; 360 /** 361 * WB adjust GM. Positive is a shift toward green. 362 */ 363 public static final int TAG_WB_ADJUST_GM = 0x0047; 364 365 357 public static final int TAG_COLOR_TEMP_KELVIN = 0x0044; 358 public static final int TAG_BRACKET_SETTINGS = 0x0045; 359 360 /** 361 * WB adjust AB. Positive is a shift toward blue. 362 */ 363 public static final int TAG_WB_ADJUST_AB = 0x0046; 364 /** 365 * WB adjust GM. Positive is a shift toward green. 366 */ 367 public static final int TAG_WB_ADJUST_GM = 0x0047; 368 369 public static final int TAG_FLASH_CURTAIN = 0x0048; 370 public static final int TAG_LONG_EXPOSURE_NOISE_REDUCTION = 0x0049; 371 372 public static final int TAG_PANASONIC_IMAGE_WIDTH = 0x004b; 373 public static final int TAG_PANASONIC_IMAGE_HEIGHT = 0x004c; 366 374 public static final int TAG_AF_POINT_POSITION = 0x004d; 367 375 … … 384 392 public static final int TAG_LENS_SERIAL_NUMBER = 0x0052; 385 393 public static final int TAG_ACCESSORY_TYPE = 0x0053; 394 public static final int TAG_ACCESSORY_SERIAL_NUMBER = 0x0054; 386 395 387 396 /** … … 403 412 public static final int TAG_INTELLIGENT_EXPOSURE = 0x005d; 404 413 405 /** 406 * Info at http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html 407 */ 408 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 414 public static final int TAG_LENS_FIRMWARE_VERSION = 0x0060; 415 public static final int TAG_BURST_SPEED = 0x0077; 416 public static final int TAG_INTELLIGENT_D_RANGE = 0x0079; 417 public static final int TAG_CLEAR_RETOUCH = 0x007c; 418 public static final int TAG_CITY2 = 0x0080; 419 public static final int TAG_PHOTO_STYLE = 0x0089; 420 public static final int TAG_SHADING_COMPENSATION = 0x008a; 421 422 public static final int TAG_ACCELEROMETER_Z = 0x008c; 423 public static final int TAG_ACCELEROMETER_X = 0x008d; 424 public static final int TAG_ACCELEROMETER_Y = 0x008e; 425 public static final int TAG_CAMERA_ORIENTATION = 0x008f; 426 public static final int TAG_ROLL_ANGLE = 0x0090; 427 public static final int TAG_PITCH_ANGLE = 0x0091; 428 public static final int TAG_SWEEP_PANORAMA_DIRECTION = 0x0093; 429 public static final int TAG_SWEEP_PANORAMA_FIELD_OF_VIEW = 0x0094; 430 public static final int TAG_TIMER_RECORDING = 0x0096; 431 432 public static final int TAG_INTERNAL_ND_FILTER = 0x009d; 433 public static final int TAG_HDR = 0x009e; 434 public static final int TAG_SHUTTER_TYPE = 0x009f; 435 436 public static final int TAG_CLEAR_RETOUCH_VALUE = 0x00a3; 437 public static final int TAG_TOUCH_AE = 0x00ab; 438 439 /** 440 * Info at http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html 441 */ 442 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 409 443 410 444 /** … … 434 468 public static final int TAG_RECOGNIZED_FACE_FLAGS = 0x0063; 435 469 public static final int TAG_TITLE = 0x0065; 436 437 438 470 public static final int TAG_BABY_NAME = 0x0066; 471 public static final int TAG_LOCATION = 0x0067; 472 public static final int TAG_COUNTRY = 0x0069; 439 473 public static final int TAG_STATE = 0x006b; 440 474 public static final int TAG_CITY = 0x006d; … … 455 489 public static final int TAG_FLASH_FIRED = 0x8007; 456 490 public static final int TAG_TEXT_STAMP_2 = 0x8008; 457 458 491 public static final int TAG_TEXT_STAMP_3 = 0x8009; 492 public static final int TAG_BABY_AGE_1 = 0x8010; 459 493 460 494 /** … … 506 540 _tagNameMap.put(TAG_TEXT_STAMP, "Text Stamp"); 507 541 _tagNameMap.put(TAG_PROGRAM_ISO, "Program ISO"); 508 542 _tagNameMap.put(TAG_ADVANCED_SCENE_MODE, "Advanced Scene Mode"); 509 543 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 510 544 _tagNameMap.put(TAG_FACES_DETECTED, "Number of Detected Faces"); … … 512 546 _tagNameMap.put(TAG_SHARPNESS, "Sharpness"); 513 547 _tagNameMap.put(TAG_FILM_MODE, "Film Mode"); 548 _tagNameMap.put(TAG_COLOR_TEMP_KELVIN, "Color Temp Kelvin"); 549 _tagNameMap.put(TAG_BRACKET_SETTINGS, "Bracket Settings"); 514 550 _tagNameMap.put(TAG_WB_ADJUST_AB, "White Balance Adjust (AB)"); 515 _tagNameMap.put(TAG_WB_ADJUST_GM, "White Balance Adjust (GM)"); 516 _tagNameMap.put(TAG_AF_POINT_POSITION, "Af Point Position"); 551 _tagNameMap.put(TAG_WB_ADJUST_GM, "White Balance Adjust (GM)"); 552 553 _tagNameMap.put(TAG_FLASH_CURTAIN, "Flash Curtain"); 554 _tagNameMap.put(TAG_LONG_EXPOSURE_NOISE_REDUCTION, "Long Exposure Noise Reduction"); 555 _tagNameMap.put(TAG_PANASONIC_IMAGE_WIDTH, "Panasonic Image Width"); 556 _tagNameMap.put(TAG_PANASONIC_IMAGE_HEIGHT, "Panasonic Image Height"); 557 558 _tagNameMap.put(TAG_AF_POINT_POSITION, "Af Point Position"); 517 559 _tagNameMap.put(TAG_FACE_DETECTION_INFO, "Face Detection Info"); 518 560 _tagNameMap.put(TAG_LENS_TYPE, "Lens Type"); 519 561 _tagNameMap.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number"); 520 562 _tagNameMap.put(TAG_ACCESSORY_TYPE, "Accessory Type"); 563 _tagNameMap.put(TAG_ACCESSORY_SERIAL_NUMBER, "Accessory Serial Number"); 521 564 _tagNameMap.put(TAG_TRANSFORM, "Transform"); 522 565 _tagNameMap.put(TAG_INTELLIGENT_EXPOSURE, "Intelligent Exposure"); 566 _tagNameMap.put(TAG_LENS_FIRMWARE_VERSION, "Lens Firmware Version"); 523 567 _tagNameMap.put(TAG_FACE_RECOGNITION_INFO, "Face Recognition Info"); 524 568 _tagNameMap.put(TAG_FLASH_WARNING, "Flash Warning"); 525 569 _tagNameMap.put(TAG_RECOGNIZED_FACE_FLAGS, "Recognized Face Flags"); 526 527 528 529 570 _tagNameMap.put(TAG_TITLE, "Title"); 571 _tagNameMap.put(TAG_BABY_NAME, "Baby Name"); 572 _tagNameMap.put(TAG_LOCATION, "Location"); 573 _tagNameMap.put(TAG_COUNTRY, "Country"); 530 574 _tagNameMap.put(TAG_STATE, "State"); 531 575 _tagNameMap.put(TAG_CITY, "City"); 532 576 _tagNameMap.put(TAG_LANDMARK, "Landmark"); 533 577 _tagNameMap.put(TAG_INTELLIGENT_RESOLUTION, "Intelligent Resolution"); 578 _tagNameMap.put(TAG_BURST_SPEED, "Burst Speed"); 579 _tagNameMap.put(TAG_INTELLIGENT_D_RANGE, "Intelligent D-Range"); 580 _tagNameMap.put(TAG_CLEAR_RETOUCH, "Clear Retouch"); 581 _tagNameMap.put(TAG_CITY2, "City 2"); 582 _tagNameMap.put(TAG_PHOTO_STYLE, "Photo Style"); 583 _tagNameMap.put(TAG_SHADING_COMPENSATION, "Shading Compensation"); 584 585 _tagNameMap.put(TAG_ACCELEROMETER_Z, "Accelerometer Z"); 586 _tagNameMap.put(TAG_ACCELEROMETER_X, "Accelerometer X"); 587 _tagNameMap.put(TAG_ACCELEROMETER_Y, "Accelerometer Y"); 588 _tagNameMap.put(TAG_CAMERA_ORIENTATION, "Camera Orientation"); 589 _tagNameMap.put(TAG_ROLL_ANGLE, "Roll Angle"); 590 _tagNameMap.put(TAG_PITCH_ANGLE, "Pitch Angle"); 591 _tagNameMap.put(TAG_SWEEP_PANORAMA_DIRECTION, "Sweep Panorama Direction"); 592 _tagNameMap.put(TAG_SWEEP_PANORAMA_FIELD_OF_VIEW, "Sweep Panorama Field Of View"); 593 _tagNameMap.put(TAG_TIMER_RECORDING, "Timer Recording"); 594 595 _tagNameMap.put(TAG_INTERNAL_ND_FILTER, "Internal ND Filter"); 596 _tagNameMap.put(TAG_HDR, "HDR"); 597 _tagNameMap.put(TAG_SHUTTER_TYPE, "Shutter Type"); 598 _tagNameMap.put(TAG_CLEAR_RETOUCH_VALUE, "Clear Retouch Value"); 599 _tagNameMap.put(TAG_TOUCH_AE, "Touch AE"); 600 534 601 _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version"); 535 602 _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode"); … … 538 605 _tagNameMap.put(TAG_WB_BLUE_LEVEL, "White Balance (Blue)"); 539 606 _tagNameMap.put(TAG_FLASH_FIRED, "Flash Fired"); 540 541 542 543 544 607 _tagNameMap.put(TAG_TEXT_STAMP_1, "Text Stamp 1"); 608 _tagNameMap.put(TAG_TEXT_STAMP_2, "Text Stamp 2"); 609 _tagNameMap.put(TAG_TEXT_STAMP_3, "Text Stamp 3"); 610 _tagNameMap.put(TAG_BABY_AGE_1, "Baby Age 1"); 611 _tagNameMap.put(TAG_TRANSFORM_1, "Transform 1"); 545 612 } 546 613 -
trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 35 35 * @author Drew Noakes https://drewnoakes.com 36 36 */ 37 @SuppressWarnings("WeakerAccess") 37 38 public class PentaxMakernoteDescriptor extends TagDescriptor<PentaxMakernoteDirectory> 38 39 { -
trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class PentaxMakernoteDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 26 26 27 27 /** 28 * Provides human-readable string representations of tag values stored in a {@link RicohMakernoteD escriptor}.28 * Provides human-readable string representations of tag values stored in a {@link RicohMakernoteDirectory}. 29 29 * <p> 30 30 * Some information about this makernote taken from here: … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class RicohMakernoteDescriptor extends TagDescriptor<RicohMakernoteDirectory> 36 37 { … … 45 46 { 46 47 switch (tagType) { 47 // case TAG_PRINT_IMAGE_MATCHING_INFO:48 // return getPrintImageMatchingInfoDescription();49 48 // case TAG_PROPRIETARY_THUMBNAIL: 50 49 // return getProprietaryThumbnailDataDescription(); … … 53 52 } 54 53 } 55 56 // @Nullable57 // public String getPrintImageMatchingInfoDescription()58 // {59 // return getByteLengthDescription(TAG_PRINT_IMAGE_MATCHING_INFO);60 // }61 54 // 62 55 // @Nullable -
trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class RicohMakernoteDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class SanyoMakernoteDescriptor extends TagDescriptor<SanyoMakernoteDirectory> 36 37 { -
trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class SanyoMakernoteDirectory extends Directory 35 36 { … … 62 63 public static final int TAG_FLASH_MODE = 0x0225; 63 64 64 public static final int TAG_PRINT_IM = 0x0e00;65 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 65 66 66 67 public static final int TAG_DATA_DUMP = 0x0f00; … … 99 100 _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode"); 100 101 101 _tagNameMap.put(TAG_PRINT_IM , "Print IM");102 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print IM"); 102 103 103 104 _tagNameMap.put(TAG_DATA_DUMP, "Data Dump"); -
trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class SigmaMakernoteDescriptor extends TagDescriptor<SigmaMakernoteDirectory> 36 37 { -
trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class SigmaMakernoteDirectory extends Directory 35 36 { -
trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class SonyType1MakernoteDescriptor extends TagDescriptor<SonyType1MakernoteDirectory> 36 37 { … … 433 434 public String getVignettingCorrectionDescription() 434 435 { 435 return getIndexedDescription(TAG_VIGNETTING_CORRECTION, "Off", null, "Auto"); 436 Integer value = _directory.getInteger(TAG_VIGNETTING_CORRECTION); 437 if (value == null) 438 return null; 439 switch (value) { 440 case 0: return "Off"; 441 case 2: return "Auto"; 442 case 0xffffffff: return "N/A"; 443 default: return String.format("Unknown (%d)", value); 444 } 436 445 } 437 446 … … 439 448 public String getLateralChromaticAberrationDescription() 440 449 { 441 return getIndexedDescription(TAG_LATERAL_CHROMATIC_ABERRATION, "Off", null, "Auto"); 450 Integer value = _directory.getInteger(TAG_LATERAL_CHROMATIC_ABERRATION); 451 if (value == null) 452 return null; 453 switch (value) { 454 case 0: return "Off"; 455 case 2: return "Auto"; 456 case 0xffffffff: return "N/A"; 457 default: return String.format("Unknown (%d)", value); 458 } 442 459 } 443 460 … … 445 462 public String getDistortionCorrectionDescription() 446 463 { 447 return getIndexedDescription(TAG_DISTORTION_CORRECTION, "Off", null, "Auto"); 464 Integer value = _directory.getInteger(TAG_DISTORTION_CORRECTION); 465 if (value == null) 466 return null; 467 switch (value) { 468 case 0: return "Off"; 469 case 2: return "Auto"; 470 case 0xffffffff: return "N/A"; 471 default: return String.format("Unknown (%d)", value); 472 } 448 473 } 449 474 -
trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class SonyType1MakernoteDirectory extends Directory 34 35 { … … 141 142 _tagNameMap.put(TAG_EXTRA_INFO, "Extra Info"); 142 143 143 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching Info");144 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 144 145 145 146 _tagNameMap.put(TAG_MULTI_BURST_MODE, "Multi Burst Mode"); -
trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class SonyType6MakernoteDescriptor extends TagDescriptor<SonyType6MakernoteDirectory> 36 37 { -
trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 32 32 * @author Drew Noakes https://drewnoakes.com 33 33 */ 34 @SuppressWarnings("WeakerAccess") 34 35 public class SonyType6MakernoteDirectory extends Directory 35 36 { -
trunk/src/com/drew/metadata/file/FileMetadataDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 30 30 * @author Drew Noakes https://drewnoakes.com 31 31 */ 32 @SuppressWarnings("WeakerAccess") 32 33 public class FileMetadataDescriptor extends TagDescriptor<FileMetadataDirectory> 33 34 { -
trunk/src/com/drew/metadata/file/FileMetadataDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 29 29 * @author Drew Noakes https://drewnoakes.com 30 30 */ 31 @SuppressWarnings("WeakerAccess") 31 32 public class FileMetadataDirectory extends Directory 32 33 { -
trunk/src/com/drew/metadata/file/FileMetadataReader.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/metadata/iptc/IptcDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 35 35 * @author Drew Noakes https://drewnoakes.com 36 36 */ 37 @SuppressWarnings("WeakerAccess") 37 38 public class IptcDescriptor extends TagDescriptor<IptcDirectory> 38 39 { -
trunk/src/com/drew/metadata/iptc/IptcDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 38 38 * @author Drew Noakes https://drewnoakes.com 39 39 */ 40 @SuppressWarnings("WeakerAccess") 40 41 public class IptcDirectory extends Directory 41 42 { -
trunk/src/com/drew/metadata/iptc/IptcReader.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 29 29 import com.drew.metadata.Directory; 30 30 import com.drew.metadata.Metadata; 31 import com.drew.metadata.StringValue; 31 32 32 33 import java.io.IOException; 34 import java.nio.charset.Charset; 33 35 import java.util.Collections; 34 36 … … 56 58 public static final int POST_DATA_RECORD = 9; 57 59 */ 60 private static final byte IptcMarkerByte = 0x1c; 58 61 59 62 @NotNull … … 67 70 for (byte[] segmentBytes : segments) { 68 71 // Ensure data starts with the IPTC marker byte 69 if (segmentBytes.length != 0 && segmentBytes[0] == 0x1c) {72 if (segmentBytes.length != 0 && segmentBytes[0] == IptcMarkerByte) { 70 73 extract(new SequentialByteArrayReader(segmentBytes), metadata, segmentBytes.length); 71 74 } … … 107 110 } 108 111 109 if (startByte != 0x1c) {112 if (startByte != IptcMarkerByte) { 110 113 // NOTE have seen images where there was one extra byte at the end, giving 111 114 // offset==length at this point, which is not worth logging as an error. 112 115 if (offset != length) 113 directory.addError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x 1c' but got '0x" + Integer.toHexString(startByte) + "'.");116 directory.addError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x" + Integer.toHexString(IptcMarkerByte) + "' but got '0x" + Integer.toHexString(startByte) + "'."); 114 117 return; 115 118 } … … 164 167 } 165 168 166 String string = null;167 168 169 switch (tagIdentifier) { 169 170 case IptcDirectory.TAG_CODED_CHARACTER_SET: 170 171 byte[] bytes = reader.getBytes(tagByteCount); 171 String charset = Iso2022Converter.convertISO2022CharsetToJavaCharset(bytes);172 if (charset == null) {172 String charsetName = Iso2022Converter.convertISO2022CharsetToJavaCharset(bytes); 173 if (charsetName == null) { 173 174 // Unable to determine the charset, so fall through and treat tag as a regular string 174 string = new String(bytes); 175 break; 175 charsetName = new String(bytes); 176 176 } 177 directory.setString(tagIdentifier, charset );177 directory.setString(tagIdentifier, charsetName); 178 178 return; 179 179 case IptcDirectory.TAG_ENVELOPE_RECORD_VERSION: … … 201 201 // If we haven't returned yet, treat it as a string 202 202 // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value 203 if (string == null) { 204 String encoding = directory.getString(IptcDirectory.TAG_CODED_CHARACTER_SET); 205 if (encoding != null) { 206 string = reader.getString(tagByteCount, encoding); 207 } else { 208 byte[] bytes = reader.getBytes(tagByteCount); 209 encoding = Iso2022Converter.guessEncoding(bytes); 210 string = encoding != null ? new String(bytes, encoding) : new String(bytes); 211 } 203 String charSetName = directory.getString(IptcDirectory.TAG_CODED_CHARACTER_SET); 204 Charset charset = null; 205 try { 206 if (charSetName != null) 207 charset = Charset.forName(charSetName); 208 } catch (Throwable ignored) { 209 } 210 211 StringValue string; 212 if (charSetName != null) { 213 string = reader.getStringValue(tagByteCount, charset); 214 } else { 215 byte[] bytes = reader.getBytes(tagByteCount); 216 Charset charSet = Iso2022Converter.guessCharSet(bytes); 217 string = charSet != null ? new StringValue(bytes, charSet) : new StringValue(bytes, null); 212 218 } 213 219 214 220 if (directory.containsTag(tagIdentifier)) { 215 // this fancy string[] business avoids using an ArrayList for performance reasons216 String [] oldStrings = directory.getStringArray(tagIdentifier);217 String [] newStrings;221 // this fancy StringValue[] business avoids using an ArrayList for performance reasons 222 StringValue[] oldStrings = directory.getStringValueArray(tagIdentifier); 223 StringValue[] newStrings; 218 224 if (oldStrings == null) { 219 225 // TODO hitting this block means any prior value(s) are discarded 220 newStrings = new String [1];226 newStrings = new StringValue[1]; 221 227 } else { 222 newStrings = new String [oldStrings.length + 1];228 newStrings = new StringValue[oldStrings.length + 1]; 223 229 System.arraycopy(oldStrings, 0, newStrings, 0, oldStrings.length); 224 230 } 225 231 newStrings[newStrings.length - 1] = string; 226 directory.setString Array(tagIdentifier, newStrings);232 directory.setStringValueArray(tagIdentifier, newStrings); 227 233 } else { 228 directory.setString (tagIdentifier, string);234 directory.setStringValue(tagIdentifier, string); 229 235 } 230 236 } -
trunk/src/com/drew/metadata/iptc/Iso2022Converter.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 59 59 60 60 /** 61 * Attempts to guess the encodingof a string provided as a byte array.61 * Attempts to guess the {@link Charset} of a string provided as a byte array. 62 62 * <p> 63 * Encodings trialled are, in order:63 * Charsets trialled are, in order: 64 64 * <ul> 65 65 * <li>UTF-8</li> … … 68 68 * </ul> 69 69 * <p> 70 * Its only purpose is to guess the encoding if and only if iptctag coded character set is not set. If the70 * Its only purpose is to guess the Charset if and only if IPTC tag coded character set is not set. If the 71 71 * encoding is not UTF-8, the tag should be set. Otherwise it is bad practice. This method tries to 72 72 * workaround this issue since some metadata manipulating tools do not prevent such bad practice. … … 79 79 */ 80 80 @Nullable 81 static String guessEncoding(@NotNull final byte[] bytes)81 static Charset guessCharSet(@NotNull final byte[] bytes) 82 82 { 83 83 String[] encodings = { UTF_8, System.getProperty("file.encoding"), ISO_8859_1 }; … … 85 85 for (String encoding : encodings) 86 86 { 87 CharsetDecoder cs = Charset.forName(encoding).newDecoder(); 87 Charset charset = Charset.forName(encoding); 88 CharsetDecoder cs = charset.newDecoder(); 88 89 89 90 try { 90 91 cs.decode(ByteBuffer.wrap(bytes)); 91 return encoding;92 return charset; 92 93 } catch (CharacterCodingException e) { 93 94 // fall through... -
trunk/src/com/drew/metadata/jpeg/JpegCommentDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 30 30 * @author Drew Noakes https://drewnoakes.com 31 31 */ 32 @SuppressWarnings("WeakerAccess") 32 33 public class JpegCommentDescriptor extends TagDescriptor<JpegCommentDirectory> 33 34 { -
trunk/src/com/drew/metadata/jpeg/JpegCommentDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 31 31 * @author Drew Noakes https://drewnoakes.com 32 32 */ 33 @SuppressWarnings("WeakerAccess") 33 34 public class JpegCommentDirectory extends Directory 34 35 { -
trunk/src/com/drew/metadata/jpeg/JpegCommentReader.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 25 25 import com.drew.lang.annotations.NotNull; 26 26 import com.drew.metadata.Metadata; 27 import com.drew.metadata.StringValue; 27 28 28 29 import java.util.Collections; … … 49 50 50 51 // The entire contents of the directory are the comment 51 directory.setString (JpegCommentDirectory.TAG_COMMENT, new String(segmentBytes));52 directory.setStringValue(JpegCommentDirectory.TAG_COMMENT, new StringValue(segmentBytes, null)); 52 53 } 53 54 } -
trunk/src/com/drew/metadata/jpeg/JpegComponent.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 89 89 return _samplingFactorByte & 0x0F; 90 90 } 91 92 @NotNull 93 @Override 94 public String toString() { 95 return String.format( 96 "Quantization table %d, Sampling factors %d horiz/%d vert", 97 _quantizationTableNumber, 98 getHorizontalSamplingFactor(), 99 getVerticalSamplingFactor() 100 ); 101 } 91 102 } -
trunk/src/com/drew/metadata/jpeg/JpegDescriptor.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class JpegDescriptor extends TagDescriptor<JpegDirectory> 36 37 { … … 124 125 return null; 125 126 126 return value.getComponentName() + " component: Quantization table " + value.getQuantizationTableNumber() 127 + ", Sampling factors " + value.getHorizontalSamplingFactor() 128 + " horiz/" + value.getVerticalSamplingFactor() + " vert"; 127 return value.getComponentName() + " component: " + value; 129 128 } 130 129 } -
trunk/src/com/drew/metadata/jpeg/JpegDirectory.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 33 33 * @author Darrell Silver http://www.darrellsilver.com and Drew Noakes https://drewnoakes.com 34 34 */ 35 @SuppressWarnings("WeakerAccess") 35 36 public class JpegDirectory extends Directory 36 37 { -
trunk/src/com/drew/metadata/jpeg/JpegReader.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 52 52 JpegSegmentType.SOF6, 53 53 JpegSegmentType.SOF7, 54 JpegSegmentType.SOF8,54 // JpegSegmentType.JPG, 55 55 JpegSegmentType.SOF9, 56 56 JpegSegmentType.SOF10, -
trunk/src/com/drew/metadata/tiff/DirectoryTiffHandler.java
r10862 r13061 1 1 /* 2 * Copyright 2002-201 6Drew Noakes2 * Copyright 2002-2017 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 25 25 import com.drew.lang.annotations.NotNull; 26 26 import com.drew.metadata.Directory; 27 import com.drew.metadata.ErrorDirectory; 27 28 import com.drew.metadata.Metadata; 29 import com.drew.metadata.StringValue; 28 30 29 31 import java.util.Stack; … … 41 43 protected final Metadata _metadata; 42 44 43 protected DirectoryTiffHandler(Metadata metadata , Class<? extends Directory> initialDirectoryClass)45 protected DirectoryTiffHandler(Metadata metadata) 44 46 { 45 47 _metadata = metadata; 48 } 49 50 public void endingIFD() 51 { 52 _currentDirectory = _directoryStack.empty() ? null : _directoryStack.pop(); 53 } 54 55 protected void pushDirectory(@NotNull Class<? extends Directory> directoryClass) 56 { 57 Directory newDirectory = null; 58 46 59 try { 47 _currentDirectory = initialDirectoryClass.newInstance();60 newDirectory = directoryClass.newInstance(); 48 61 } catch (InstantiationException e) { 49 62 throw new RuntimeException(e); … … 51 64 throw new RuntimeException(e); 52 65 } 53 _metadata.addDirectory(_currentDirectory); 54 } 55 56 public void endingIFD() 57 { 58 _currentDirectory = _directoryStack.empty() ? null : _directoryStack.pop(); 59 } 60 61 protected void pushDirectory(@NotNull Class<? extends Directory> directoryClass) 62 { 63 _directoryStack.push(_currentDirectory); 64 try { 65 Directory newDirectory = directoryClass.newInstance(); 66 newDirectory.setParent(_currentDirectory); 66 67 if (newDirectory != null) 68 { 69 // If this is the first directory, don't add to the stack 70 if (_currentDirectory != null) 71 { 72 _directoryStack.push(_currentDirectory); 73 newDirectory.setParent(_currentDirectory); 74 } 67 75 _currentDirectory = newDirectory; 68 } catch (InstantiationException e) { 69 throw new RuntimeException(e); 70 } catch (IllegalAccessException e) { 71 throw new RuntimeException(e); 76 _metadata.addDirectory(_currentDirectory); 72 77 } 73 _metadata.addDirectory(_currentDirectory);74 78 } 75 79 76 80 public void warn(@NotNull String message) 77 81 { 78 _currentDirectory.addError(message);82 getCurrentOrErrorDirectory().addError(message); 79 83 } 80 84 81 85 public void error(@NotNull String message) 82 86 { 83 _currentDirectory.addError(message); 87 getCurrentOrErrorDirectory().addError(message); 88 } 89 90 @NotNull 91 private Directory getCurrentOrErrorDirectory() 92 { 93 if (_currentDirectory != null) 94 return _currentDirectory; 95 ErrorDirectory error = _metadata.getFirstDirectoryOfType(ErrorDirectory.class); 96 if (error != null) 97 return error; 98 pushDirectory(ErrorDirectory.class); 99 return _currentDirectory; 84 100 } 85 101 … … 89 105 } 90 106 91 public void setString(int tagId, @NotNull String string)92 { 93 _currentDirectory.setString (tagId, string);107 public void setString(int tagId, @NotNull StringValue string) 108 { 109 _currentDirectory.setStringValue(tagId, string); 94 110 } 95 111
Note:
See TracChangeset
for help on using the changeset viewer.