swift - 修改图像元数据

标签 swift core-foundation

我正在尝试修改 JPEG 图像中包含的元数据。它可以是图像中的任何元数据,在我的示例中,我试图将 DateTimeDigitized 属性更改为当前日期。

我的代码似乎大部分都可以工作,但是 set 属性被删除而不是更改。我不确定为什么会这样,谁能告诉我我做错了什么?

我欢迎任何关于有助于执行任务的框架的建议,但我特别感兴趣的是我在使用这种方法时做错了什么。

我在 Playground 中运行此代码,其中名为“foo.jpg”的图像存储在路径 ~/Documents/Shared Playground Data/ 中。

import Foundation
import ImageIO            // CGImage functions
import PlaygroundSupport

let ImagePropertyExifDictionary = kCGImagePropertyExifDictionary as String
let ImagePropertyExifDateTimeDigitized = kCGImagePropertyExifDateTimeDigitized as String

func updateEXIFDateDigitized() {
  // Create URL for source and destination
  let sourceURL = playgroundSharedDataDirectory.appendingPathComponent("foo.jpg") as CFURL
  let destinationURL = playgroundSharedDataDirectory.appendingPathComponent("bar.jpg") as CFURL

  // Read source and get properties
  guard
    let sourceRef = CGImageSourceCreateWithURL(sourceURL, nil),
    var metadata = CGImageSourceCopyPropertiesAtIndex(sourceRef, 0, nil) as? [String:Any] else { return }

  print("unmodified properties", metadata, separator:"\n")

  // Modify EXIF DateTimeDigitized property
  guard var exif = metadata[ImagePropertyExifDictionary] as? [String:Any] else { return }

  exif[ImagePropertyExifDateTimeDigitized] = Date() as CFDate
  metadata[ImagePropertyExifDictionary] = exif as CFDictionary
  print("", "modified properties", metadata, separator:"\n")

  // Set up destination
  guard let destinationRef = CGImageDestinationCreateWithURL(destinationURL, kUTTypeJPEG, 1, nil) else { return }

  // Add image from source to destination with new properties
  CGImageDestinationAddImageFromSource(destinationRef, sourceRef, 0, metadata as CFDictionary)

  // Save destination
  guard CGImageDestinationFinalize(destinationRef) else { return }

  guard
    let sourceRef2 = CGImageSourceCreateWithURL(destinationURL, nil),
    let metadata2 = CGImageSourceCopyPropertiesAtIndex(sourceRef2, 0, nil) else { return }

  print("", "saved properties", metadata2, separator:"\n")
}

updateEXIFDateDigitized()

结果的相关位,为简洁起见,我删除了其他字段:

unmodified properties
{
  "{Exif}" =     {
    DateTimeDigitized = "2007:07:31 17:42:01";
    DateTimeOriginal = "2007:07:31 17:42:01";
  };
}

modified properties
{
  "{Exif}" =     {
    DateTimeDigitized = "2017-05-11 15:45:38 +0000";
    DateTimeOriginal = "2007:07:31 17:42:01";
  };
}

saved properties
{
  "{Exif}" =     {
    DateTimeOriginal = "2007:07:31 17:42:01";
  };
}

最佳答案

我正在自己回答这个问题,因为我发现了为什么它没有保存数据,而且看起来这个问题可以帮助其他人。

我的代码是正确的,唯一的问题是我没有正确格式化日期。由于日期格式不正确,因此框架对其进行了修剪。我像这样格式化日期并正确保存和显示:

let formatter = DateFormatter()
formatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
exif[ImagePropertyExifDateTimeDigitized] = formatter.string(from: Date())

这代替了行:

exif[ImagePropertyExifDateTimeDigitized] = Date() as CFDate

现在的输出是(再次修剪为仅相关属性):

unmodified properties
  {
    "{Exif}" =     {
      DateTimeDigitized = "2007:07:31 17:42:01";
      DateTimeOriginal = "2007:07:31 17:42:01";
    };
}

modified properties
  {
    "{Exif}" =     {
      DateTimeDigitized = "2017:05:12 01:04:14";
      DateTimeOriginal = "2007:07:31 17:42:01";
    };
}

saved properties
  {
    "{Exif}" =     {
      DateTimeDigitized = "2017:05:12 01:04:14";
      DateTimeOriginal = "2007:07:31 17:42:01";
    };
}

关于swift - 修改图像元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43920643/

相关文章:

swift - 如何在 swift 中执行 block 样式函数

ios - 如何防止访问其他类的委托(delegate)方法?

swift - 可选绑定(bind)评估可选(nil)的不需要的行为

swift - 在 Swift 中使用 CFArrayGetValueAtIndex 和 UnsafePointer (AUPreset)

macos - C 数据结构还是核心基础?

objective-c - 为什么框架中的常量不需要 __bridge?

swift - 使用 prepareForSegue 时 indexPathForSelectedRow 错误

ios - 没有关系的核心数据中的两个实体是糟糕的设计吗?

c++ - CFStringCompareWithOptions 的奇怪行为

iPhone 如何使用 ARC 正确处理 Core Foundation 引用?