Commons Imaging 读取图像EXIF信息。Apache Commons Imaging 前身是 Apache Commons Sanselan ,这是一个用来读写各种图像格式的 Java 类库,包括快速解析图片的基本信息(大小、色彩空间、ICC配置等)和元数据。尽管慢点但非常好的可移植性。比起 ImageIO/JAI/Toolkit 更容易使用,支持更多的格式,提供简单访问元数据的方法。javadoc
读取图像EXIF信息的示例代码:
001
package org.apache.commons.imaging.examples;
002
003
import java.io.BufferedOutputStream;
004
import java.io.File;
005
import java.io.FileOutputStream;
006
import java.io.IOException;
007
import java.io.OutputStream;
008
009
import org.apache.commons.imaging.ImageReadException;
010
import org.apache.commons.imaging.ImageWriteException;
011
import org.apache.commons.imaging.Imaging;
012
import org.apache.commons.imaging.common.IImageMetadata;
013
import org.apache.commons.imaging.common.RationalNumber;
014
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
015
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
016
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
017
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
018
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
019
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
020
import org.apache.commons.imaging.util.IoUtils;
021
022
public class WriteExifMetadataExample {
023
public void removeExifMetadata(final File jpegImageFile, final File dst)
024
throws IOException, ImageReadException, ImageWriteException {
025
OutputStream os = null;
026
try {
027
os = new FileOutputStream(dst);
028
os = new BufferedOutputStream(os);
029
030
new ExifRewriter().removeExifMetadata(jpegImageFile, os);
031
} finally {
032
if (os != null) {
033
try {
034
os.close();
035
} catch (final IOException e) {
036
037
}
038
}
039
}
040
}
041
042
/**
043
* This example illustrates how to add/update EXIF metadata in a JPEG file.
044
*
045
* @param jpegImageFile
046
* A source image file.
047
* @param dst
048
* The output file.
049
* @throws IOException
050
* @throws ImageReadException
051
* @throws ImageWriteException
052
*/
053
public void changeExifMetadata(final File jpegImageFile, final File dst)
054
throws IOException, ImageReadException, ImageWriteException {
055
OutputStream os = null;
056
try {
057
TiffOutputSet outputSet = null;
058
059
// note that metadata might be null if no metadata is found.
060
final IImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
061
final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
062
if (null != jpegMetadata) {
063
// note that exif might be null if no Exif metadata is found.
064
final TiffImageMetadata exif = jpegMetadata.getExif();
065
066
if (null != exif) {
067
// TiffImageMetadata class is immutable (read-only).
068
// TiffOutputSet class represents the Exif data to write.
069
//
070
// Usually, we want to update existing Exif metadata by
071
// changing
072
// the values of a few fields, or adding a field.
073
// In these cases, it is easiest to use getOutputSet() to
074
// start with a “copy” of the fields read from the image.
075
outputSet = exif.getOutputSet();
076
}
077
}
078
079
// if file does not contain any exif metadata, we create an empty
080
// set of exif metadata. Otherwise, we keep all of the other
081
// existing tags.
082
if (null == outputSet) {
083
outputSet = new TiffOutputSet();
084
}
085
086
{
087
// Example of how to add a field/tag to the output set.
088
//
089
// Note that you should first remove the field/tag if it already
090
// exists in this directory, or you may end up with duplicate
091
// tags. See above.
092
//
093
// Certain fields/tags are expected in certain Exif directories;
094
// Others can occur in more than one directory (and often have a
095
// different meaning in different directories).
096
//
097
// TagInfo constants often contain a description of what
098
// directories are associated with a given tag.
099
//
100
// see
101
// org.apache.commons.sanselan.formats.tiff.constants.AllTagConstants
102
//
103
final TiffOutputDirectory exifDirectory = outputSet
104
.getOrCreateExifDirectory();
105
// make sure to remove old value if present (this method will
106
// not fail if the tag does not exist).
107
exifDirectory
108
.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
109
exifDirectory.add(ExifTagConstants.EXIF_TAG_APERTURE_VALUE,
110
RationalNumber.factoryMethod(3, 10));
111
}
112
113
{
114
// Example of how to add/update GPS info to output set.
115
116
// New York City
117
final double longitude = -74.0; // 74 degrees W (in Degrees East)
118
final double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees
119
// North)
120
121
outputSet.setGPSInDegrees(longitude, latitude);
122
}
123
124
// printTagValue(jpegMetadata, TiffConstants.TIFF_TAG_DATE_TIME);
125
126
os = new FileOutputStream(dst);
127
os = new BufferedOutputStream(os);
128
129
new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
130
outputSet);
131
132
os.close();
133
os = null;
134
} finally {
135
if (os != null) {
136
try {
137
os.close();
138
} catch (final IOException e) {
139
140
}
141
}
142
}
143
}
144
145
/**
146
* This example illustrates how to remove a tag (if present) from EXIF
147
* metadata in a JPEG file.
148
*
149
* In this case, we remove the “aperture” tag from the EXIF metadata if
150
* present.
151
*
152
* @param jpegImageFile
153
* A source image file.
154
* @param dst
155
* The output file.
156
* @throws IOException
157
* @throws ImageReadException
158
* @throws ImageWriteException
159
*/
160
public void removeExifTag(final File jpegImageFile, final File dst) throws IOException,
161
ImageReadException, ImageWriteException {
162
OutputStream os = null;
163
try {
164
TiffOutputSet outputSet = null;
165
166
// note that metadata might be null if no metadata is found.
167
final IImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
168
final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
169
if (null != jpegMetadata) {
170
// note that exif might be null if no Exif metadata is found.
171
final TiffImageMetadata exif = jpegMetadata.getExif();
172
173
if (null != exif) {
174
// TiffImageMetadata class is immutable (read-only).
175
// TiffOutputSet class represents the Exif data to write.
176
//
177
// Usually, we want to update existing Exif metadata by
178
// changing
179
// the values of a few fields, or adding a field.
180
// In these cases, it is easiest to use getOutputSet() to
181
// start with a “copy” of the fields read from the image.
182
outputSet = exif.getOutputSet();
183
}
184
}
185
186
if (null == outputSet) {
187
// file does not contain any exif metadata. We don’t need to
188
// update the file; just copy it.
189
IoUtils.copyFileNio(jpegImageFile, dst);
190
return;
191
}
192
193
{
194
// Example of how to remove a single tag/field.
195
// There are two ways to do this.
196
197
// Option 1: brute force
198
// Note that this approach is crude: Exif data is organized in
199
// directories. The same tag/field may appear in more than one
200
// directory, and have different meanings in each.
201
outputSet.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
202
203
// Option 2: precision
204
// We know the exact directory the tag should appear in, in this
205
// case the “exif” directory.
206
// One complicating factor is that in some cases, manufacturers
207
// will place the same tag in different directories.
208
// To learn which directory a tag appears in, either refer to
209
// the constants in ExifTagConstants.java or go to Phil Harvey’s
210
// EXIF website.
211
final TiffOutputDirectory exifDirectory = outputSet
212
.getExifDirectory();
213
if (null != exifDirectory) {
214
exifDirectory
215
.removeField(ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
216
}
217
}
218
219
os = new FileOutputStream(dst);
220
os = new BufferedOutputStream(os);
221
222
new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
223
outputSet);
224
225
os.close();
226
os = null;
227
} finally {
228
if (os != null) {
229
try {
230
os.close();
231
} catch (final IOException e) {
232
233
}
234
}
235
}
236
}
237
238
/**
239
* This example illustrates how to set the GPS values in JPEG EXIF metadata.
240
*
241
* @param jpegImageFile
242
* A source image file.
243
* @param dst
244
* The output file.
245
* @throws IOException
246
* @throws ImageReadException
247
* @throws ImageWriteException
248
*/
249
public void setExifGPSTag(final File jpegImageFile, final File dst) throws IOException,
250
ImageReadException, ImageWriteException {
251
OutputStream os = null;
252
try {
253
TiffOutputSet outputSet = null;
254
255
// note that metadata might be null if no metadata is found.
256
final IImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
257
final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
258
if (null != jpegMetadata) {
259
// note that exif might be null if no Exif metadata is found.
260
final TiffImageMetadata exif = jpegMetadata.getExif();
261
262
if (null != exif) {
263
// TiffImageMetadata class is immutable (read-only).
264
// TiffOutputSet class represents the Exif data to write.
265
//
266
// Usually, we want to update existing Exif metadata by
267
// changing
268
// the values of a few fields, or adding a field.
269
// In these cases, it is easiest to use getOutputSet() to
270
// start with a “copy” of the fields read from the image.
271
outputSet = exif.getOutputSet();
272
}
273
}
274
275
// if file does not contain any exif metadata, we create an empty
276
// set of exif metadata. Otherwise, we keep all of the other
277
// existing tags.
278
if (null == outputSet) {
279
outputSet = new TiffOutputSet();
280
}
281
282
{
283
// Example of how to add/update GPS info to output set.
284
285
// New York City
286
final double longitude = -74.0; // 74 degrees W (in Degrees East)
287
final double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees
288
// North)
289
290
outputSet.setGPSInDegrees(longitude, latitude);
291
}
292
293
os = new FileOutputStream(dst);
294
os = new BufferedOutputStream(os);
295
296
new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
297
outputSet);
298
299
os.close();
300
os = null;
301
} finally {
302
if (os != null) {
303
try {
304
os.close();
305
} catch (final IOException e) {
306
307
}
308
}
309
}
310
}
311
312
}