com.drew.imaging.ImageProcessingException Java Examples

The following examples show how to use com.drew.imaging.ImageProcessingException. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: MutableImage.java    From react-native-camera-face-detector with MIT License 6 votes vote down vote up
public void fixOrientation() throws ImageMutationFailedException {
    try {
        Metadata metadata = originalImageMetaData();

        ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
        if (exifIFD0Directory == null) {
            return;
        } else if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
            int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
            if(exifOrientation != 1) {
                rotate(exifOrientation);
                exifIFD0Directory.setInt(ExifIFD0Directory.TAG_ORIENTATION, 1);
            }
        }
    } catch (ImageProcessingException | IOException | MetadataException e) {
        throw new ImageMutationFailedException("failed to fix orientation", e);
    }
}
 
Example #2
Source File: ImageResource.java    From entando-components with GNU Lesser General Public License v3.0 6 votes vote down vote up
protected Map<String, String> getImgMetadata(File file, List<String> ignoreKeysList) {
    logger.debug("Get image Metadata in Resource Action");
    Map<String, String> meta = new HashMap<>();
    try {
        Metadata metadata = ImageMetadataReader.readMetadata(file);

        for (Directory directory : metadata.getDirectories()) {
            for (Tag tag : directory.getTags()) {
                if (!ignoreKeysList.contains(tag.getTagName())) {
                    logger.debug("Add Metadata with key: {}", tag.getTagName());
                    meta.put(tag.getTagName(), tag.getDescription());
                } else {
                    logger.debug("Skip Metadata key {}", tag.getTagName());
                }
            }
        }
    } catch (ImageProcessingException|IOException ex) {
        logger.error("Error reading image metadata for file {}", file.getName(), ex);
    }
    return meta;
}
 
Example #3
Source File: ImgUtilsTest.java    From TranskribusCore with GNU General Public License v3.0 6 votes vote down vote up
public void testExiftoolVsImageIO() throws FileNotFoundException, IOException, TimeoutException, InterruptedException, ImageProcessingException, MetadataException {
//		File imgFile = new File("/mnt/dea_scratch/TRP/test/I._ZvS_1902_4.Q/ZS-I-1902-198 (1).jpg");
		File imgFile = new File("/tmp/Exif_orientation_test/Exif_orientation_test/IMG_20181115_144511.jpg");
		SSW sw = new SSW();
		sw.start();
		Dimension dim = ImgUtils.readImageDimensionsWithExiftool(imgFile);
		long exiftoolTime = sw.stop(true, "exiftool: ");
		sw.start();
		Dimension dim2 = TrpImageIO.readImageDimensions(imgFile);
		long imageioTime = sw.stop(true, "imageio: ");
		sw.start();
		Dimension dim3 = ImgUtils.readImageDimensionsWithMdParser(imgFile);
		long mdExtractorTime = sw.stop(true, "md-extractor: ");
		
		logger.info("exiftool: " + dim.getWidth() + " x " + dim.getHeight() + " -> " + exiftoolTime + " ms");
		logger.info("imageio: " + dim2.getWidth() + " x " + dim2.getHeight() + " -> " + imageioTime + " ms");
		logger.info("md-extractor: " + dim3.getWidth() + " x " + dim3.getHeight() + " -> " + mdExtractorTime + " ms");
	}
 
Example #4
Source File: SampleProcessor.java    From tutorials with Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
  LOG.info("Input record: {}", record);

  FileRef fileRef = record.get("/fileRef").getValueAsFileRef();
  Metadata metadata;
  try {
    metadata = ImageMetadataReader.readMetadata(fileRef.createInputStream(getContext(), InputStream.class));
  } catch (ImageProcessingException | IOException e) {
    String filename = record.get("/fileInfo/filename").getValueAsString();
    LOG.info("Exception getting metadata from {}", filename, e);
    throw new OnRecordErrorException(record, Errors.SAMPLE_02, e);
  }

  for (Directory directory : metadata.getDirectories()) {
    LinkedHashMap<String, Field> listMap = new LinkedHashMap<>();

    for (Tag tag : directory.getTags()) {
      listMap.put(tag.getTagName(), Field.create(tag.getDescription()));
    }

    if (directory.hasErrors()) {
      for (String error : directory.getErrors()) {
        LOG.info("ERROR: {}", error);
      }
    }

    record.set("/" + directory.getName(), Field.createListMap(listMap));
  }

  LOG.info("Output record: {}", record);

  batchMaker.addRecord(record);
}
 
