Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Editing jpeg EXIF data with Java

I want to edit jpg files' properties like: comments, title, date taken, camera maker, etc.

enter image description here

I have found libraries to read these data. But I need a free library with examples to edit them.

I'm aware of apache's imaging (sanselan). But I was not able to edit data with it. If you have previously used it yourself, I'd accept that as an answer only if you provide an example code other than the one in their website. Because even when I use their example I was not able to edit any property other than GPS data. After i run the code, file-properties-details still have the same values.

Thanks !

Note: I also tried JHeader (https://sourceforge.net/projects/jheader/) but using it as a process with -cl option still did not changed properties list.

like image 365
Null Pointer Avatar asked Apr 26 '16 14:04

Null Pointer


2 Answers

Apache commons Imaging works for me.

I have extended the sample provided here

So obviously my client code looks like this

public static void main(String[] args) throws ImageWriteException, ImageReadException, IOException {
    new WriteExifMetadataExample().changeExifMetadata(new File("somefilename.jpg"), new File("result_file.jpg"));
}

and the extended method in WriteExifMetadataExample

public void changeExifMetadata(final File jpegImageFile, final File dst)
        throws IOException, ImageReadException, ImageWriteException {
    OutputStream os = null;
    boolean canThrow = false;
    try {
        TiffOutputSet outputSet = null;

        // note that metadata might be null if no metadata is found.
        final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
        final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
        if (null != jpegMetadata) {
            // note that exif might be null if no Exif metadata is found.
            final TiffImageMetadata exif = jpegMetadata.getExif();

            if (null != exif) {
                // TiffImageMetadata class is immutable (read-only).
                // TiffOutputSet class represents the Exif data to write.
                //
                // Usually, we want to update existing Exif metadata by
                // changing
                // the values of a few fields, or adding a field.
                // In these cases, it is easiest to use getOutputSet() to
                // start with a "copy" of the fields read from the image.
                outputSet = exif.getOutputSet();
            }
        }

        // if file does not contain any exif metadata, we create an empty
        // set of exif metadata. Otherwise, we keep all of the other
        // existing tags.
        if (null == outputSet) {
            outputSet = new TiffOutputSet();
        }

        {
            // Example of how to add a field/tag to the output set.
            //
            // Note that you should first remove the field/tag if it already
            // exists in this directory, or you may end up with duplicate
            // tags. See above.
            //
            // Certain fields/tags are expected in certain Exif directories;
            // Others can occur in more than one directory (and often have a
            // different meaning in different directories).
            //
            // TagInfo constants often contain a description of what
            // directories are associated with a given tag.
            //
            final TiffOutputDirectory exifDirectory = outputSet
                    .getOrCreateExifDirectory();
            // make sure to remove old value if present (this method will
            // not fail if the tag does not exist).
            exifDirectory
                    .removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
            exifDirectory.add(ExifTagConstants.EXIF_TAG_APERTURE_VALUE,
                    new RationalNumber(3, 10));
        }

        {
            // Example of how to add/update GPS info to output set.

            // New York City
            final double longitude = -74.0; // 74 degrees W (in Degrees East)
            final double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees
            // North)

            outputSet.setGPSInDegrees(longitude, latitude);
        }



        final TiffOutputDirectory exifDirectory = outputSet
                .getOrCreateRootDirectory();
        exifDirectory
                .removeField(ExifTagConstants.EXIF_TAG_SOFTWARE);
        exifDirectory.add(ExifTagConstants.EXIF_TAG_SOFTWARE,
                "SomeKind");

        os = new FileOutputStream(dst);
        os = new BufferedOutputStream(os);

        new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
                outputSet);

        canThrow = true;
    } finally {
        IoUtils.closeQuietly(canThrow, os);
    }
}

Please pay attention only to line where I add additional tag

final TiffOutputDirectory exifDirectory = outputSet
                .getOrCreateRootDirectory();
        exifDirectory
                .removeField(ExifTagConstants.EXIF_TAG_SOFTWARE);
        exifDirectory.add(ExifTagConstants.EXIF_TAG_SOFTWARE,
                "SomeKind");

as a result EXIF tag was properly added

enter image description here


To change the comments tag you can do the following

        final TiffOutputDirectory exifDirectory = outputSet.getOrCreateRootDirectory();
        exifDirectory.removeField(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT);
        exifDirectory.add(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT, "SomeKind");

the full list of available constants is in the package:

org.apache.commons.imaging.formats.tiff.constants

enter image description here

like image 76
yurko Avatar answered Sep 19 '22 14:09

yurko


Would an example like this work for you?

I'd assume using packages like org.apache.commons.imaging.util.IoUtils and import org.apache.commons.imaging.Imaging would be of great help to you here.

like image 38
John Avatar answered Sep 18 '22 14:09

John