protected TiffOutputSummary validateDirectories(final TiffOutputSet outputSet)
throws ImageWriteException {
final List<TiffOutputDirectory> directories = outputSet.getDirectories();
if (directories.isEmpty()) {
throw new ImageWriteException("No directories.");
}
TiffOutputDirectory exifDirectory = null;
TiffOutputDirectory gpsDirectory = null;
TiffOutputDirectory interoperabilityDirectory = null;
TiffOutputField exifDirectoryOffsetField = null;
TiffOutputField gpsDirectoryOffsetField = null;
TiffOutputField interoperabilityDirectoryOffsetField = null;
final List<Integer> directoryIndices = new ArrayList<Integer>();
final Map<Integer, TiffOutputDirectory> directoryTypeMap = new HashMap<Integer, TiffOutputDirectory>();
for (TiffOutputDirectory directory : directories) {
final int dirType = directory.type;
directoryTypeMap.put(dirType, directory);
// Debug.debug("validating dirType", dirType + " ("
// + directory.getFields().size() + " fields)");
if (dirType < 0) {
switch (dirType) {
case DIRECTORY_TYPE_EXIF:
if (exifDirectory != null) {
throw new ImageWriteException(
"More than one EXIF directory.");
}
exifDirectory = directory;
break;
case DIRECTORY_TYPE_GPS:
if (gpsDirectory != null) {
throw new ImageWriteException(
"More than one GPS directory.");
}
gpsDirectory = directory;
break;
case DIRECTORY_TYPE_INTEROPERABILITY:
if (interoperabilityDirectory != null) {
throw new ImageWriteException(
"More than one Interoperability directory.");
}
interoperabilityDirectory = directory;
break;
default:
throw new ImageWriteException("Unknown directory: "
+ dirType);
}
} else {
if (directoryIndices.contains(dirType)) {
throw new ImageWriteException(
"More than one directory with index: " + dirType
+ ".");
}
directoryIndices.add(dirType);
// dirMap.put(arg0, arg1)
}
final HashSet<Integer> fieldTags = new HashSet<Integer>();
final List<TiffOutputField> fields = directory.getFields();
for (TiffOutputField field : fields) {
if (fieldTags.contains(field.tag)) {
throw new ImageWriteException("Tag ("
+ field.tagInfo.getDescription()
+ ") appears twice in directory.");
}
fieldTags.add(field.tag);
if (field.tag == ExifTagConstants.EXIF_TAG_EXIF_OFFSET.tag) {
if (exifDirectoryOffsetField != null) {
throw new ImageWriteException(
"More than one Exif directory offset field.");
}
exifDirectoryOffsetField = field;
} else if (field.tag == ExifTagConstants.EXIF_TAG_INTEROP_OFFSET.tag) {
if (interoperabilityDirectoryOffsetField != null) {
throw new ImageWriteException(
"More than one Interoperability directory offset field.");
}
interoperabilityDirectoryOffsetField = field;
} else if (field.tag == ExifTagConstants.EXIF_TAG_GPSINFO.tag) {
if (gpsDirectoryOffsetField != null) {
throw new ImageWriteException(
"More than one GPS directory offset field.");
}
gpsDirectoryOffsetField = field;
}
}
// directory.
}
if (directoryIndices.isEmpty()) {
throw new ImageWriteException("Missing root directory.");
}
// "normal" TIFF directories should have continous indices starting with
// 0, ie. 0, 1, 2...
Collections.sort(directoryIndices);
TiffOutputDirectory previousDirectory = null;
for (int i = 0; i < directoryIndices.size(); i++) {
final Integer index = directoryIndices.get(i);
if (index != i) {
throw new ImageWriteException("Missing directory: " + i + ".");
}
// set up chain of directory references for "normal" directories.
final TiffOutputDirectory directory = directoryTypeMap.get(index);
if (null != previousDirectory) {
previousDirectory.setNextDirectory(directory);
}
previousDirectory = directory;
}
final TiffOutputDirectory rootDirectory = directoryTypeMap
.get(DIRECTORY_TYPE_ROOT);
// prepare results
final TiffOutputSummary result = new TiffOutputSummary(byteOrder,
rootDirectory, directoryTypeMap);
if (interoperabilityDirectory == null
&& interoperabilityDirectoryOffsetField != null) {
// perhaps we should just discard field?
throw new ImageWriteException(
"Output set has Interoperability Directory Offset field, but no Interoperability Directory");
} else if (interoperabilityDirectory != null) {
if (exifDirectory == null) {
exifDirectory = outputSet.addExifDirectory();
}
if (interoperabilityDirectoryOffsetField == null) {
interoperabilityDirectoryOffsetField =
TiffOutputField.createOffsetField(
ExifTagConstants.EXIF_TAG_INTEROP_OFFSET,
byteOrder);
exifDirectory.add(interoperabilityDirectoryOffsetField);
}
result.add(interoperabilityDirectory,
interoperabilityDirectoryOffsetField);
}
// make sure offset fields and offset'd directories correspond.
if (exifDirectory == null && exifDirectoryOffsetField != null) {
// perhaps we should just discard field?
throw new ImageWriteException(
"Output set has Exif Directory Offset field, but no Exif Directory");
} else if (exifDirectory != null) {
if (exifDirectoryOffsetField == null) {
exifDirectoryOffsetField = TiffOutputField.createOffsetField(
ExifTagConstants.EXIF_TAG_EXIF_OFFSET, byteOrder);
rootDirectory.add(exifDirectoryOffsetField);
}
result.add(exifDirectory, exifDirectoryOffsetField);
}
if (gpsDirectory == null && gpsDirectoryOffsetField != null) {
// perhaps we should just discard field?
throw new ImageWriteException(
"Output set has GPS Directory Offset field, but no GPS Directory");
} else if (gpsDirectory != null) {
if (gpsDirectoryOffsetField == null) {
gpsDirectoryOffsetField = TiffOutputField.createOffsetField(
ExifTagConstants.EXIF_TAG_GPSINFO, byteOrder);