Example #5
Source File: ImageMetadata.java    From scrimage with Apache License 2.0 5 votes vote down vote up
public static ImageMetadata fromImage(ImmutableImage image) throws IOException {
   try (ByteArrayInputStream stream = new ByteArrayInputStream(image.bytes(PngWriter.NoCompression))) {
      Metadata metadata = ImageMetadataReader.readMetadata(stream);
      return fromMetadata(metadata);
   } catch (ImageProcessingException e) {
      throw new IOException(e);
   }
}
 
Example #6
Source File: ImageMetadata.java    From scrimage with Apache License 2.0 5 votes vote down vote up
public static ImageMetadata load(ImageSource source) throws IOException {
   try {
      return fromMetadata(ImageMetadataReader.readMetadata(new ByteArrayInputStream(source.read())));
   } catch (ImageProcessingException e) {
      return ImageMetadata.empty;
   }
}
 
Example #7
Source File: ExtractImageMetadata.java    From nifi with Apache License 2.0 5 votes vote down vote up
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
    FlowFile flowfile = session.get();
    if (flowfile == null) {
        return;
    }

    final ComponentLog logger = this.getLogger();
    final AtomicReference<Metadata> value = new AtomicReference<>(null);
    final Integer max = context.getProperty(MAX_NUMBER_OF_ATTRIBUTES).asInteger();

    try {
        session.read(flowfile, new InputStreamCallback() {
            @Override
            public void process(InputStream in) throws IOException {
                try {
                    Metadata imageMetadata = ImageMetadataReader.readMetadata(in);
                    value.set(imageMetadata);
                } catch (ImageProcessingException ex) {
                    throw new ProcessException(ex);
                }
            }
        });

        Metadata metadata = value.get();
        Map<String, String> results = getTags(max, metadata);

        // Write the results to an attribute
        if (!results.isEmpty()) {
            flowfile = session.putAllAttributes(flowfile, results);
        }

        session.transfer(flowfile, SUCCESS);
    } catch (ProcessException e) {
        logger.error("Failed to extract image metadata from {} due to {}", new Object[]{flowfile, e});
        session.transfer(flowfile, FAILURE);
    }
}
 
Example #8
Source File: ResourceAction.java    From entando-components with GNU Lesser General Public License v3.0 5 votes vote down vote up
protected Map getImgMetadata(File file) {
    logger.debug("Get image Metadata in Resource Action");
    Map<String, String> meta = new HashMap<>();
    ResourceInterface resourcePrototype = this.getResourceManager().createResourceType(this.getResourceType());
    try {
        Metadata metadata = ImageMetadataReader.readMetadata(file);
        String ignoreKeysConf = resourcePrototype.getMetadataIgnoreKeys();
        String[] ignoreKeys = null;
        if (null != ignoreKeysConf) {
            ignoreKeys = ignoreKeysConf.split(",");
            logger.debug("Metadata ignoreKeys: {}", ignoreKeys);
        } else {
            logger.debug("Metadata ignoreKeys not configured");
        }
        List<String> ignoreKeysList = new ArrayList<String>();
        if (null != ignoreKeys) {
            ignoreKeysList = Arrays.asList(ignoreKeys);
        }
        for (Directory directory : metadata.getDirectories()) {
            for (Tag tag : directory.getTags()) {
                if (!ignoreKeysList.contains(tag.getTagName())) {
                    logger.debug("Add Metadata with key: {}", tag.getTagName());
                    meta.put(tag.getTagName(), tag.getDescription());
                } else {
                    logger.debug("Skip Metadata key {}", tag.getTagName());
                }
            }
        }
    } catch (ImageProcessingException ex) {
        logger.error("Error reading metadata from file " + this.getFileName() + " - message " + ex.getMessage());
    } catch (IOException ioex) {
        logger.error("Error reading file", ioex);
    }
    return meta;
}
 
