protected TiffOutputSummary validateDirectories()

in src/main/java/org/apache/commons/imaging/formats/tiff/write/AbstractTiffImageWriter.java [201:356]


    protected TiffOutputSummary validateDirectories(final TiffOutputSet outputSet) throws ImagingException {
        if (outputSet.isEmpty()) {
            throw new ImagingException("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<>();
        final Map<Integer, TiffOutputDirectory> directoryTypeMap = new HashMap<>();
        for (final TiffOutputDirectory directory : outputSet) {
            final int dirType = directory.getType();
            directoryTypeMap.put(dirType, directory);
            // Debug.debug("validating dirType", dirType + " ("
            // + directory.getFields().size() + " fields)");

            if (dirType < 0) {
                switch (dirType) {
                case TiffDirectoryConstants.DIRECTORY_TYPE_EXIF:
                    if (exifDirectory != null) {
                        throw new ImagingException("More than one EXIF directory.");
                    }
                    exifDirectory = directory;
                    break;

                case TiffDirectoryConstants.DIRECTORY_TYPE_GPS:
                    if (gpsDirectory != null) {
                        throw new ImagingException("More than one GPS directory.");
                    }
                    gpsDirectory = directory;
                    break;

                case TiffDirectoryConstants.DIRECTORY_TYPE_INTEROPERABILITY:
                    if (interoperabilityDirectory != null) {
                        throw new ImagingException("More than one Interoperability directory.");
                    }
                    interoperabilityDirectory = directory;
                    break;
                default:
                    throw new ImagingException("Unknown directory: " + dirType);
                }
            } else {
                if (directoryIndices.contains(dirType)) {
                    throw new ImagingException("More than one directory with index: " + dirType + ".");
                }
                directoryIndices.add(dirType);
                // dirMap.put(arg0, arg1)
            }

            final HashSet<Integer> fieldTags = new HashSet<>();
            for (final TiffOutputField field : directory) {
                if (fieldTags.contains(field.tag)) {
                    throw new ImagingException("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 ImagingException("More than one Exif directory offset field.");
                    }
                    exifDirectoryOffsetField = field;
                } else if (field.tag == ExifTagConstants.EXIF_TAG_INTEROP_OFFSET.tag) {
                    if (interoperabilityDirectoryOffsetField != null) {
                        throw new ImagingException("More than one Interoperability directory offset field.");
                    }
                    interoperabilityDirectoryOffsetField = field;
                } else if (field.tag == ExifTagConstants.EXIF_TAG_GPSINFO.tag) {
                    if (gpsDirectoryOffsetField != null) {
                        throw new ImagingException("More than one GPS directory offset field.");
                    }
                    gpsDirectoryOffsetField = field;
                }
            }
            // directory.
        }

        if (directoryIndices.isEmpty()) {
            throw new ImagingException("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 ImagingException("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(TiffDirectoryConstants.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 ImagingException("Output set has Interoperability Directory Offset field, but no Interoperability Directory");
        }
        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 ImagingException("Output set has Exif Directory Offset field, but no Exif Directory");
        }
        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 ImagingException("Output set has GPS Directory Offset field, but no GPS Directory");
        }
        if (gpsDirectory != null) {
            if (gpsDirectoryOffsetField == null) {
                gpsDirectoryOffsetField = TiffOutputField.createOffsetField(ExifTagConstants.EXIF_TAG_GPSINFO, byteOrder);
                rootDirectory.add(gpsDirectoryOffsetField);
            }

            result.add(gpsDirectory, gpsDirectoryOffsetField);
        }

        return result;

        // Debug.debug();
    }