/// <summary> /// Extracts aMetadata /// </summary> /// <param name="aMetadata">where to add aMetadata</param> /// <returns>the aMetadata found</returns> public override Metadata Extract(Metadata aMetadata) { if (base.data == null) { return aMetadata; } AbstractDirectory lcDirectory = aMetadata.GetDirectory("com.drew.metadata.jpeg.JpegCommentDirectory"); string comment = Utils.Decode(base.data, true); lcDirectory.SetObject(JpegCommentDirectory.TAG_JPEG_COMMENT,comment); return aMetadata; }
/// <summary> /// Extracts aMetadata from a SegmentReader /// </summary> /// <param name="aSegmentReader">where to extract aMetadata</param> /// <returns>the aMetadata found</returns> private static Metadata ExtractJpegSegmentReaderMetadata(JpegSegmentReader aSegmentReader) { Metadata lcMetadata = new Metadata(); try { byte[] lcExifSegment = aSegmentReader.ReadSegment(JpegSegmentReader.SEGMENT_APP1); new ExifReader(lcExifSegment).Extract(lcMetadata); } catch (Exception e) { Trace.TraceWarning("Error in reading Exif segment ("+e.Message+")"); // in the interests of catching as much data as possible, continue } try { byte[] lcIptcSegment = aSegmentReader.ReadSegment(JpegSegmentReader.SEGMENT_APPD); new IptcReader(lcIptcSegment).Extract(lcMetadata); } catch (Exception e) { Trace.TraceWarning("Error in reading Iptc segment (" + e.Message + ")"); } try { byte[] lcJpegSegment = aSegmentReader.ReadSegment(JpegSegmentReader.SEGMENT_SOF0); new JpegReader(lcJpegSegment).Extract(lcMetadata); } catch (Exception e) { Trace.TraceWarning("Error in reading Jpeg segment (" + e.Message + ")"); } try { byte[] lcJpegCommentSegment = aSegmentReader.ReadSegment(JpegSegmentReader.SEGMENT_COM); new JpegCommentReader(lcJpegCommentSegment).Extract(lcMetadata); } catch (Exception e) { Trace.TraceWarning("Error in reading Jpeg Comment segment (" + e.Message + ")"); } return lcMetadata; }
/// <summary> /// Constructor of the object. /// </summary> /// <param name="aStream">Where to read information from. Caution, you are responsible for closing this stream.</param> /// <returns>a meta data object</returns> public static Metadata ReadMetadata(Stream aStream) { Metadata metadata = new Metadata(); try { byte[] buffer = new byte[(int)aStream.Length]; aStream.Read(buffer, 0, buffer.Length); new ExifReader(buffer).ExtractTiff(metadata); } catch (MetadataException e) { throw new TiffProcessingException(e); } return metadata; }
/// <summary> /// Constructor of the object. /// </summary> /// <param name="aMetadata">the metadata that shoud be transformed into XML</param> public XmlOutPutStreamHandler(Metadata aMetadata) : base() { this.Metadata = aMetadata; this.DtdFileName = "MetadataExtractor.dtd"; }
/// <summary> /// Constructor of the object. /// </summary> /// <param name="aMetadata">the metadata that shoud be transformed into txt</param> public TxtOutPutStreamHandler(Metadata aMetadata) : base() { this.Metadata = aMetadata; }
/// <summary> /// Extracts aMetadata /// </summary> /// <param name="aMetadata">where to add aMetadata</param> /// <returns>the aMetadata found</returns> public override Metadata Extract(Metadata aMetadata) { if (base.data == null) { return aMetadata; } AbstractDirectory lcDirectory = aMetadata.GetDirectory("com.drew.metadata.jpeg.JpegDirectory"); try { // data precision int dataPrecision = base.Get16Bits(JpegDirectory.TAG_JPEG_DATA_PRECISION); lcDirectory.SetObject( JpegDirectory.TAG_JPEG_DATA_PRECISION, dataPrecision); // process height int height = base.Get32Bits(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT); lcDirectory.SetObject(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT, height); // process width int width = base.Get32Bits(JpegDirectory.TAG_JPEG_IMAGE_WIDTH); lcDirectory.SetObject(JpegDirectory.TAG_JPEG_IMAGE_WIDTH, width); // number of components int numberOfComponents = base.Get16Bits(JpegDirectory.TAG_JPEG_NUMBER_OF_COMPONENTS); lcDirectory.SetObject( JpegDirectory.TAG_JPEG_NUMBER_OF_COMPONENTS, numberOfComponents); // for each component, there are three bytes of data: // 1 - Component ID: 1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q // 2 - Sampling factors: bit 0-3 vertical, 4-7 horizontal // 3 - Quantization table number int offset = 6; for (int i = 0; i < numberOfComponents; i++) { int componentId = base.Get16Bits(offset++); int samplingFactorByte = base.Get16Bits(offset++); int quantizationTableNumber = base.Get16Bits(offset++); JpegComponent lcJpegComponent = new JpegComponent( componentId, samplingFactorByte, quantizationTableNumber); lcDirectory.SetObject( JpegDirectory.TAG_JPEG_COMPONENT_DATA_1 + i, lcJpegComponent); } } catch (MetadataException me) { lcDirectory.HasError = true; Trace.TraceError("MetadataException: " + me.Message); } return aMetadata; }
/// <summary> /// Extracts aMetadata /// </summary> /// <param name="aMetadata">where to add aMetadata</param> /// <returns>the aMetadata found</returns> public abstract Metadata Extract(Metadata metadata);
/// <summary> /// Extracts aMetadata /// </summary> /// <param name="aMetadata">where to add aMetadata</param> /// <returns>the aMetadata found</returns> public override Metadata Extract(Metadata aMetadata) { if (base.data == null) { return aMetadata; } AbstractDirectory lcDirectory = aMetadata.GetDirectory("com.drew.metadata.iptc.IptcDirectory"); // find start of data int offset = 0; try { while (offset < base.data.Length - 1 && Get32Bits(offset) != 0x1c02) { offset++; } } catch (MetadataException e) { lcDirectory.HasError = true; Trace.TraceError( "Couldn't find start of Iptc data (invalid segment) ("+e.Message+")"); return aMetadata; } // for each tag while (offset < base.data.Length) { // identifies start of a tag if (base.data[offset] != 0x1c) { break; } // we need at least five bytes left to read a tag if ((offset + 5) >= base.data.Length) { break; } offset++; int directoryType; int tagType; int tagByteCount; try { directoryType = base.data[offset++]; tagType = base.data[offset++]; tagByteCount = Get32Bits(offset); } catch (MetadataException e) { lcDirectory.HasError = true; Trace.TraceError( "Iptc data segment ended mid-way through tag descriptor ("+e.Message+")"); return aMetadata; } offset += 2; if ((offset + tagByteCount) > base.data.Length) { lcDirectory.HasError = true; Trace.TraceError( "Data for tag extends beyond end of IPTC segment"); break; } ProcessTag(lcDirectory, directoryType, tagType, offset, tagByteCount); offset += tagByteCount; } return aMetadata; }
/// <summary> /// Constructor of the object. /// </summary> /// <param name="aMetadata">the metadata that shoud be transformed into XML</param> public XmlNewOutPutStreamHandler(Metadata aMetadata) : base() { this.Metadata = aMetadata; this.DtdFileName = "MetadataExtractorNew.dtd"; XmlNewOutPutStreamHandler.FORBIDEN_CHAR = XmlNewOutPutStreamHandler.BuildForbidenChar(); }
/// <summary> /// Reads metatdata from raw file. /// </summary> /// <param name="aMetadata">a meta data</param> /// <param name="aTiffHeaderOffset">an offset</param> /// <returns>the metadata found</returns> private Metadata ExtractIFD(Metadata aMetadata, int aTiffHeaderOffset) { this.metadata = aMetadata; if (base.data == null) { return this.metadata; } ExifDirectory directory = this.ExifDirectory; // this should be either "MM" or "II" string byteOrderIdentifier = Utils.Decode(base.data, aTiffHeaderOffset, 2, false); if (!this.SetByteOrder(byteOrderIdentifier)) { directory.HasError = true; Trace.TraceError("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier); return this.metadata; } // Check the next two values for correctness. if (this.Get16Bits(2 + aTiffHeaderOffset) != 0x2a) { // directory.AddError("Invalid Exif start - should have 0x2A at offset 8 in Exif header"); // return this.metadata; } int firstDirectoryOffset = this.Get32Bits(4 + aTiffHeaderOffset) + aTiffHeaderOffset; // David Ekholm sent an digital camera image that has this problem if (firstDirectoryOffset >= base.data.Length - 1) { directory.HasError = true; Trace.TraceError("First exif directory offset is beyond end of Exif data segment"); // First directory normally starts 14 bytes in -- try it here and catch another error in the worst case firstDirectoryOffset = 14; } IDictionary<int, string> processedDirectoryOffsets = new Dictionary<int, string>(); // 0th IFD (we merge with Exif IFD) try { this.ProcessDirectory(directory, processedDirectoryOffsets, firstDirectoryOffset, aTiffHeaderOffset); } catch (Exception e) { throw new MetadataException(e); } // after the extraction process, if we have the correct tags, we may be able to store thumbnail information this.StoreThumbnailBytes(directory, aTiffHeaderOffset); return this.metadata; }
/// <summary> /// Extract tiff information (used by raw files) /// </summary> /// <param name="aMetadata">where to extract information</param> /// <returns>the information extracted</returns> public Metadata ExtractTiff(Metadata aMetadata) { return this.ExtractIFD(aMetadata, 0); }
/// <summary> /// Performs the Exif data extraction, adding found values to the specified instance of Metadata. /// </summary> /// <param name="aMetadata">where to add meta data</param> /// <returns>the aMetadata</returns> public override Metadata Extract(Metadata metadata) { this.metadata = metadata; if (base.data == null) { return this.metadata; } // once we know there'str some data, create the directory and start working on it AbstractDirectory directory = this.metadata.GetDirectory("com.drew.metadata.exif.ExifDirectory"); if (base.data.Length <= 14) { directory.HasError = true; Trace.TraceError("Exif data segment must contain at least 14 bytes"); return this.metadata; } if (!"Exif\0\0".Equals(Utils.Decode(base.data, 0, 6, false))) { directory.HasError = true; Trace.TraceError("Exif data segment doesn't begin with 'Exif'"); return this.metadata; } // this should be either "MM" or "II" string byteOrderIdentifier = Utils.Decode(base.data, 6, 2, false); if (!SetByteOrder(byteOrderIdentifier)) { directory.HasError = true; Trace.TraceError("Unclear distinction between Motorola/Intel byte ordering"); return this.metadata; } // Check the next two values for correctness. if (Get16Bits(8) != 0x2a) { directory.HasError = true; Trace.TraceError("Invalid Exif start - should have 0x2A at offSet 8 in Exif header"); return this.metadata; } int firstDirectoryOffSet = Get32Bits(10) + TIFF_HEADER_START_OFFSET; // David Ekholm sent an digital camera image that has this problem if (firstDirectoryOffSet >= base.data.Length - 1) { directory.HasError = true; Trace.TraceError("First exif directory offSet is beyond end of Exif data segment"); // First directory normally starts 14 bytes in -- try it here and catch another error in the worst case firstDirectoryOffSet = 14; } // 0th IFD (we merge with Exif IFD) //ProcessDirectory(directory, firstDirectoryOffSet); // after the extraction process, if we have the correct tags, we may be able to extract thumbnail information //ExtractThumbnail(directory); Dictionary<int, string> processedDirectoryOffsets = new Dictionary<int, string>(); // 0th IFD (we merge with Exif IFD) ProcessDirectory(directory, processedDirectoryOffsets, firstDirectoryOffSet, TIFF_HEADER_START_OFFSET); // after the extraction process, if we have the correct tags, we may be able to store thumbnail information StoreThumbnailBytes(directory, TIFF_HEADER_START_OFFSET); return this.metadata; }
/// <summary> /// Reads aMetadata from a JPEGDecodeParam object /// </summary> /// <param name="aDecodeParam">where to find aMetadata</param> /// <returns>the aMetadata found</returns> public static Metadata ReadMetadata(JPEGDecodeParam aDecodeParam) { Metadata lcMetadata = new Metadata(); // We should only really be seeing Exif in _data[0]... the 2D array exists // because markers can theoretically appear multiple times in the aFile. // TODO test this method byte[][] lcExifSegment = aDecodeParam.GetMarkerData(JPEGDecodeParam.APP1_MARKER); if (lcExifSegment != null && lcExifSegment[0].Length > 0) { new ExifReader(lcExifSegment[0]).Extract(lcMetadata); } // similarly, use only the first IPTC segment byte[][] lcIptcSegment = aDecodeParam.GetMarkerData(JPEGDecodeParam.APPD_MARKER); if (lcIptcSegment != null && lcIptcSegment[0].Length > 0) { new IptcReader(lcIptcSegment[0]).Extract(lcMetadata); } // NOTE: Unable to utilise JpegReader for the SOF0 frame here, as the aDecodeParam doesn't contain the byte[] // similarly, use only the first Jpeg Comment segment byte[][] lcJpegCommentSegment = aDecodeParam.GetMarkerData(JPEGDecodeParam.COMMENT_MARKER); if (lcJpegCommentSegment != null && lcJpegCommentSegment[0].Length > 0) { new JpegCommentReader(lcJpegCommentSegment[0]).Extract(lcMetadata); } return lcMetadata; }