Example #9
Source File: MetaDataPanel.java    From Pixelitor with GNU General Public License v3.0 5 votes vote down vote up
private static Metadata extractMetadata(File file) {
    Metadata metadata;
    try {
        metadata = ImageMetadataReader.readMetadata(file);
    } catch (ImageProcessingException | IOException e) {
        Messages.showException(e);
        return null;
    }
    return metadata;
}
 
Example #10
Source File: XmpSample.java    From metadata-extractor with Apache License 2.0 5 votes vote down vote up
private static void xmpSample(InputStream imageStream) throws XMPException, ImageProcessingException, IOException
{
    // Extract metadata from the image
    Metadata metadata = ImageMetadataReader.readMetadata(imageStream);

    // Iterate through any XMP directories we may have received
    for (XmpDirectory xmpDirectory : metadata.getDirectoriesOfType(XmpDirectory.class)) {

        // Usually with metadata-extractor, you iterate a directory's tags. However XMP has
        // a complex structure with many potentially unknown properties. This doesn't map
        // well to metadata-extractor's directory-and-tag model.
        //
        // If you need to use XMP data, access the XMPMeta object directly.
        XMPMeta xmpMeta = xmpDirectory.getXMPMeta();

        XMPIterator itr = xmpMeta.iterator();

        // Iterate XMP properties
        while (itr.hasNext()) {

            XMPPropertyInfo property = (XMPPropertyInfo) itr.next();

            // Print details of the property
            System.out.println(property.getPath() + ": " + property.getValue());
        }
    }
}
 
Example #11
Source File: QuickTimeMetadataReader.java    From metadata-extractor with Apache License 2.0 5 votes vote down vote up
@NotNull
public static Metadata readMetadata(@NotNull final File file) throws ImageProcessingException, IOException
{
    InputStream inputStream = new FileInputStream(file);
    Metadata metadata;
    try {
        metadata = readMetadata(inputStream);
    } finally {
        inputStream.close();
    }
    new FileSystemMetadataReader().read(file, metadata);
    return metadata;
}
 
Example #12
Source File: Mp4MetadataReader.java    From metadata-extractor with Apache License 2.0 5 votes vote down vote up
@NotNull
public static Metadata readMetadata(@NotNull final File file) throws ImageProcessingException, IOException
{
    InputStream inputStream = new FileInputStream(file);
    Metadata metadata;
    try {
        metadata = readMetadata(inputStream);
    } finally {
        inputStream.close();
    }
    new FileSystemMetadataReader().read(file, metadata);
    return metadata;
}
 
Example #13
Source File: ExtractImageMetadata.java    From localization_nifi with Apache License 2.0 5 votes vote down vote up
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
    FlowFile flowfile = session.get();
    if (flowfile == null) {
        return;
    }

    final ComponentLog logger = this.getLogger();
    final AtomicReference<Metadata> value = new AtomicReference<>(null);
    final Integer max = context.getProperty(MAX_NUMBER_OF_ATTRIBUTES).asInteger();

    try {
        session.read(flowfile, new InputStreamCallback() {
            @Override
            public void process(InputStream in) throws IOException {
                try {
                    Metadata imageMetadata = ImageMetadataReader.readMetadata(in);
                    value.set(imageMetadata);
                } catch (ImageProcessingException ex) {
                    throw new ProcessException(ex);
                }
            }
        });

        Metadata metadata = value.get();
        Map<String, String> results = getTags(max, metadata);

        // Write the results to an attribute
        if (!results.isEmpty()) {
            flowfile = session.putAllAttributes(flowfile, results);
        }

        session.transfer(flowfile, SUCCESS);
    } catch (ProcessException e) {
        logger.error("Failed to extract image metadata from {} due to {}", new Object[]{flowfile, e});
        session.transfer(flowfile, FAILURE);
    }
}
 
Example #14
Source File: ImgUtils.java    From TranskribusCore with GNU General Public License v3.0 5 votes vote down vote up
public static Dimension readImageDimensionsWithMdParser(URL url) throws FileNotFoundException, IOException {
	try {
		ImageTransformation imgDim = TrpImgMdParser.readImageDimension(url);
		return new Dimension(imgDim.getDestinationWidth(), imgDim.getDestinationHeight());
	} catch(ImageProcessingException | MetadataException e) {
		logger.warn("Metadata extractor did not find EXIF data. Falling back to reading raw image data dimension.");
		return TrpImageIO.readImageDimensions(url);
	}
}
 
