Apache Commons Imaging 之前是著名的 Apache Commons Sanselan ,用于读写各种图像格式的 Java 类库,包括快速解析图片的基本信息(size, color space, ICC profile等)和元数据。尽管慢点但非常好的可移植性。比起 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 | } |
项目主页:http://www.open-open.com/lib/view/home/1372982998081
转自:http://www.open-open.com/lib/view/open1372982998081.html