复制Photoshop PSD图像时附加关键字

时间:2018-07-26 12:19:46

标签: swift metadata photoshop keyword

任务是在复制图像时以四种可能的格式(jpg,png,psd,tif)将关键字插入元数据。为游乐场设置了示例,以处理存储在桌面上“ Metadata Test”文件夹中的图像“ foo.jpg”等。所有图像均可正确复制,但在Adobe Bridge中查看时,除PSD外,所有关键词均会出现。有谁知道为什么PSD缺少关键字?

import Cocoa
import ImageIO
import PlaygroundSupport

func copyFileAppendKeywords(at: URL, to: URL, keywords: [String]) -> Bool {
    // Create source reference.
    guard let sourceRef = CGImageSourceCreateWithURL(at as CFURL, nil) else { return false }
    // Get source file type.
    guard let uti: CFString = CGImageSourceGetType(sourceRef) else { return false }
    // Create destination reference.
    guard let destinationRef = CGImageDestinationCreateWithURL(to as CFURL, uti, 1, nil) else { return false }
    // Get source metadata.
    var metadata: Dictionary<String, AnyObject>
    if let v = CGImageSourceCopyPropertiesAtIndex(sourceRef, 0, nil) {
        metadata = v as! Dictionary
    } else { return false }

    print("\n======== \(at.lastPathComponent) original metadata ========\n", metadata, separator:"\n")

    var iptc: Dictionary<String, AnyObject>
    if let v = metadata["{IPTC}"] {
        // Image has IPTC data.
        iptc = v as! Dictionary
    } else {
        // Image doesn't have IPTC data; create it.
        iptc = Dictionary<String, AnyObject>()
        iptc["Keywords"] = [] as AnyObject
    }
    // Create empty keyword array and fill it keywords provided.
    var iptcKeywords: [String] = []
    if let v = iptc["Keywords"] {
        // Image has existing keywords; append to them.
        // To instead replace all keywords, disable this block.
        iptcKeywords = v as! [String]
    }
    // Add each keyword.
    keywords.forEach {
        iptcKeywords.append($0)
    }
    // Add keywords array to IPTC dictionary.
    iptc["Keywords"] = iptcKeywords as AnyObject
    // Write (or overwrite) IPTC dictionary to metadata
    metadata["{IPTC}"] = iptc as AnyObject

    print("\n======== \(to.lastPathComponent) modified metadata ========\n", metadata, separator:"\n")

    // Copy image plus metadata
    CGImageDestinationAddImageFromSource(destinationRef, sourceRef, 0, metadata as CFDictionary)

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

    return true

    // NOTE: no keywords appear in resulting PSD.

}

let folder = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop").appendingPathComponent("Metadata Test")

var at: URL
var to: URL
let keywords: [String] = ["one", "two", "three"]

at = documents.appendingPathComponent("foo.jpg")
to = documents.appendingPathComponent("bar.jpg")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = documents.appendingPathComponent("foo.png")
to = documents.appendingPathComponent("bar.png")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = documents.appendingPathComponent("foo.psd")
to = documents.appendingPathComponent("bar.psd")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = documents.appendingPathComponent("foo.tif")
to = documents.appendingPathComponent("bar.tif")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

编辑:我尝试了使用CGImageDestinationCopyImageSource(卷积冒险)而不是CGImageDestinationAddImageFromSource的另一种方法,以查看它是否有所作为,并且因为(我认为)AddImageFromSource将重新压缩JPEG(我不确定)会更可取。 ,但以防万一。不幸的是,这种差异并不能解决问题。实际上,结果更糟-现在PNG也没有关键字。但是这种其他方法一文不值。两者都适用于JPEG。

import Cocoa
import ImageIO
import PlaygroundSupport

func copyFileAppendKeywords(at: URL, to: URL, keywords: [String]) -> Bool {
    // Create source reference.
    guard let sourceRef = CGImageSourceCreateWithURL(at as CFURL, nil) else { return false }
    CGImageSourceGetCount(sourceRef)
    // Get source file type.
    guard let uti: CFString = CGImageSourceGetType(sourceRef) else { return false }
    // Create destination reference.
    guard let destinationRef = CGImageDestinationCreateWithURL(to as CFURL, uti, 1, nil) else { return false }
    // Get source metadata.
    var metadata: CGMutableImageMetadata
    if let v = CGImageSourceCopyMetadataAtIndex(sourceRef, 0, nil) {
        metadata = CGImageMetadataCreateMutableCopy(v)!
    } else { return false }

    print("\n======== \(at.lastPathComponent) original metadata ========\n", metadata, separator:"\n")

    // Create empty keyword array and fill it keywords provided.
    var iptcKeywords: [String] = []
    // Add each keyword.
    keywords.forEach {
        iptcKeywords.append($0)
    }
    // Update dc:subject with new keywords.
    CGImageMetadataSetValueWithPath(metadata, nil, "dc:subject" as CFString, iptcKeywords as CFTypeRef)

    print("\n======== \(to.lastPathComponent) modified metadata ========\n", metadata, separator:"\n")

    // Copy file with new metadata.
    let destMetadata: [String: AnyObject] = [
        kCGImageDestinationMetadata as String: metadata as CGImageMetadata
    ]
    var errorRef: Unmanaged<CFError>?
    if !CGImageDestinationCopyImageSource(destinationRef, sourceRef, destMetadata as CFDictionary, &errorRef) {
        print (errorRef.debugDescription)
    }
    // NOTE: documentation claims...
    // "the CGImageDestinationCopyImageSource API supports the following image formats: JPEG, PNG, PSD, TIFF."
    // Does not appear true. Only formats affected are JPEG and TIFF. Keywords do not appear in PNG or PSD.

    return true
}

let folder = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop").appendingPathComponent("Metadata Test")
var at: URL
var to: URL
let keywords: [String] = ["one", "two", "three"]

at = folder.appendingPathComponent("foo.jpg")
to = folder.appendingPathComponent("bar.jpg")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = folder.appendingPathComponent("foo.png")
to = folder.appendingPathComponent("bar.png")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = folder.appendingPathComponent("foo.psd")
to = folder.appendingPathComponent("bar.psd")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

at = folder.appendingPathComponent("foo.tif")
to = folder.appendingPathComponent("bar.tif")
copyFileAppendKeywords(at: at, to: to, keywords: keywords)

0 个答案:

没有答案