Changeset 6127 in josm for trunk/src/com/drew/imaging/jpeg/JpegMetadataReader.java
- Timestamp:
- 2013-08-09T18:05:11+02:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/drew/imaging/jpeg/JpegMetadataReader.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 12-Nov-2002 18:51:36 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.imaging.jpeg; 18 22 19 import com.drew.metadata.Directory; 23 import com.drew.lang.ByteArrayReader; 24 import com.drew.lang.annotations.NotNull; 20 25 import com.drew.metadata.Metadata; 21 import com.drew.metadata.MetadataException;22 import com.drew.metadata.Tag;23 import com.drew.metadata.exif.ExifDirectory;24 26 import com.drew.metadata.exif.ExifReader; 25 27 import com.drew.metadata.iptc.IptcReader; 26 28 import com.drew.metadata.jpeg.JpegCommentReader; 29 import com.drew.metadata.jpeg.JpegDirectory; 27 30 import com.drew.metadata.jpeg.JpegReader; 28 31 … … 30 33 import java.io.IOException; 31 34 import java.io.InputStream; 32 import java.util.Iterator;33 35 34 36 /** 37 * Obtains all available metadata from Jpeg formatted files. 35 38 * 39 * @author Drew Noakes http://drewnoakes.com 36 40 */ 37 41 public class JpegMetadataReader 38 42 { 43 // TODO investigate supporting javax.imageio 39 44 // public static Metadata readMetadata(IIOMetadata metadata) throws JpegProcessingException {} 40 45 // public static Metadata readMetadata(ImageInputStream in) throws JpegProcessingException{} … … 42 47 // public static Metadata readMetadata(ImageReader reader) throws JpegProcessingException{} 43 48 44 public static Metadata readMetadata(InputStream in) throws JpegProcessingException 49 @NotNull 50 public static Metadata readMetadata(@NotNull InputStream inputStream) throws JpegProcessingException 45 51 { 46 JpegSegmentReader segmentReader = new JpegSegmentReader(in); 47 return extractMetadataFromJpegSegmentReader(segmentReader); 52 return readMetadata(inputStream, true); 48 53 } 49 54 50 public static Metadata readMetadata(File file) throws JpegProcessingException 55 @NotNull 56 public static Metadata readMetadata(@NotNull InputStream inputStream, final boolean waitForBytes) throws JpegProcessingException 57 { 58 JpegSegmentReader segmentReader = new JpegSegmentReader(inputStream, waitForBytes); 59 return extractMetadataFromJpegSegmentReader(segmentReader.getSegmentData()); 60 } 61 62 @NotNull 63 public static Metadata readMetadata(@NotNull File file) throws JpegProcessingException, IOException 51 64 { 52 65 JpegSegmentReader segmentReader = new JpegSegmentReader(file); 53 return extractMetadataFromJpegSegmentReader(segmentReader); 66 return extractMetadataFromJpegSegmentReader(segmentReader.getSegmentData()); 54 67 } 55 68 56 public static Metadata extractMetadataFromJpegSegmentReader(JpegSegmentReader segmentReader) 69 @NotNull 70 public static Metadata extractMetadataFromJpegSegmentReader(@NotNull JpegSegmentData segmentReader) 57 71 { 58 72 final Metadata metadata = new Metadata(); 59 try { 60 byte[] exifSegment = segmentReader.readSegment(JpegSegmentReader.SEGMENT_APP1); 61 new ExifReader(exifSegment).extract(metadata); 62 } catch (JpegProcessingException e) { 63 // in the interests of catching as much data as possible, continue 64 // TODO lodge error message within exif directory? 73 74 // Loop through looking for all SOFn segments. When we find one, we know what type of compression 75 // was used for the JPEG, and we can process the JPEG metadata in the segment too. 76 for (byte i = 0; i < 16; i++) { 77 // There are no SOF4 or SOF12 segments, so don't bother 78 if (i == 4 || i == 12) 79 continue; 80 // Should never have more than one SOFn for a given 'n'. 81 byte[] jpegSegment = segmentReader.getSegment((byte)(JpegSegmentReader.SEGMENT_SOF0 + i)); 82 if (jpegSegment == null) 83 continue; 84 JpegDirectory directory = metadata.getOrCreateDirectory(JpegDirectory.class); 85 directory.setInt(JpegDirectory.TAG_JPEG_COMPRESSION_TYPE, i); 86 new JpegReader().extract(new ByteArrayReader(jpegSegment), metadata); 87 break; 65 88 } 66 89 67 try { 68 byte[] iptcSegment = segmentReader.readSegment(JpegSegmentReader.SEGMENT_APPD); 69 new IptcReader(iptcSegment).extract(metadata); 70 } catch (JpegProcessingException e) { 71 // TODO lodge error message within iptc directory? 90 // There should never be more than one COM segment. 91 byte[] comSegment = segmentReader.getSegment(JpegSegmentReader.SEGMENT_COM); 92 if (comSegment != null) 93 new JpegCommentReader().extract(new ByteArrayReader(comSegment), metadata); 94 95 // Loop through all APP1 segments, checking the leading bytes to identify the format of each. 96 for (byte[] app1Segment : segmentReader.getSegments(JpegSegmentReader.SEGMENT_APP1)) { 97 if (app1Segment.length > 3 && "EXIF".equalsIgnoreCase(new String(app1Segment, 0, 4))) 98 new ExifReader().extract(new ByteArrayReader(app1Segment), metadata); 99 100 //if (app1Segment.length > 27 && "http://ns.adobe.com/xap/1.0/".equalsIgnoreCase(new String(app1Segment, 0, 28))) 101 // new XmpReader().extract(new ByteArrayReader(app1Segment), metadata); 72 102 } 73 103 74 try { 75 byte[] jpegSegment = segmentReader.readSegment(JpegSegmentReader.SEGMENT_SOF0); 76 new JpegReader(jpegSegment).extract(metadata); 77 } catch (JpegProcessingException e) { 78 // TODO lodge error message within jpeg directory? 79 } 80 81 try { 82 byte[] jpegCommentSegment = segmentReader.readSegment(JpegSegmentReader.SEGMENT_COM); 83 new JpegCommentReader(jpegCommentSegment).extract(metadata); 84 } catch (JpegProcessingException e) { 85 // TODO lodge error message within jpegcomment directory? 86 } 104 // Loop through all APPD segments, checking the leading bytes to identify the format of each. 105 for (byte[] appdSegment : segmentReader.getSegments(JpegSegmentReader.SEGMENT_APPD)) { 106 if (appdSegment.length > 12 && "Photoshop 3.0".compareTo(new String(appdSegment, 0, 13))==0) { 107 //new PhotoshopReader().extract(new ByteArrayReader(appdSegment), metadata); 108 } else { 109 // TODO might be able to check for a leading 0x1c02 for IPTC data... 110 new IptcReader().extract(new ByteArrayReader(appdSegment), metadata); 111 } 112 } 87 113 88 114 return metadata; 89 115 } 90 116 91 private JpegMetadataReader() 117 private JpegMetadataReader() throws Exception 92 118 { 93 } 94 95 public static void main(String[] args) throws MetadataException, IOException 96 { 97 Metadata metadata = null; 98 try { 99 metadata = JpegMetadataReader.readMetadata(new File(args[0])); 100 } catch (Exception e) { 101 e.printStackTrace(System.err); 102 System.exit(1); 103 } 104 105 // iterate over the exif data and print to System.out 106 Iterator directories = metadata.getDirectoryIterator(); 107 while (directories.hasNext()) { 108 Directory directory = (Directory)directories.next(); 109 Iterator tags = directory.getTagIterator(); 110 while (tags.hasNext()) { 111 Tag tag = (Tag)tags.next(); 112 try { 113 System.out.println("[" + directory.getName() + "] " + tag.getTagName() + " = " + tag.getDescription()); 114 } catch (MetadataException e) { 115 System.err.println(e.getMessage()); 116 System.err.println(tag.getDirectoryName() + " " + tag.getTagName() + " (error)"); 117 } 118 } 119 if (directory.hasErrors()) { 120 Iterator errors = directory.getErrors(); 121 while (errors.hasNext()) { 122 System.out.println("ERROR: " + errors.next()); 123 } 124 } 125 } 126 127 if (args.length>1 && args[1].trim().equals("/thumb")) 128 { 129 ExifDirectory directory = (ExifDirectory)metadata.getDirectory(ExifDirectory.class); 130 if (directory.containsThumbnail()) 131 { 132 System.out.println("Writing thumbnail..."); 133 directory.writeThumbnail(args[0].trim() + ".thumb.jpg"); 134 } 135 else 136 { 137 System.out.println("No thumbnail data exists in this image"); 138 } 139 } 119 throw new Exception("Not intended for instantiation"); 140 120 } 141 121 } 122
Note:
See TracChangeset
for help on using the changeset viewer.