Example #15
Source File: ImgUtils.java    From TranskribusCore with GNU General Public License v3.0 5 votes vote down vote up
public static Dimension readImageDimensionsWithMdParser(File imgFile) throws FileNotFoundException, IOException {
	try {
		ImageTransformation imgDim = TrpImgMdParser.readImageDimension(imgFile);
		return new Dimension(imgDim.getDestinationWidth(), imgDim.getDestinationHeight());
	} catch(ImageProcessingException | MetadataException e) {
		logger.warn("Metadata extractor did not find EXIF data. Falling back to reading raw image data dimension.");
		return TrpImageIO.readImageDimensions(imgFile);
	}
}
 
Example #16
Source File: CreateFilePane.java    From pattypan with MIT License 5 votes vote down vote up
/**
 *
 * @param filePath
 * @return
 */
private String getExifDate(File file) {

  try {
    Metadata metadata = ImageMetadataReader.readMetadata(file);
    Directory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
    int dateTag = ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL;

    if (directory != null && directory.containsTag(dateTag)) {
      Date date = directory.getDate(dateTag, TimeZone.getDefault());
      return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date);
    } else {
      return "";
    }
  } catch (ImageProcessingException | IOException ex) {
    Session.LOGGER.log(Level.INFO, 
        "Exif error for {0}: {1}",
        new String[]{file.getName(), ex.getLocalizedMessage()}
    );
    return "";
  }
}
 
Example #17
Source File: MutableImage.java    From react-native-camera-face-detector with MIT License 5 votes vote down vote up
private Metadata originalImageMetaData() throws ImageProcessingException, IOException {
    if(this.originalImageMetaData == null) {//this is expensive, don't do it more than once
        originalImageMetaData = ImageMetadataReader.readMetadata(
                new BufferedInputStream(new ByteArrayInputStream(originalImageData)),
                originalImageData.length
        );
    }
    return originalImageMetaData;
}
 
Example #18
Source File: MutableImage.java    From react-native-camera-face-detector with MIT License 5 votes vote down vote up
public void writeDataToFile(File file, ReadableMap options, int jpegQualityPercent) throws IOException {
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(toJpeg(currentRepresentation, jpegQualityPercent));
    fos.close();

    try {
        ExifInterface exif = new ExifInterface(file.getAbsolutePath());

        // copy original exif data to the output exif...
        // unfortunately, this Android ExifInterface class doesn't understand all the tags so we lose some
        for (Directory directory : originalImageMetaData().getDirectories()) {
            for (Tag tag : directory.getTags()) {
                int tagType = tag.getTagType();
                Object object = directory.getObject(tagType);
                exif.setAttribute(tag.getTagName(), object.toString());
            }
        }

        writeLocationExifData(options, exif);

        if(hasBeenReoriented)
            rewriteOrientation(exif);

        exif.saveAttributes();
    } catch (ImageProcessingException  | IOException e) {
        Log.e(TAG, "failed to save exif data", e);
    }
}
 
Example #19
Source File: ImageDataReaderTest.java    From java-11-examples with Apache License 2.0 5 votes vote down vote up
@Test
public void testExifDataRead() throws ImageProcessingException, IOException {
    final String imagePath = "/IMG_20180827_190350.jpg";
    LOG.info("reading image {}", imagePath);
    InputStream imageStream = this.getClass().getResourceAsStream(imagePath);
    ImageInfo imageInfo = ImageDataReader.getImageInfo(imageStream);
    Assert.assertNotNull(imageInfo);
    Assert.assertTrue(imageInfo.getPixelsX() == 2448);
    Assert.assertTrue(imageInfo.getPixelsY() == 3264);
}
 
Example #20
Source File: ImageDataReader.java    From java-11-examples with Apache License 2.0 5 votes vote down vote up
public static ImageInfo getImageInfo(InputStream imageStream) throws ImageProcessingException, IOException {
    Metadata metadata = ImageMetadataReader.readMetadata(imageStream);
    ImageInfo.Builder builder = new ImageInfo.Builder();
    for (Directory directory: metadata.getDirectories()) {
        for (Tag tag: directory.getTags()) {
            if (ParsingUtils.IMAGE_HEIGHT.equals(tag.getTagName())) {
                builder.setPixelsY(ParsingUtils.getIntegerFromData(tag.getDescription()));
            } else if (ParsingUtils.IMAGE_WIDTH.equals(tag.getTagName())) {
                builder.setPixelsX(ParsingUtils.getIntegerFromData(tag.getDescription()));
            }
        }
    }
    return builder.build();
}
 
