/// <summary> /// Will stock the thumbnail into exif directory if available. /// </summary> /// <param name="exifDirectory">where to stock the thumbnail</param> /// <param name="tiffHeaderOffset">the tiff lcHeader lcOffset value</param> private void StoreThumbnailBytes(AbstractDirectory exifDirectory, int tiffHeaderOffset) { if (!exifDirectory.ContainsTag(ExifDirectory.TAG_COMPRESSION)) { return; } if (!exifDirectory.ContainsTag(ExifDirectory.TAG_THUMBNAIL_LENGTH) || !exifDirectory.ContainsTag(ExifDirectory.TAG_THUMBNAIL_OFFSET)) { return; } try { int offset = exifDirectory.GetInt(ExifDirectory.TAG_THUMBNAIL_OFFSET); int length = exifDirectory.GetInt(ExifDirectory.TAG_THUMBNAIL_LENGTH); byte[] result = new byte[length]; for (int i = 0; i < result.Length; i++) { result[i] = base.data[tiffHeaderOffset + offset + i]; } exifDirectory.SetObject(ExifDirectory.TAG_THUMBNAIL_DATA, result); } catch (Exception e) { exifDirectory.HasError = true; Trace.TraceError("Unable to extract thumbnail: " + e.Message); } }
public override void visit(AbstractDirectory dir) { //++depth; var nextDir = dir as Directory.Directory; if (nextDir != null) { ++depth; Retreat(depth); Console.WriteLine(nextDir.Name); Retreat(depth); Console.WriteLine("{"); //++depth; Retreat(depth); foreach (var abstractDirectory in nextDir.ChildrenList) { abstractDirectory.accept(this); } --depth; Console.WriteLine("}"); } else { Retreat(depth + 1); Console.WriteLine(dir); } Retreat(depth); }
public File(FileData file, AbstractDirectory parent) { Parent = parent; NewName = file.Name; Name = file.Name; Title = file.Name; Size = file.Length; Updated = file.Updated; Created = file.Created; }
/// <summary> /// Creates a directory tag. /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { aBuff.Append("--| ").Append(aDirectory.GetName()).Append(" |--"); aBuff.AppendLine(); foreach (Tag lcTag in aDirectory) { CreateTag(aBuff, lcTag); } } }
/// <summary> /// Creates a directory tag. /// /// Examples : /// <pre> /// <directory name="Exif"> /// <tag> /// ... /// </tag> /// <tag> /// ... /// </tag> /// </directory> /// </pre> /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { this.Open(aBuff, "directory", "name", aDirectory.GetName(), "class", aDirectory.GetType(), true); foreach (Tag lcTag in aDirectory) { this.CreateTag(aBuff, lcTag); } this.Close(aBuff, "directory", true); } }
/// <summary> /// Creates a directory tag. /// /// Examples : /// <pre> /// <directory name="Exif"> /// <tag> /// ... /// </tag> /// <tag> /// ... /// </tag> /// </directory> /// </pre> /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { Open(aBuff, "directory name=\"" + aDirectory.GetName() + "\"", true); foreach (Tag lcTag in aDirectory) { CreateTag(aBuff, lcTag); } Close(aBuff, "directory", true); } }
/// <summary> /// Creates a directory tag. /// /// Examples : /// <pre> /// <directory name="Exif"> /// <tag> /// ... /// </tag> /// <tag> /// ... /// </tag> /// </directory> /// </pre> /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { this.Open(aBuff, "directory", "name", aDirectory.GetName(), "class", aDirectory.GetType(), true); IEnumerator <Tag> lcTagsEnum = aDirectory.GetTagIterator(); while (lcTagsEnum.MoveNext()) { this.CreateTag(aBuff, lcTagsEnum.Current); } this.Close(aBuff, "directory", true); } }
/// <summary> /// Transform the metatdat object into an XML stream. /// </summary> /// <returns>The metadata object as XML stream</returns> public virtual string AsText() { StringBuilder lcBuff = new StringBuilder(); IEnumerator <AbstractDirectory> lcDirectoryEnum = this.Metadata.GetDirectoryIterator(); while (lcDirectoryEnum.MoveNext()) { AbstractDirectory lcDirectory = lcDirectoryEnum.Current; CreateDirectory(lcBuff, lcDirectory); lcDirectory = null; } return(lcBuff.ToString()); }
/// <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> /// Creates a directory tag. /// /// Examples : /// <pre> /// <directory name="Exif"> /// <tag> /// ... /// </tag> /// <tag> /// ... /// </tag> /// </directory> /// </pre> /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { Open(aBuff, "directory name=\"" + aDirectory.GetName() + "\"", true); IEnumerator <Tag> lcTagsEnum = aDirectory.GetTagIterator(); while (lcTagsEnum.MoveNext()) { Tag lcTag = lcTagsEnum.Current; CreateTag(aBuff, lcTag); lcTag = null; } Close(aBuff, "directory", true); } }
/// <summary> /// Creates a directory tag. /// </summary> /// <param name="aBuff">where to put info</param> /// <param name="aDirectory">the information to add</param> protected virtual void CreateDirectory(StringBuilder aBuff, AbstractDirectory aDirectory) { if (aDirectory != null) { aBuff.Append("--| ").Append(aDirectory.GetName()).Append(" |--"); aBuff.AppendLine(); IEnumerator <Tag> lcTagsEnum = aDirectory.GetTagIterator(); while (lcTagsEnum.MoveNext()) { Tag lcTag = lcTagsEnum.Current; CreateTag(aBuff, lcTag); lcTag = null; } } }
public File(IFileSystem fs, FileData file, AbstractDirectory parent) : base(fs) { Parent = parent; NewName = file.Name; Name = file.Name; Title = file.Name; Size = file.Length; Updated = file.Updated; Created = file.Created; url = file.VirtualPath; string icon = ImagesUtility.GetResizedPath(file.VirtualPath, "icon"); if (FileSystem.FileExists(icon)) this.iconUrl = icon; }
private void SyncDirectory(AbstractDirectory source, AbstractDirectory destination) { if (destination.Exists) { var directoriesInSource = source.GetDirectories().GetEnumerator(); var directoriesInDestination = destination.GetDirectories().GetEnumerator(); Sync(directoriesInSource, directoriesInDestination, destination, SyncDirectory); var regularFilesInSource = source.GetRegularFiles().GetEnumerator(); var regularFilesInDestination = destination.GetRegularFiles().GetEnumerator(); Sync(regularFilesInSource, regularFilesInDestination, destination, SyncRegularFile); destination.SetAllAttributes(source); } else { source.Copy(destination); } }
/// <summary> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public IptcDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
private void WriteSearch(HttpContext context) { var query = context.Request["query"]; if (string.IsNullOrWhiteSpace(query)) { context.Response.WriteJson(new { Status = "Error", Total = 0, Message = "Please provide a search term." }); return; } query = query.TrimStart().TrimEnd(); var host = Engine.Resolve <IHost>(); var rootItem = Engine.Persister.Get(host.DefaultSite.RootItemID); var root = new HierarchyNode <ContentItem>(rootItem); FS = Engine.Resolve <IFileSystem>(); var selectionTrail = Find.EnumerateParents(Selection.SelectedItem, null, true).ToList().Where(a => a is AbstractNode).Reverse().ToList(); var uploadDirectories = MediaBrowserUtils.GetAvailableUploadFoldersForAllSites(context, root, selectionTrail, Engine, FS); if (uploadDirectories.Count == 0) { context.Response.WriteJson(new { Status = "Error", Total = 0, Message = "No available directories in this site." }); return; } //Do the search using the IFileSystem var resultsFileData = FS.SearchFiles(query, uploadDirectories); if (!resultsFileData.Any()) { context.Response.WriteJson(new { Status = "Error", Total = 0, Message = "0 files found." }); return; } var files = new List <File>(); var fileMap = new Dictionary <string, File>(StringComparer.OrdinalIgnoreCase); var lastParent = string.Empty; AbstractDirectory parent = null; foreach (var fd in resultsFileData.OrderBy(s => s.VirtualPath)) { var parentDirectory = fd.VirtualPath.Substring(0, fd.VirtualPath.LastIndexOf('/')); if (lastParent != parentDirectory) { parent = new Directory(DirectoryData.Virtual(parentDirectory), null); lastParent = parentDirectory; } var file = new File(fd, parent); file.Set(FS); file.Set(ImageSizes); var unresizedFileName = ImageSizes.RemoveImageSize(file.Name); if (unresizedFileName != null && fileMap.ContainsKey(unresizedFileName)) { fileMap[unresizedFileName].Add(file); if (ImageSizes.GetSizeName(file.Name) == "icon") { file.IsIcon = true; } } else { if (unresizedFileName == null) { files.Add(file); fileMap[file.Name] = file; } } } files.Sort(new TitleComparer <File>()); var directory = FS.GetDirectory("/"); var fsRootPath = directory != null && !string.IsNullOrWhiteSpace(directory.RootPath) ? directory.RootPath : ""; var selectableExtensions = context.Request["exts"]; context.Response.WriteJson(new { Path = "", Total = files.Count, Files = GetFileReducedList(files, ImageSizes, selectableExtensions, fsRootPath) }); }
/// <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> /// Process one of the nested Tiff IFD directories. /// 2 bytes: number of tags for each tag /// 2 bytes: tag type /// 2 bytes: format code /// 4 bytes: component count /// </summary> /// <param name="directory">the directory</param> /// <param name="dirStartOffSet">where to start</param> private void ProcessDirectory(AbstractDirectory directory, IDictionary <int, string> processedDirectoryOffsets, int dirStartOffset, int tiffHeaderOffset) { // check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist if (processedDirectoryOffsets.ContainsKey(dirStartOffset)) { return; } // remember that we've visited this directory so that we don't visit it again later processedDirectoryOffsets.Add(dirStartOffset, MARK_AS_PROCESSED); if (dirStartOffset >= base.data.Length || dirStartOffset < 0) { directory.HasError = true; Trace.TraceError("Ignored directory marked to start outside data segement"); return; } if (!IsDirectoryLengthValid(dirStartOffset, tiffHeaderOffset)) { directory.HasError = true; Trace.TraceError("Illegally sized directory"); return; } // First two bytes in the IFD are the tag count int dirTagCount = Get16Bits(dirStartOffset); // Handle each tag in this directory for (int tagNumber = 0; tagNumber < dirTagCount; tagNumber++) { int tagOffset = CalculateTagOffset(dirStartOffset, tagNumber); // 2 bytes for the tag type int tagType = Get16Bits(tagOffset); // 2 bytes for the format code int formatCode = Get16Bits(tagOffset + 2); if (formatCode < 1 || formatCode > MAX_FORMAT_CODE) { directory.HasError = true; Trace.TraceError("Invalid format code: " + formatCode); continue; } // 4 bytes dictate the number of components in this tag'lcStr data int componentCount = Get32Bits(tagOffset + 4); if (componentCount < 0) { directory.HasError = true; Trace.TraceError("Negative component count in EXIF"); continue; } // each component may have more than one byte... calculate the total number of bytes int byteCount = componentCount * BYTES_PER_FORMAT[formatCode]; int tagValueOffset = CalculateTagValueOffset(byteCount, tagOffset, tiffHeaderOffset); if (tagValueOffset < 0 || tagValueOffset > base.data.Length) { directory.HasError = true; Trace.TraceError("Illegal pointer offset value in EXIF"); continue; } // Check that this tag isn't going to allocate outside the bounds of the data array. // This addresses an uncommon OutOfMemoryError. if (byteCount < 0 || tagValueOffset + byteCount > base.data.Length) { directory.HasError = true; Trace.TraceError("Illegal number of bytes: " + byteCount); continue; } // Calculate the value as an lcOffset for cases where the tag represents directory int subdirOffset = tiffHeaderOffset + Get32Bits(tagValueOffset); switch (tagType) { case TAG_EXIF_OFFSET: ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.ExifDirectory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); continue; case TAG_INTEROP_OFFSET: ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.ExifInteropDirectory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); continue; case TAG_GPS_INFO_OFFSET: ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.GpsDirectory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); continue; case TAG_MAKER_NOTE: ProcessMakerNote(tagValueOffset, processedDirectoryOffsets, tiffHeaderOffset); continue; default: ProcessTag(directory, tagType, tagValueOffset, componentCount, formatCode); break; } } // End of for // at the end of each IFD is an optional link to the next IFD int finalTagOffset = CalculateTagOffset(dirStartOffset, dirTagCount); int nextDirectoryOffset = Get32Bits(finalTagOffset); if (nextDirectoryOffset != 0) { nextDirectoryOffset += tiffHeaderOffset; if (nextDirectoryOffset >= base.data.Length) { Trace.TraceWarning("Last 4 bytes of IFD reference another IFD with an address that is out of bounds\nNote this could have been caused by jhead 1.3 cropping too much"); return; } else if (nextDirectoryOffset < dirStartOffset) { Trace.TraceWarning("Last 4 bytes of IFD reference another IFD with an address that is before the start of this directory"); return; } // the next directory is of same type as this one ProcessDirectory(directory, processedDirectoryOffsets, nextDirectoryOffset, tiffHeaderOffset); } }
/// <summary> /// Constructor of the object /// </summary> /// <param name="base.directory">a base.directory</param> public ExifInteropDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// This method serves as marsheller of objects for dataset. /// It converts from IPTC octets to relevant java object. /// </summary> /// <param name="aDirectory">the directory</param> /// <param name="aDirectoryType">the directory type</param> /// <param name="aTagType">the tag type</param> /// <param name="anOffset">the lcOffset</param> /// <param name="aTagByteCount">the tag byte count</param> private void ProcessTag( AbstractDirectory aDirectory, int aDirectoryType, int aTagType, int anOffset, int aTagByteCount) { int tagIdentifier = aTagType | (aDirectoryType << 8); switch (tagIdentifier) { case IptcDirectory.TAG_RECORD_VERSION: // short short shortValue = (short)((base.data[anOffset] << 8) | base.data[anOffset + 1]); aDirectory.SetObject(tagIdentifier, shortValue); return; case IptcDirectory.TAG_URGENCY: // byte aDirectory.SetObject(tagIdentifier, base.data[anOffset]); return; case IptcDirectory.TAG_RELEASE_DATE: case IptcDirectory.TAG_DATE_CREATED: // Date object if (aTagByteCount >= 8) { string dateStr = Utils.Decode(base.data, anOffset, aTagByteCount, false); try { int year = Convert.ToInt32(dateStr.Remove(4)); int month = Convert.ToInt32(dateStr.Substring(4, 2)); //No -1 here; int day = Convert.ToInt32(dateStr.Substring(6, 2)); DateTime date = new DateTime(year, month, day); aDirectory.SetObject(tagIdentifier, date); return; } catch (FormatException) { // fall through and we'll store whatever was there as a String } } break; // Added for .Net compiler //case IptcDirectory.TAG_RELEASE_TIME: //case IptcDirectory.TAG_TIME_CREATED: } // If no special handling by now, treat it as a string string str = null; if (aTagByteCount < 1) { str = ""; } else { str = Utils.Decode(base.data, anOffset, aTagByteCount, false); } if (aDirectory.ContainsTag(tagIdentifier)) { string[] oldStrings; string[] newStrings; try { oldStrings = aDirectory.GetStringArray(tagIdentifier); } catch (MetadataException) { oldStrings = null; } if (oldStrings == null) { newStrings = new String[1]; } else { newStrings = new string[oldStrings.Length + 1]; for (int i = 0; i < oldStrings.Length; i++) { newStrings[i] = oldStrings[i]; } } newStrings[newStrings.Length - 1] = str; aDirectory.SetObject(tagIdentifier, newStrings); } else { aDirectory.SetObject(tagIdentifier, str); } }
/// <summary> /// Constructor of the object /// </summary> /// <param name="directory">a directory</param> public JpegCommentDescriptor(AbstractDirectory directory) : base(directory) { }
/// <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> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public CasioType1Descriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// Determine the camera model and makernote format /// </summary> /// <param name="subdirOffset">the sub lcOffset dir</param> /// <param name="processedDirectoryOffsets">the processed directory offsets</param> /// <param name="tiffHeaderOffset">the tiff lcHeader lcOffset</param> private void ProcessMakerNote(int subdirOffset, IDictionary <int, string> processedDirectoryOffsets, int tiffHeaderOffset) { // Console.WriteLine("ProcessMakerNote value="+subdirOffSet); // Determine the camera model and makernote format AbstractDirectory exifDirectory = this.metadata.GetDirectory("com.drew.metadata.exif.ExifDirectory"); if (exifDirectory == null) { return; } string cameraModel = exifDirectory.GetString(ExifDirectory.TAG_MAKE); string firstTwoChars = Utils.Decode(base.data, subdirOffset, 2, false); string firstThreeChars = Utils.Decode(base.data, subdirOffset, 3, false); string firstFourChars = Utils.Decode(base.data, subdirOffset, 4, false); string firstFiveChars = Utils.Decode(base.data, subdirOffset, 5, false); string firstSixChars = Utils.Decode(base.data, subdirOffset, 6, false); string firstSevenChars = Utils.Decode(base.data, subdirOffset, 7, false); string firstEightChars = Utils.Decode(base.data, subdirOffset, 8, false); if ("OLYMP".Equals(firstFiveChars) || "EPSON".Equals(firstFiveChars) || "AGFA".Equals(firstFourChars)) { Trace.TraceInformation("Found an Olympus/Epson/Agfa directory."); // Olympus Makernote // Epson and Agfa use Olypus maker note standard, see: // http://www.ozhiker.com/electronics/pjmt/jpeg_info/ ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.OlympusDirectory"), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset); } else if (cameraModel != null && cameraModel.Trim().ToUpper().StartsWith("NIKON")) { if ("Nikon".Equals(Utils.Decode(base.data, subdirOffset, 5, false))) { // There are two scenarios here: // Type 1: // :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon........... // :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................ // Type 3: // :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*... // :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200 if (base.data[subdirOffset + 6] == 1) { Trace.TraceInformation("Found an Nykon Type 1 directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.NikonType1Directory"), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset); } else if (base.data[subdirOffset + 6] == 2) { Trace.TraceInformation("Found an Nykon Type 2 directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.NikonType2Directory"), processedDirectoryOffsets, subdirOffset + 18, subdirOffset + 10); } else { exifDirectory.HasError = true; Trace.TraceError( "Unsupported makernote for Nikon data ignored."); } } else { Trace.TraceInformation("Found an Nykon Type 2 directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.NikonType2Directory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); } } else if ("SONY CAM".Equals(firstEightChars) || "SONY DSC".Equals(firstEightChars)) { Trace.TraceInformation("Found a Sony directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.SonyDirectory"), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset); } else if ("KDK".Equals(firstThreeChars)) { Trace.TraceInformation("Found a Kodak directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.KodakDirectory"), processedDirectoryOffsets, subdirOffset + 20, tiffHeaderOffset); } else if ("Canon".ToUpper().Equals(cameraModel.ToUpper())) { Trace.TraceInformation("Found a Canon directory."); ProcessDirectory( this.metadata.GetDirectory("com.drew.metadata.exif.CanonDirectory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); } else if (cameraModel != null && cameraModel.ToUpper().StartsWith("CASIO")) { if ("QVC\u0000\u0000\u0000".Equals(firstSixChars)) { Trace.TraceInformation("Found a Casion Type 2 directory."); ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.CasioType2Directory"), processedDirectoryOffsets, subdirOffset + 6, tiffHeaderOffset); } else { Trace.TraceInformation("Found a Casion Type 1 directory."); ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.CasioType1Directory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); } } else if ("FUJIFILM".Equals(firstEightChars) || "Fujifilm".ToUpper().Equals(cameraModel.ToUpper())) { Trace.TraceInformation("Found a Fujifilm directory."); // TODO make this field a passed parameter, to avoid threading issues bool byteOrderBefore = this.isMotorollaByteOrder; // bug in fujifilm makernote ifd means we temporarily use Intel byte ordering this.isMotorollaByteOrder = false; // the 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote // IFD, though the lcOffset is relative to the start of the makernote, not the TIFF // lcHeader (like everywhere else) int ifdStart = subdirOffset + Get32Bits(subdirOffset + 8); ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.FujifilmDirectory"), processedDirectoryOffsets, ifdStart, tiffHeaderOffset); this.isMotorollaByteOrder = byteOrderBefore; } else if (cameraModel != null && cameraModel.ToUpper().StartsWith("MINOLTA")) { Trace.TraceInformation("Found a Minolta directory, will use Olympus directory."); // Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote // area that commences immediately. ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif. OlympusDirectory"), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); } else if ("KC".Equals(firstTwoChars) || "MINOL".Equals(firstFiveChars) || "MLY".Equals(firstThreeChars) || "+M+M+M+M".Equals(firstEightChars)) { // This Konica data is not understood. Header identified in accordance with information at this site: // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html // TODO determine how to process the information described at the above website Trace.TraceError("Unsupported Konica/Minolta data ignored."); } else if ("KYOCERA".Equals(firstSevenChars)) { Trace.TraceInformation("Found a Kyocera directory"); // http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.KyoceraDirectory"), processedDirectoryOffsets, subdirOffset + 22, tiffHeaderOffset); } else if ("Panasonic\u0000\u0000\u0000".Equals(Utils.Decode(base.data, subdirOffset, 12, false))) { Trace.TraceInformation("Found a panasonic directory"); // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD // Offsets are relative to the start of the TIFF lcHeader at the beginning of the EXIF segment // more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.PanasonicDirectory"), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset); } else if ("AOC\u0000".Equals(firstFourChars)) { Trace.TraceInformation("Found a Casio type 2 directory"); // NON-Standard TIFF IFD Data using Casio Type 2 Tags // IFD has no Next-IFD pointer at end of IFD, and // Offsets are relative to the start of the current IFD tag, not the TIFF lcHeader // Observed for: // - Pentax ist D ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.CasioType2Directory"), processedDirectoryOffsets, subdirOffset + 6, subdirOffset); } else if (cameraModel != null && (cameraModel.ToUpper().StartsWith("PENTAX") || cameraModel.ToUpper().StartsWith("ASAHI"))) { Trace.TraceInformation("Found a Pentax directory"); // NON-Standard TIFF IFD Data using Pentax Tags // IFD has no Next-IFD pointer at end of IFD, and // Offsets are relative to the start of the current IFD tag, not the TIFF lcHeader // Observed for: // - PENTAX Optio 330 // - PENTAX Optio 430 ProcessDirectory(this.metadata.GetDirectory("com.drew.metadata.exif.PentaxDirectory"), processedDirectoryOffsets, subdirOffset, subdirOffset); } else { // TODO how to store makernote data when it'str not from a supported camera model? Trace.TraceError("Unsupported directory data ignored."); } }
/// <summary> /// Processes tag /// </summary> /// <param name="directory">the directory</param> /// <param name="aTagType">the tag type</param> /// <param name="tagValueOffset">the lcOffset value</param> /// <param name="componentCount">the component count</param> /// <param name="formatCode">the format code</param> private void ProcessTag( AbstractDirectory directory, int tagType, int tagValueOffset, int componentCount, int formatCode) { // Directory simply stores raw values // The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions switch (formatCode) { case FMT_UNDEFINED: Debug.Write("Found a tag made of bytes"); // this includes exif user comments byte[] tagBytes = new byte[componentCount]; int byteCount = componentCount * BYTES_PER_FORMAT[formatCode]; for (int i = 0; i < byteCount; i++) { tagBytes[i] = base.data[tagValueOffset + i]; } directory.SetObject(tagType, tagBytes); break; case FMT_STRING: Debug.Write("Found a tag made of string"); string lcStr = null; if (tagType == ExifDirectory.TAG_USER_COMMENT) { lcStr = ReadCommentString( tagValueOffset, componentCount, formatCode); } else { lcStr = ReadString(tagValueOffset, componentCount); } directory.SetObject(tagType, lcStr); break; case FMT_SRATIONAL: //goto case FMT_URATIONAL; case FMT_URATIONAL: if (componentCount == 1) { Debug.Write("Found a tag made of rational"); Rational rational = new Rational(Get32Bits(tagValueOffset), Get32Bits(tagValueOffset + 4)); directory.SetObject(tagType, rational); } else { Debug.Write("Found a tag made of rationals"); Rational[] rationals = new Rational[componentCount]; for (int i = 0; i < componentCount; i++) { rationals[i] = new Rational(Get32Bits(tagValueOffset + (8 * i)), Get32Bits(tagValueOffset + 4 + (8 * i))); } directory.SetObject(tagType, rationals); } break; case FMT_SBYTE: //goto case FMT_BYTE; case FMT_BYTE: if (componentCount == 1) { Debug.Write("Found a tag made of byte"); // this may need to be a byte, but I think casting to int is fine int b = base.data[tagValueOffset]; directory.SetObject(tagType, b); } else { Debug.Write("Found a tag made of bytes but will use ints"); int[] bytes = new int[componentCount]; for (int i = 0; i < componentCount; i++) { bytes[i] = base.data[tagValueOffset + i]; } directory.SetIntArray(tagType, bytes); } break; case FMT_SINGLE: //goto case FMT_DOUBLE; case FMT_DOUBLE: if (componentCount == 1) { Debug.Write("Found a tag made of double but will use int"); int i = base.data[tagValueOffset]; directory.SetObject(tagType, i); } else { Debug.Write("Found a tag made of doubles but will use ints"); int[] ints = new int[componentCount]; for (int i = 0; i < componentCount; i++) { ints[i] = base.data[tagValueOffset + i]; } directory.SetIntArray(tagType, ints); } break; case FMT_USHORT: //goto case FMT_SSHORT; case FMT_SSHORT: if (componentCount == 1) { Debug.Write("Found a tag made of short but will use int"); int i = Get16Bits(tagValueOffset); directory.SetObject(tagType, i); } else { Debug.Write("Found a tag made of shorts but will use ints"); int[] ints = new int[componentCount]; for (int i = 0; i < componentCount; i++) { ints[i] = Get16Bits(tagValueOffset + (i * 2)); } directory.SetIntArray(tagType, ints); } break; case FMT_SLONG: //goto case FMT_ULONG; case FMT_ULONG: if (componentCount == 1) { Debug.Write("Found a tag made of long but will use int"); int i = Get32Bits(tagValueOffset); directory.SetObject(tagType, i); } else { Debug.Write("Found a tag made of longs but will use ints"); int[] ints = new int[componentCount]; for (int i = 0; i < componentCount; i++) { ints[i] = Get32Bits(tagValueOffset + (i * 4)); } directory.SetIntArray(tagType, ints); } break; default: Trace.TraceWarning("Unknown format code " + formatCode + " for tag " + tagType); break; } }
/// <summary> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public PanasonicDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public OlympusDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// Constructor of the object /// </summary> /// <param name="directory">a directory</param> public KodakDescriptor(AbstractDirectory directory) : base(directory) { }
/// <summary> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public FujifilmDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <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> /// Constructor of the object /// </summary> /// <param name="base.directory">a base.directory</param> public NikonType2Descriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// Constructor of the object /// </summary> /// <param name="aDirectory">a base.directory</param> public KyoceraDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }
/// <summary> /// Constructor of the object /// </summary> /// <param name="base.directory">a base.directory</param> public PentaxDescriptor(AbstractDirectory aDirectory) : base(aDirectory) { }