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