Example #21
Source File: PcxReader.java    From metadata-extractor with Apache License 2.0 4 votes vote down vote up
public void extract(@NotNull final SequentialReader reader, @NotNull final Metadata metadata)
{
    reader.setMotorolaByteOrder(false);

    PcxDirectory directory = new PcxDirectory();
    metadata.addDirectory(directory);

    try {
        byte identifier = reader.getInt8();
        if (identifier != 0x0A)
            throw new ImageProcessingException("Invalid PCX identifier byte");

        directory.setInt(PcxDirectory.TAG_VERSION, reader.getInt8());

        byte encoding = reader.getInt8();
        if (encoding != 0x01)
            throw new ImageProcessingException("Invalid PCX encoding byte");

        directory.setInt(PcxDirectory.TAG_BITS_PER_PIXEL, reader.getUInt8());
        directory.setInt(PcxDirectory.TAG_XMIN,           reader.getUInt16());
        directory.setInt(PcxDirectory.TAG_YMIN,           reader.getUInt16());
        directory.setInt(PcxDirectory.TAG_XMAX,           reader.getUInt16());
        directory.setInt(PcxDirectory.TAG_YMAX,           reader.getUInt16());
        directory.setInt(PcxDirectory.TAG_HORIZONTAL_DPI, reader.getUInt16());
        directory.setInt(PcxDirectory.TAG_VERTICAL_DPI,   reader.getUInt16());
        directory.setByteArray(PcxDirectory.TAG_PALETTE,  reader.getBytes(48));
        reader.skip(1);
        directory.setInt(PcxDirectory.TAG_COLOR_PLANES,   reader.getUInt8());
        directory.setInt(PcxDirectory.TAG_BYTES_PER_LINE, reader.getUInt16());

        int paletteType = reader.getUInt16();
        if (paletteType != 0)
            directory.setInt(PcxDirectory.TAG_PALETTE_TYPE, paletteType);

        int hScrSize = reader.getUInt16();
        if (hScrSize != 0)
            directory.setInt(PcxDirectory.TAG_HSCR_SIZE, hScrSize);

        int vScrSize = reader.getUInt16();
        if (vScrSize != 0)
            directory.setInt(PcxDirectory.TAG_VSCR_SIZE, vScrSize);

    } catch (Exception ex) {
        directory.addError("Exception reading PCX file metadata: " + ex.getMessage());
    }
}
 
