【问题标题】:Changing "DateTaken" of a photo更改照片的“拍摄日期”
【发布时间】:2015-11-11 01:32:42
【问题描述】:

我刚从美国旅行回来,在编辑完所有照片后,我注意到相机使用的是以色列时区,而不是美国时区。有7个小时的时差,所以对我来说是个大问题。我有 175GB 的照片,但我“只关心”大约 350 张照片。我无法手动编辑他们的 EXIF,所以我考虑使用 C#。

这个想法是它会读取每张照片的 EXIF,获取时间,并在原始照片中将时间设置为负 7 小时。我尝试使用 Image 类,但它不起作用。我尝试使用 bitmapMetadate,它成功了!我设法抽出时间并做了减去七个小时,但我不知道如何保存它。我该怎么做?谢谢!

    public static string PhotoToBeEdited(FileInfo f)
    {
        FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
        BitmapSource img = BitmapFrame.Create(fs);
        BitmapMetadata md = (BitmapMetadata)img.Metadata;
        string date = md.DateTaken;
        Console.WriteLine(date);
        DateTime dt= DateTime.Parse(date);
        date = dt.AddHours(-7).ToString();

        [...]

        return date;
    }

【问题讨论】:

    标签: c# bitmap exif


    【解决方案1】:

    我发现最简单的方法是使用here 和 System.Drawing.Bitmap 描述的技术;

    代码应该是这样的:

      public void ChangeDateTaken(string path)
        {
            Image theImage = new Bitmap(path);
            PropertyItem[] propItems = theImage.PropertyItems;
            Encoding _Encoding = Encoding.UTF8;
            var DataTakenProperty1 = propItems.Where(a => a.Id.ToString("x") == "9004").FirstOrDefault();
            var DataTakenProperty2 = propItems.Where(a => a.Id.ToString("x") == "9003").FirstOrDefault();
            string originalDateString = _Encoding.GetString(DataTakenProperty1.Value);
            originalDateString = originalDateString.Remove(originalDateString.Length - 1);
            DateTime originalDate = DateTime.ParseExact(originalDateString, "yyyy:MM:dd HH:mm:ss", null);
    
            originalDate = originalDate.AddHours(-7);
    
    
            DataTakenProperty1.Value = _Encoding.GetBytes(originalDate.ToString("yyyy:MM:dd HH:mm:ss") + '\0');
            DataTakenProperty2.Value = _Encoding.GetBytes(originalDate.ToString("yyyy:MM:dd HH:mm:ss") + '\0');
            theImage.SetPropertyItem(DataTakenProperty1);
            theImage.SetPropertyItem(DataTakenProperty2);
            string new_path = System.IO.Path.GetDirectoryName(path) + "\\_" + System.IO.Path.GetFileName(path);
            theImage.Save(new_path);
            theImage.Dispose();
        }
    

    不要忘记添加 System.Drawing 程序集。 如果需要,您可能还需要根据您的文化调整 DateTime 格式

    【讨论】:

    • 谢谢!你真是个天才!
    • 提示:如果尚未指定拍摄日期,则必须创建新的 propItems。这并不容易,因为构造函数不允许这样做,但我找到了一种方法 here. 所以你可以检查 DataTakenProperty1 是否为 null,如果它为 null,则创建新道具。
    【解决方案2】:

    对于 .NET Core,我使用 NuGet 包 ExifLibNet (https://github.com/oozcitak/exiflibrary)

    PM> 安装包 ExifLibNet

    // using ExifLibrary;
    
    var file = ImageFile.FromFile(filename);
    file.Properties.Set(ExifTag.DateTimeDigitized, dateTime);
    file.Properties.Set(ExifTag.DateTimeOriginal, dateTime);
    file.Save(filename);
    

    【讨论】:

    【解决方案3】:

    不完全是编程解决方案,但您可以使用exiftool。我将它用于这个确切的目的。

    日期/时间转换功能

    您有没有忘记在数码相机上设置日期/时间 在拍一堆照片之前? ExifTool 具有时移功能 这使得将批处理修复应用到 图像(例如,更改 Windows 报告的“拍摄日期” 探险家)。例如,您的相机时钟已重置为 2000:01:01 00:00:00 当您在 2005:11:03 放入新电池时 10:48:00。然后你后来拍的所有照片都有 5 年、10 个月、2 天、10 小时和 48 分钟。要解决此问题,请将所有图像放在同一目录中 ("DIR") 并运行 exiftool:

    > exiftool "-DateTimeOriginal+=5:10:2 10:48:0" DIR
    

    您还可以设置TimeZoneOffset 字段,以防有软件实际使用它。

    【讨论】:

    • 我试过了,我放弃了。我不知道如何使用它。不管怎么说,还是要谢谢你。顺便说一句,你有个好名字!
    猜你喜欢
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多