public async void TestFilenameWithSpace() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("space test.NEF")).ToList(); Assert.True(res.Count() > 0); }
private static int Main(string[] args) { var workingDirectory = new DirectoryInfo(CurrentPath); var exifTool = new ExifTool(new ExifToolOptions { ExifToolPath = "/usr/bin/vendor_perl/exiftool" }); var exifWrapper = new ExifWrapper(exifTool); var rootImageHandler = new RootImageHandler(exifWrapper); var fromIPhoneOld = CommandExtensions.Create( "from-iphone-old", "Converts a dump from iPhone into a date-based directory structure", dryRun => FromIPhoneOld.Run(workingDirectory, dryRun)); var fromIPhone = CommandExtensions.CreateWithOutput( "from-iphone", "Converts a dump from iPhone into a date-based directory structure", (dryRun, output) => { new FromIPhone(exifWrapper) .Run(workingDirectory, output, dryRun); }); var fixExif = CommandExtensions.Create( "fix-exif", "Set all the missing Exif dates in Exif in a directory, inferring the missing dates from directory names", dryRun => { new FixExif(rootImageHandler).Run(workingDirectory, dryRun); }); var removeDuplicateJpg = CommandExtensions.Create( "remove-duplicate-jpg", "Remove the JPG files that duplicate equivalent HEIC images", dryRun => RemoveDuplicateJpg.Run(workingDirectory, dryRun) ); var separateIPhone5 = CommandExtensions.CreateWithOutput( "identify-iphone5", "Identify which photos have been taken with iPhone 5", (dryRun, output) => { new IdentifyIPhone5(exifWrapper) .Run(workingDirectory, dryRun); }); var rootCommand = new RootCommand { new Option("--version", "The current version of this tool"), fromIPhoneOld, fromIPhone, fixExif, removeDuplicateJpg, separateIPhone5 }; rootCommand.Handler = CommandHandler.Create(Version.VersionHandler); return(rootCommand.Invoke(args)); }
public async void FileToStreamWriteTest() { var opts = new ExifToolOptions(); var et = new ExifTool(opts); var result = await et.WriteTagsAsync(SRC_FILE, UPDATES); Assert.True(result.Success); Assert.NotNull(result.Output); ValidateTags(await et.GetTagsAsync(result.Output)); }
public async void TestQuiet() { Console.WriteLine("---------------------"); Console.WriteLine("Quiet test (should not see spewage below)"); var et = new ExifTool(new ExifToolOptions { Quiet = true }); var tags = (await et.GetTagsAsync("DSC_3982.NEF")).ToList(); Console.WriteLine("---------------------"); }
public async void GetTagsFromImage() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("DSC_3982.NEF")).ToList(); foreach (var tag in res) { Console.WriteLine($"{tag.Name} : {tag.Description} : {tag.Value}"); } Assert.True(res.Count() > 0); }
public async void StreamToFileWriteTest() { var opts = new ExifToolOptions(); var et = new ExifTool(opts); var src = new FileStream(SRC_FILE, FileMode.Open); var result = await et.WriteTagsAsync(src, UPDATES, "stream_to_file_test.jpg"); Assert.True(result.Success); Assert.Null(result.Output); ValidateTag(await et.GetTagsAsync("stream_to_file_test.jpg")); }
public async void GetRegionExtensionsTags() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("35781602-96011d02-09ec-11e8-9335-aaa98042aa5a.jpg")).ToList(); var region = res.SingleOrDefaultPrimaryTag("RegionAreaY"); Assert.NotNull(region); Assert.NotNull(region.List); Assert.Equal(2, region.List.Count); Assert.Equal(0.4605, Convert.ToDouble(region.List[0])); Assert.Equal(0.4710, Convert.ToDouble(region.List[1])); }
public async void FileToFileWriteTest() { var opts = new ExifToolOptions(); var et = new ExifTool(opts); var result = await et.WriteTagsAsync(SRC_FILE, UPDATES, "file_to_file_test.jpg"); Assert.True(result.Success); Assert.Null(result.Output); ValidateTags(await et.GetTagsAsync("file_to_file_test.jpg")); File.Delete("file_to_file_test.jpg"); }
public async void OverwriteTest() { File.Copy(SRC_FILE, "overwrite_test.jpg"); var opts = new ExifToolOptions(); var et = new ExifTool(opts); var result = await et.OverwriteTagsAsync("overwrite_test.jpg", UPDATES); Assert.True(result.Success); Assert.Null(result.Output); ValidateTag(await et.GetTagsAsync("overwrite_test.jpg")); File.Delete("overwrite_test.jpg"); }
public async void OverwriteOriginalInPlaceTest() { File.Copy(SRC_FILE, "overwrite_original_in_place_test.jpg", true); var opts = new ExifToolOptions(); var et = new ExifTool(opts); var result = await et.OverwriteTagsAsync("overwrite_original_in_place_test.jpg", UPDATES, FileWriteMode.OverwriteOriginalInPlace); Assert.True(result.Success); Assert.Null(result.Output); ValidateTags(await et.GetTagsAsync("overwrite_original_in_place_test.jpg")); File.Delete("overwrite_original_in_place_test.jpg"); }
public async void TestExifValues() { var et = new ExifTool(new ExifToolOptions()); var tags = (await et.GetTagsAsync("DSC_3982.NEF")).ToList(); var bitsPerSample = GetExifData <ushort>(tags, "BitsPerSample")?.TypedValue; var digitalZoomRatio = GetExifData <double>(tags, "DigitalZoomRatio")?.TypedValue; var expTime = GetExifData <double>(tags, "ExposureTime"); Assert.True(bitsPerSample == 14, "bits per sample should be 14 for this photo"); Assert.True(digitalZoomRatio == 1, "digital zoom ratio should be 1 for this photo"); Assert.Equal("1/500", expTime.Value); Assert.Equal("0.002", expTime.NumberValue); Assert.Equal(.002, expTime.TypedValue); }
public async void TestExifValues() { var et = new ExifTool(new ExifToolOptions()); var tags = (await et.GetTagsAsync("DSC_3982.NEF")).ToList(); var bitsPerSampleTag = tags.SingleOrDefaultPrimaryTag("BitsPerSample"); var bitsPerSample = bitsPerSampleTag?.TryGetUInt16(); var digitalZoomRatio = tags.SingleOrDefaultPrimaryTag("DigitalZoomRatio")?.TryGetDouble(); var expTime = tags.SingleOrDefaultPrimaryTag("ExposureTime"); Assert.Equal((ushort?)14, bitsPerSample); Assert.Equal((double?)1, digitalZoomRatio); Assert.Equal("1/500", expTime.Value); Assert.Equal("0.002", expTime.NumberValue); Assert.Equal(.002, expTime.GetDouble()); }
public async void HasExtensionTags() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("35781602-96011d02-09ec-11e8-9335-aaa98042aa5a.jpg")) .Where(x => x.TagInfo.Id.StartsWith("apple")) .ToList(); foreach (var tag in res) { Console.WriteLine($"{tag.GetType()} : {tag.TagInfo.Id} : {tag.TagInfo.Name} : {tag.TagInfo.Description} : {tag.Value}"); } Assert.True(res.Count() > 0); Assert.True(res.Count(x => x.TagInfo.Id == "apple-fi:RegionsRegionListExtensionsAngleInfoYaw") == 1); Assert.True(res.Count(x => x.TagInfo.Name == "RegionsRegionListExtensionsAngleInfoYaw") == 1); }
public async void FileToFileWriteTestEncoded() { var opts = new ExifToolOptions() { EscapeTagValues = true }; var et = new ExifTool(opts); var result = await et.WriteTagsAsync(SRC_FILE, UPDATES_ENCODED, "file_to_file_encoded_test.jpg"); Assert.True(result.Success); Assert.Null(result.Output); ValidateEncodedTag(await et.GetTagsAsync("file_to_file_encoded_test.jpg")); File.Delete("file_to_file_encoded_test.jpg"); }
public async void GetTagsFromImageWithKeywords() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("50032922-56e5cc00-ffee-11e8-9cc9-a1330b3a909f.jpg")).ToList(); foreach (var tag in res) { Console.WriteLine($"{tag.Name} : {tag.Description} : {tag.Value}"); } Assert.True(res.Count() > 0); var keywords = res.SingleOrDefaultPrimaryTag("keywords"); Assert.NotNull(keywords); Assert.NotNull(keywords.List); Assert.Equal(3, keywords.List.Count); Assert.Equal("Fay Canyon", keywords.List[1]); }
public async void GetTagsFromImage() { var et = new ExifTool(new ExifToolOptions()); var res = (await et.GetTagsAsync("DSC_3982.NEF")).ToList(); foreach (var tag in res) { Console.WriteLine($"{tag.GetType()} : {tag.TagInfo.Name} : {tag.TagInfo.Description} : {tag.Value}"); var tsft = tag as Tag <SubfileType>; if (tsft != null) { var sft = tsft.TypedValue; Assert.Equal("Full-resolution Image", sft.Description, true); } } Assert.True(res.Count() > 0); }
public async void TestStream() { using (var ms = new MemoryStream()) using (var fs = new FileStream("DSC_3982.NEF", FileMode.Open)) { fs.CopyTo(ms); ms.Seek(0, SeekOrigin.Begin); var et = new ExifTool(new ExifToolOptions()); var tags = (await et.GetTagsAsync(ms)).ToList(); var bitsPerSample = tags.SingleOrDefaultPrimaryTag("BitsPerSample")?.TryGetUInt16(); var digitalZoomRatio = tags.SingleOrDefaultPrimaryTag("DigitalZoomRatio")?.TryGetDouble(); var expTime = tags.SingleOrDefaultPrimaryTag("ExposureTime"); Assert.Equal((ushort?)14, bitsPerSample); Assert.Equal((double?)1, digitalZoomRatio); Assert.Equal("1/500", expTime.Value); Assert.Equal("0.002", expTime.NumberValue); Assert.Equal(0.002, expTime.GetDouble()); } }
public async void TestStream() { using (var ms = new MemoryStream()) using (var fs = new FileStream("DSC_3982.NEF", FileMode.Open)) { fs.CopyTo(ms); ms.Seek(0, SeekOrigin.Begin); var et = new ExifTool(new ExifToolOptions()); var tags = (await et.GetTagsAsync(ms)).ToList(); var bitsPerSample = GetExifData <ushort>(tags, "BitsPerSample")?.TypedValue; var digitalZoomRatio = GetExifData <double>(tags, "DigitalZoomRatio")?.TypedValue; var expTime = GetExifData <double>(tags, "ExposureTime"); Assert.True(bitsPerSample == 14, "bits per sample should be 14 for this photo"); Assert.True(digitalZoomRatio == 1, "digital zoom ratio should be 1 for this photo"); Assert.Equal("1/500", expTime.Value); Assert.Equal("0.002", expTime.NumberValue); Assert.Equal(.002, expTime.TypedValue); } }
/// <summary> /// Specialised constructor for a face read out with exiftool and written by Picasa /// </summary> /// <param name="region">Face information, including area and name</param> /// <param name="dimensions">Dimensions of the complete image</param> public Face(ExifTool.Region region, RegionInfoDimensions dimensions) { }
private static void Main(string[] args) { var videoPath = Prompt("Enter video path: "); videoPath = videoPath.Trim(); if (videoPath != null && !videoPath.EndsWith(".mp4")) { throw new Exception("Only .mp4 videos are supported."); } try { Console.WriteLine("Getting video metadata.."); //Using exiftool to get the metadata of the file. var exifTool = new ExifTool(new ExifToolOptions() { IncludeBinaryTags = true }); var metadata = exifTool.GetTagsAsync(videoPath).Result; var duration = metadata.First(x => x.Name == "Duration") ?? throw new Exception("You entered a non-video file."); var hexDuration = ""; if (duration.IsInteger) { hexDuration = duration.GetInt64().ToString("x8"); } else if (duration.IsDouble) { hexDuration = ((long)(duration.GetDouble() * 1000)).ToString("x8"); } Console.WriteLine("Converting video to hex.."); var hexString = Hex.ToHexString(File.ReadAllBytes(videoPath)); if (!hexString.Contains(Hex.ToHexString(LmvhdHex))) { throw new Exception("The LMVHD part is not found. File is either unsupported, or corrupted."); } //Get all text after the lmvhd part var lmvhdPart = hexString.Substring(hexString.IndexOf(Hex.ToHexString(LmvhdHex), StringComparison.Ordinal)); var newDuration = Prompt($"Enter new duration (hex, {hexDuration.Length} characters): "); if (newDuration.Length != hexDuration.Length) { throw new Exception("New duration's length is not equal to the original duration length."); } if (!long.TryParse(newDuration, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _)) { throw new Exception("You entered a non-hex string."); } //Replace only the first occurence of the correct pattern (the duration) Console.WriteLine("Replacing the correct bytes.."); var regex = new Regex(Regex.Escape(hexDuration)); var newText = regex.Replace(lmvhdPart, newDuration, 1); Console.WriteLine("Writing result to the file.."); var newFilePath = Path.Combine(Path.GetDirectoryName(videoPath), Path.GetFileNameWithoutExtension(videoPath) + "_edited.mp4"); File.Create(newFilePath).Close(); //Replace the lmvhd part with the new, edited part hexString = hexString.Replace(lmvhdPart, newText); File.WriteAllBytes(newFilePath, Hex.FromHexString(hexString)); Console.WriteLine($"Done!"); } catch (Exception e) { Console.WriteLine(e); throw; } }
internal ExifWrapper(ExifTool exifTool) { _exifTool = exifTool; }