}
private void processMakerNote(int subdirOffset, HashMap processedDirectoryOffsets, int tiffHeaderOffset)
{
// Determine the camera model and makernote format
Directory exifDirectory = _metadata.getDirectory(ExifDirectory.class);
if (exifDirectory==null)
return;
String cameraModel = exifDirectory.getString(ExifDirectory.TAG_MAKE);
final String firstTwoChars = new String(_data, subdirOffset, 2);
final String firstThreeChars = new String(_data, subdirOffset, 3);
final String firstFourChars = new String(_data, subdirOffset, 4);
final String firstFiveChars = new String(_data, subdirOffset, 5);
final String firstSixChars = new String(_data, subdirOffset, 6);
final String firstSevenChars = new String(_data, subdirOffset, 7);
final String firstEightChars = new String(_data, subdirOffset, 8);
if ("OLYMP".equals(firstFiveChars) || "EPSON".equals(firstFiveChars) || "AGFA".equals(firstFourChars))
{
// Olympus Makernote
// Epson and Agfa use Olypus maker note standard, see:
// http://www.ozhiker.com/electronics/pjmt/jpeg_info/
processDirectory(_metadata.getDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset);
}
else if (cameraModel!=null && cameraModel.trim().toUpperCase().startsWith("NIKON"))
{
if ("Nikon".equals(firstFiveChars))
{
/* There are two scenarios here:
* Type 1: **
* :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
* :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
* Type 3: **
* :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
* :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
*/
if (_data[subdirOffset+6]==1)
processDirectory(_metadata.getDirectory(NikonType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset);
else if (_data[subdirOffset+6]==2)
processDirectory(_metadata.getDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 18, subdirOffset + 10);
else
exifDirectory.addError("Unsupported makernote data ignored.");
}
else
{
// The IFD begins with the first MakerNote byte (no ASCII name). This occurs with CoolPix 775, E990 and D1 models.
processDirectory(_metadata.getDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset);
}
}
else if ("SONY CAM".equals(firstEightChars) || "SONY DSC".equals(firstEightChars))
{
processDirectory(_metadata.getDirectory(SonyMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset);
}
else if ("KDK".equals(firstThreeChars))
{
processDirectory(_metadata.getDirectory(KodakMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 20, tiffHeaderOffset);
}
else if ("Canon".equalsIgnoreCase(cameraModel))
{
processDirectory(_metadata.getDirectory(CanonMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset);
}
else if (cameraModel!=null && cameraModel.toUpperCase().startsWith("CASIO"))
{
if ("QVC\u0000\u0000\u0000".equals(firstSixChars))
processDirectory(_metadata.getDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, tiffHeaderOffset);
else
processDirectory(_metadata.getDirectory(CasioType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset);
}
else if ("FUJIFILM".equals(firstEightChars) || "Fujifilm".equalsIgnoreCase(cameraModel))
{
// TODO make this field a passed parameter, to avoid threading issues
boolean byteOrderBefore = _isMotorollaByteOrder;
// bug in fujifilm makernote ifd means we temporarily use Intel byte ordering
_isMotorollaByteOrder = false;
// the 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote
// IFD, though the offset is relative to the start of the makernote, not the TIFF
// header (like everywhere else)
int ifdStart = subdirOffset + get32Bits(subdirOffset + 8);
processDirectory(_metadata.getDirectory(FujifilmMakernoteDirectory.class), processedDirectoryOffsets, ifdStart, tiffHeaderOffset);
_isMotorollaByteOrder = byteOrderBefore;
}
else if (cameraModel!=null && cameraModel.toUpperCase().startsWith("MINOLTA"))
{
// Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote
// area that commences immediately.
processDirectory(_metadata.getDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset);
}
else if ("KC".equals(firstTwoChars) || "MINOL".equals(firstFiveChars) || "MLY".equals(firstThreeChars) || "+M+M+M+M".equals(firstEightChars))
{
// This Konica data is not understood. Header identified in accordance with information at this site:
// http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html
// TODO determine how to process the information described at the above website
exifDirectory.addError("Unsupported Konica/Minolta data ignored.");
}
else if ("KYOCERA".equals(firstSevenChars))
{
// http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html
processDirectory(_metadata.getDirectory(KyoceraMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 22, tiffHeaderOffset);
}
else if ("Panasonic\u0000\u0000\u0000".equals(new String(_data, subdirOffset, 12)))
{
// NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD
// Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment
// more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html
processDirectory(_metadata.getDirectory(PanasonicMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset);
}
else if ("AOC\u0000".equals(firstFourChars))
{
// NON-Standard TIFF IFD Data using Casio Type 2 Tags
// IFD has no Next-IFD pointer at end of IFD, and
// Offsets are relative to the start of the current IFD tag, not the TIFF header
// Observed for:
// - Pentax ist D
processDirectory(_metadata.getDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, subdirOffset);
}
else if (cameraModel!=null && (cameraModel.toUpperCase().startsWith("PENTAX") || cameraModel.toUpperCase().startsWith("ASAHI")))
{
// NON-Standard TIFF IFD Data using Pentax Tags
// IFD has no Next-IFD pointer at end of IFD, and
// Offsets are relative to the start of the current IFD tag, not the TIFF header
// Observed for:
// - PENTAX Optio 330
// - PENTAX Optio 430
processDirectory(_metadata.getDirectory(PentaxMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, subdirOffset);
}
else
{
// TODO how to store makernote data when it's not from a supported camera model?
// this is difficult as the starting offset is not known. we could look for it...
exifDirectory.addError("Unsupported makernote data ignored.");
}
}