View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.examples;
18  
19  import java.io.BufferedOutputStream;
20  import java.io.File;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  
25  import org.apache.commons.imaging.ImageReadException;
26  import org.apache.commons.imaging.ImageWriteException;
27  import org.apache.commons.imaging.Imaging;
28  import org.apache.commons.imaging.common.ImageMetadata;
29  import org.apache.commons.imaging.common.RationalNumber;
30  import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
31  import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
32  import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
33  import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
34  import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
35  import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
36  import org.apache.commons.io.FileUtils;
37  
38  public class WriteExifMetadataExample {
39      public void removeExifMetadata(final File jpegImageFile, final File dst)
40              throws IOException, ImageReadException, ImageWriteException {
41          try (FileOutputStream fos = new FileOutputStream(dst);
42                  OutputStream os = new BufferedOutputStream(fos)) {
43              new ExifRewriter().removeExifMetadata(jpegImageFile, os);
44          }
45      }
46  
47      /**
48       * This example illustrates how to add/update EXIF metadata in a JPEG file.
49       * 
50       * @param jpegImageFile
51       *            A source image file.
52       * @param dst
53       *            The output file.
54       * @throws IOException
55       * @throws ImageReadException
56       * @throws ImageWriteException
57       */
58      public void changeExifMetadata(final File jpegImageFile, final File dst)
59              throws IOException, ImageReadException, ImageWriteException {
60          
61          try (FileOutputStream fos = new FileOutputStream(dst);
62                  OutputStream os = new BufferedOutputStream(fos);) {
63              
64              TiffOutputSet outputSet = null;
65  
66              // note that metadata might be null if no metadata is found.
67              final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
68              final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
69              if (null != jpegMetadata) {
70                  // note that exif might be null if no Exif metadata is found.
71                  final TiffImageMetadata exif = jpegMetadata.getExif();
72  
73                  if (null != exif) {
74                      // TiffImageMetadata class is immutable (read-only).
75                      // TiffOutputSet class represents the Exif data to write.
76                      //
77                      // Usually, we want to update existing Exif metadata by
78                      // changing
79                      // the values of a few fields, or adding a field.
80                      // In these cases, it is easiest to use getOutputSet() to
81                      // start with a "copy" of the fields read from the image.
82                      outputSet = exif.getOutputSet();
83                  }
84              }
85  
86              // if file does not contain any exif metadata, we create an empty
87              // set of exif metadata. Otherwise, we keep all of the other
88              // existing tags.
89              if (null == outputSet) {
90                  outputSet = new TiffOutputSet();
91              }
92  
93              {
94                  // Example of how to add a field/tag to the output set.
95                  //
96                  // Note that you should first remove the field/tag if it already
97                  // exists in this directory, or you may end up with duplicate
98                  // tags. See above.
99                  //
100                 // Certain fields/tags are expected in certain Exif directories;
101                 // Others can occur in more than one directory (and often have a
102                 // different meaning in different directories).
103                 //
104                 // TagInfo constants often contain a description of what
105                 // directories are associated with a given tag.
106                 //
107                 final TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();
108                 // make sure to remove old value if present (this method will
109                 // not fail if the tag does not exist).
110                 exifDirectory.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
111                 exifDirectory.add(ExifTagConstants.EXIF_TAG_APERTURE_VALUE,
112                         new RationalNumber(3, 10));
113             }
114 
115             {
116                 // Example of how to add/update GPS info to output set.
117 
118                 // New York City
119                 final double longitude = -74.0; // 74 degrees W (in Degrees East)
120                 final double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees
121                 // North)
122 
123                 outputSet.setGPSInDegrees(longitude, latitude);
124             }
125 
126             // printTagValue(jpegMetadata, TiffConstants.TIFF_TAG_DATE_TIME);
127 
128             new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
129                     outputSet);
130         }
131     }
132 
133     /**
134      * This example illustrates how to remove a tag (if present) from EXIF
135      * metadata in a JPEG file.
136      * 
137      * In this case, we remove the "aperture" tag from the EXIF metadata if
138      * present.
139      * 
140      * @param jpegImageFile
141      *            A source image file.
142      * @param dst
143      *            The output file.
144      * @throws IOException
145      * @throws ImageReadException
146      * @throws ImageWriteException
147      */
148     public void removeExifTag(final File jpegImageFile, final File dst) throws IOException,
149             ImageReadException, ImageWriteException {
150         try (FileOutputStream fos = new FileOutputStream(dst);
151                 OutputStream os = new BufferedOutputStream(fos)) {
152             TiffOutputSet outputSet = null;
153 
154             // note that metadata might be null if no metadata is found.
155             final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
156             final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
157             if (null != jpegMetadata) {
158                 // note that exif might be null if no Exif metadata is found.
159                 final TiffImageMetadata exif = jpegMetadata.getExif();
160 
161                 if (null != exif) {
162                     // TiffImageMetadata class is immutable (read-only).
163                     // TiffOutputSet class represents the Exif data to write.
164                     //
165                     // Usually, we want to update existing Exif metadata by
166                     // changing
167                     // the values of a few fields, or adding a field.
168                     // In these cases, it is easiest to use getOutputSet() to
169                     // start with a "copy" of the fields read from the image.
170                     outputSet = exif.getOutputSet();
171                 }
172             }
173 
174             if (null == outputSet) {
175                 // file does not contain any exif metadata. We don't need to
176                 // update the file; just copy it.
177                 FileUtils.copyFile(jpegImageFile, dst);
178                 return;
179             }
180 
181             {
182                 // Example of how to remove a single tag/field.
183                 // There are two ways to do this.
184 
185                 // Option 1: brute force
186                 // Note that this approach is crude: Exif data is organized in
187                 // directories. The same tag/field may appear in more than one
188                 // directory, and have different meanings in each.
189                 outputSet.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
190 
191                 // Option 2: precision
192                 // We know the exact directory the tag should appear in, in this
193                 // case the "exif" directory.
194                 // One complicating factor is that in some cases, manufacturers
195                 // will place the same tag in different directories.
196                 // To learn which directory a tag appears in, either refer to
197                 // the constants in ExifTagConstants.java or go to Phil Harvey's
198                 // EXIF website.
199                 final TiffOutputDirectory exifDirectory = outputSet.getExifDirectory();
200                 if (null != exifDirectory) {
201                     exifDirectory.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
202                 }
203             }
204 
205             new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
206                     outputSet);
207         }
208     }
209 
210     /**
211      * This example illustrates how to set the GPS values in JPEG EXIF metadata.
212      * 
213      * @param jpegImageFile
214      *            A source image file.
215      * @param dst
216      *            The output file.
217      * @throws IOException
218      * @throws ImageReadException
219      * @throws ImageWriteException
220      */
221     public void setExifGPSTag(final File jpegImageFile, final File dst) throws IOException,
222             ImageReadException, ImageWriteException {
223         try (FileOutputStream fos = new FileOutputStream(dst);
224                 OutputStream os = new BufferedOutputStream(fos)) {
225             TiffOutputSet outputSet = null;
226 
227             // note that metadata might be null if no metadata is found.
228             final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
229             final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
230             if (null != jpegMetadata) {
231                 // note that exif might be null if no Exif metadata is found.
232                 final TiffImageMetadata exif = jpegMetadata.getExif();
233 
234                 if (null != exif) {
235                     // TiffImageMetadata class is immutable (read-only).
236                     // TiffOutputSet class represents the Exif data to write.
237                     //
238                     // Usually, we want to update existing Exif metadata by
239                     // changing
240                     // the values of a few fields, or adding a field.
241                     // In these cases, it is easiest to use getOutputSet() to
242                     // start with a "copy" of the fields read from the image.
243                     outputSet = exif.getOutputSet();
244                 }
245             }
246 
247             // if file does not contain any exif metadata, we create an empty
248             // set of exif metadata. Otherwise, we keep all of the other
249             // existing tags.
250             if (null == outputSet) {
251                 outputSet = new TiffOutputSet();
252             }
253 
254             {
255                 // Example of how to add/update GPS info to output set.
256 
257                 // New York City
258                 final double longitude = -74.0; // 74 degrees W (in Degrees East)
259                 final double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees
260                 // North)
261 
262                 outputSet.setGPSInDegrees(longitude, latitude);
263             }
264 
265             new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
266                     outputSet);
267         }
268     }
269 
270 }