Example #22
Source File: PhotoshopReader.java    From metadata-extractor with Apache License 2.0 4 votes vote down vote up
public void extract(@NotNull final SequentialReader reader, int length, @NotNull final Metadata metadata, @Nullable final Directory parentDirectory)
{
    PhotoshopDirectory directory = new PhotoshopDirectory();
    metadata.addDirectory(directory);

    if (parentDirectory != null)
        directory.setParent(parentDirectory);

    // Data contains a sequence of Image Resource Blocks (IRBs):
    //
    // 4 bytes - Signature; mostly "8BIM" but "PHUT", "AgHg" and "DCSR" are also found
    // 2 bytes - Resource identifier
    // String  - Pascal string, padded to make length even
    // 4 bytes - Size of resource data which follows
    // Data    - The resource data, padded to make size even
    //
    // http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1037504

    int pos = 0;
    int clippingPathCount = 0;
    while (pos < length) {
        try {
            // 4 bytes for the signature ("8BIM", "PHUT", etc.)
            String signature = reader.getString(4);
            pos += 4;

            // 2 bytes for the resource identifier (tag type).
            int tagType = reader.getUInt16(); // segment type
            pos += 2;

            // A variable number of bytes holding a pascal string (two leading bytes for length).
            short descriptionLength = reader.getUInt8();
            pos += 1;
            // Some basic bounds checking
            if (descriptionLength < 0 || descriptionLength + pos > length)
                throw new ImageProcessingException("Invalid string length");

            // Get name (important for paths)
            StringBuilder description = new StringBuilder();
            descriptionLength += pos;
            // Loop through each byte and append to string
            while (pos < descriptionLength) {
                description.append((char)reader.getUInt8());
                pos ++;
            }

            // The number of bytes is padded with a trailing zero, if needed, to make the size even.
            if (pos % 2 != 0) {
                reader.skip(1);
                pos++;
            }

            // 4 bytes for the size of the resource data that follows.
            int byteCount = reader.getInt32();
            pos += 4;
            // The resource data.
            byte[] tagBytes = reader.getBytes(byteCount);
            pos += byteCount;
            // The number of bytes is padded with a trailing zero, if needed, to make the size even.
            if (pos % 2 != 0) {
                reader.skip(1);
                pos++;
            }

            if (signature.equals("8BIM")) {
                if (tagType == PhotoshopDirectory.TAG_IPTC)
                    new IptcReader().extract(new SequentialByteArrayReader(tagBytes), metadata, tagBytes.length, directory);
                else if (tagType == PhotoshopDirectory.TAG_ICC_PROFILE_BYTES)
                    new IccReader().extract(new ByteArrayReader(tagBytes), metadata, directory);
                else if (tagType == PhotoshopDirectory.TAG_EXIF_DATA_1 || tagType == PhotoshopDirectory.TAG_EXIF_DATA_3)
                    new ExifReader().extract(new ByteArrayReader(tagBytes), metadata, 0, directory);
                else if (tagType == PhotoshopDirectory.TAG_XMP_DATA)
                    new XmpReader().extract(tagBytes, metadata, directory);
                else if (tagType >= 0x07D0 && tagType <= 0x0BB6) {
                    clippingPathCount++;
                    tagBytes = Arrays.copyOf(tagBytes, tagBytes.length + description.length() + 1);
                    // Append description(name) to end of byte array with 1 byte before the description representing the length
                    for (int i = tagBytes.length - description.length() - 1; i < tagBytes.length; i++) {
                        if (i % (tagBytes.length - description.length() - 1 + description.length()) == 0)
                            tagBytes[i] = (byte)description.length();
                        else
                            tagBytes[i] = (byte)description.charAt(i - (tagBytes.length - description.length() - 1));
                    }
                    PhotoshopDirectory._tagNameMap.put(0x07CF + clippingPathCount, "Path Info " + clippingPathCount);
                    directory.setByteArray(0x07CF + clippingPathCount, tagBytes);
                }
                else
                    directory.setByteArray(tagType, tagBytes);

                if (tagType >= 0x0fa0 && tagType <= 0x1387)
                    PhotoshopDirectory._tagNameMap.put(tagType, String.format("Plug-in %d Data", tagType - 0x0fa0 + 1));
            }
        } catch (Exception ex) {
            directory.addError(ex.getMessage());
            return;
        }
    }
}
 
Example #23
Source File: MetadataUtil.java    From cineast with MIT License 3 votes vote down vote up
/**
 * Reads the {@link Metadata} from the given {@link Path} and returns the first {@link Directory}
 * of the specified type, if present.
 *
 * <p>Note that this is an utility method when one is interested in only one specific
 * {@code Directory}. Use {@code Metadata} and its factory methods
 * (e.g. {@link ImageMetadataReader#readMetadata} if multiple directories or more fine-graded
 * control is needed.
 *
 * @param path a path from which the directory may be read.
 * @param directoryType the {@code Directory} type
 * @param <T> the {@code Directory} type
 * @return an {@link Optional} containing the first {@code Directory} of type {@code T} of the
 *         metadata of the file, if present, otherwise an empty {@code Optional}.
 */
public static <T extends Directory> T getMetadataDirectoryOfType(Path path,
    Class<T> directoryType) {
  Metadata metadata = null;
  try {
    metadata = ImageMetadataReader.readMetadata(path.toFile());
  } catch (ImageProcessingException | IOException e) {
    logger.error("Error while reading exif data of file {}: {}",
        path, LogHelper.getStackTrace(e));
  }
  if(metadata==null){
    return null;
  }
  return metadata.getFirstDirectoryOfType( directoryType );
}