Changeset 8132 in josm for trunk/src/com/drew/imaging/jpeg/JpegMetadataReader.java
- Timestamp:
- 2015-03-10T01:17:39+01:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/com/drew/imaging/jpeg/JpegMetadataReader.java ¶
r6127 r8132 1 1 /* 2 * Copyright 2002-201 2Drew Noakes2 * Copyright 2002-2015 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 16 16 * More information about this project is available at: 17 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http ://code.google.com/p/metadata-extractor/18 * https://drewnoakes.com/code/exif/ 19 * https://github.com/drewnoakes/metadata-extractor 20 20 */ 21 21 package com.drew.imaging.jpeg; 22 22 23 import com.drew.lang.ByteArrayReader;24 import com.drew.lang.annotations.NotNull;25 import com.drew.metadata.Metadata;26 import com.drew.metadata.exif.ExifReader;27 import com.drew.metadata.iptc.IptcReader;28 import com.drew.metadata.jpeg.JpegCommentReader;29 import com.drew.metadata.jpeg.JpegDirectory;30 import com.drew.metadata.jpeg.JpegReader;31 32 23 import java.io.File; 24 import java.io.FileInputStream; 33 25 import java.io.IOException; 34 26 import java.io.InputStream; 27 import java.util.Arrays; 28 import java.util.HashSet; 29 import java.util.Set; 30 31 import com.drew.lang.StreamReader; 32 import com.drew.lang.annotations.NotNull; 33 import com.drew.lang.annotations.Nullable; 34 import com.drew.metadata.Metadata; 35 //import com.drew.metadata.adobe.AdobeJpegReader; 36 import com.drew.metadata.exif.ExifReader; 37 //import com.drew.metadata.icc.IccReader; 38 import com.drew.metadata.iptc.IptcReader; 39 //import com.drew.metadata.jfif.JfifReader; 40 import com.drew.metadata.jpeg.JpegCommentReader; 41 import com.drew.metadata.jpeg.JpegReader; 42 //import com.drew.metadata.photoshop.PhotoshopReader; 43 //import com.drew.metadata.xmp.XmpReader; 35 44 36 45 /** 37 * Obtains all available metadata from J pegformatted files.46 * Obtains all available metadata from JPEG formatted files. 38 47 * 39 * @author Drew Noakes http://drewnoakes.com 48 * @author Drew Noakes https://drewnoakes.com 40 49 */ 41 50 public class JpegMetadataReader 42 51 { 43 // TODO investigate supporting javax.imageio 44 // public static Metadata readMetadata(IIOMetadata metadata) throws JpegProcessingException {} 45 // public static Metadata readMetadata(ImageInputStream in) throws JpegProcessingException{} 46 // public static Metadata readMetadata(IIOImage image) throws JpegProcessingException{} 47 // public static Metadata readMetadata(ImageReader reader) throws JpegProcessingException{} 52 public static final Iterable<JpegSegmentMetadataReader> ALL_READERS = Arrays.asList( 53 new JpegReader(), 54 new JpegCommentReader(), 55 //new JfifReader(), 56 new ExifReader(), 57 //new XmpReader(), 58 //new IccReader(), 59 //new PhotoshopReader(), 60 new IptcReader()//, 61 //new AdobeJpegReader() 62 ); 48 63 49 64 @NotNull 50 public static Metadata readMetadata(@NotNull InputStream inputStream) throws JpegProcessingException 65 public static Metadata readMetadata(@NotNull InputStream inputStream, @Nullable Iterable<JpegSegmentMetadataReader> readers) throws JpegProcessingException, IOException 51 66 { 52 return readMetadata(inputStream, true); 67 Metadata metadata = new Metadata(); 68 process(metadata, inputStream, readers); 69 return metadata; 53 70 } 54 71 55 72 @NotNull 56 public static Metadata readMetadata(@NotNull InputStream inputStream , final boolean waitForBytes) throws JpegProcessingException73 public static Metadata readMetadata(@NotNull InputStream inputStream) throws JpegProcessingException, IOException 57 74 { 58 JpegSegmentReader segmentReader = new JpegSegmentReader(inputStream, waitForBytes); 59 return extractMetadataFromJpegSegmentReader(segmentReader.getSegmentData()); 75 return readMetadata(inputStream, null); 76 } 77 78 @NotNull 79 public static Metadata readMetadata(@NotNull File file, @Nullable Iterable<JpegSegmentMetadataReader> readers) throws JpegProcessingException, IOException 80 { 81 InputStream inputStream = null; 82 try 83 { 84 inputStream = new FileInputStream(file); 85 return readMetadata(inputStream, readers); 86 } finally { 87 if (inputStream != null) 88 inputStream.close(); 89 } 60 90 } 61 91 … … 63 93 public static Metadata readMetadata(@NotNull File file) throws JpegProcessingException, IOException 64 94 { 65 JpegSegmentReader segmentReader = new JpegSegmentReader(file); 66 return extractMetadataFromJpegSegmentReader(segmentReader.getSegmentData()); 95 return readMetadata(file, null); 67 96 } 68 97 69 @NotNull 70 public static Metadata extractMetadataFromJpegSegmentReader(@NotNull JpegSegmentData segmentReader) 98 public static void process(@NotNull Metadata metadata, @NotNull InputStream inputStream) throws JpegProcessingException, IOException 71 99 { 72 final Metadata metadata = new Metadata(); 100 process(metadata, inputStream, null); 101 } 73 102 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; 88 } 103 public static void process(@NotNull Metadata metadata, @NotNull InputStream inputStream, @Nullable Iterable<JpegSegmentMetadataReader> readers) throws JpegProcessingException, IOException 104 { 105 if (readers == null) 106 readers = ALL_READERS; 89 107 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); 102 } 103 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); 108 Set<JpegSegmentType> segmentTypes = new HashSet<JpegSegmentType>(); 109 for (JpegSegmentMetadataReader reader : readers) { 110 for (JpegSegmentType type : reader.getSegmentTypes()) { 111 segmentTypes.add(type); 111 112 } 112 113 } 113 114 114 return metadata; 115 JpegSegmentData segmentData = JpegSegmentReader.readSegments(new StreamReader(inputStream), segmentTypes); 116 117 processJpegSegmentData(metadata, readers, segmentData); 118 } 119 120 public static void processJpegSegmentData(Metadata metadata, Iterable<JpegSegmentMetadataReader> readers, JpegSegmentData segmentData) 121 { 122 // Pass the appropriate byte arrays to each reader. 123 for (JpegSegmentMetadataReader reader : readers) { 124 for (JpegSegmentType segmentType : reader.getSegmentTypes()) { 125 for (byte[] segmentBytes : segmentData.getSegments(segmentType)) { 126 if (reader.canProcess(segmentBytes, segmentType)) { 127 reader.extract(segmentBytes, metadata, segmentType); 128 } 129 } 130 } 131 } 115 132 } 116 133 … … 120 137 } 121 138 } 122
Note:
See TracChangeset
for help on using the changeset viewer.