Update Exif Metadata with Commons Imaging

Recently, I organized all my photos and upload them to google photo. But after that I realized, some of them do not have the correct Exif information. Especially the taken date. Some because I have edited, some because my phone doesn’t save the correct metadata. I update some of them manually. But there are still so many. So I try Python, C# and this (Commons Imaging: a Pure-Java Image Library).

Download Apache Commons Imaging

At first, I feel disappointed, because there is no valid link to its latest download page (Apache Commons Imaging 1.0). But after I tried metadata-extractor, JHeader, ExifTool and PIL, I still could not update my photos’ Exif. So I come back to Apache Commons Imaging, and I finally find a usable download page of it.

Update Exif of Date Taken Method

The code below is simple, but you can update any metadata if you want. There are also more information from here.

public static void updateExifOfDateTaken(File file, String dateTaken) {
    OutputStream os = null;
    TiffOutputSet outputSet = null;
    try {
        IImageMetadata metadata = Imaging.getMetadata(file);
        if (metadata instanceof JpegImageMetadata) {
            TiffImageMetadata exif = ((JpegImageMetadata) metadata).getExif();
            if (exif != null) {
                // TiffImageMetadata class is immutable (read-only).
                // TiffOutputSet class represents the Exif data to write.
                outputSet = exif.getOutputSet();
            }

            if (outputSet == null) {
                outputSet = new TiffOutputSet();
            }

            // Note that you should first remove the field/tag if it already
            // exists in this directory, or you may end up with duplicate tags.
            TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();
            exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
            exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
                    dateTaken);

            File successFolder = new File(file.getParent() + "\\success");
            if (!successFolder.exists()) {
                if (!successFolder.mkdirs()) {
                    throw new IOException("Failed to create directory "
                            + successFolder.getPath());
                }
            }

            if (successFolder.exists()) {
                os = new BufferedOutputStream(new FileOutputStream(successFolder
                        + "\\" + file.getName()));
                new ExifRewriter().updateExifMetadataLossless(file, os, outputSet);
            }
        }
    } catch (Exception e) {
        File failFolder = new File(file.getParent() + "\\fail");
        if (!failFolder.exists()) {
            if (failFolder.mkdirs()) {
                file.renameTo(new File(failFolder + "\\" + file.getName()));
                System.out.println("Failed update " + file.getName());
            } else {
                System.out.println("Failed to create directory "
                        + failFolder.getPath());
            }
        }
    }
}

Main Method

public static void main(String[] args) {
    File photoFolder = new File("D:\\Desktop\\New folder");
    for (File fileEntry : photoFolder.listFiles()) {
        if (fileEntry.isFile()) {
            updateExifOfDateTaken(fileEntry, getDateTaken(fileEntry));
        }
    }
}

Because of my photos’ file name is exactly the date taken. I also write a method to create the new date from the photo.

Before Updating Date Taken

public static String getDateTaken(File file) {
    String fileName = file.getName().replaceFirst("[.][^.]+$", "");
    String year = fileName.substring(0, 4);
    String month = fileName.substring(4, 6);
    String date = fileName.substring(6, 8);
    String hour = fileName.substring(9, 11);
    String minute = fileName.substring(11, 13);
    String second = fileName.substring(13, 15);
    return (year + ":" + month + ":" + date + " "
            + hour + ":" + minute + ":" + second);
}

After Updating Date Taken

It works :-)

After Updating Date Taken