首页 > 解决方案 > 使用 Core Graphics 使用 AppleScriptObjC 更改图像色彩空间配置文件

问题描述

我已经有一些代码可以使用 NSIMage 和 NSColorSpace 完成我需要的大部分工作。不幸的是,我正在尝试重新创建在 Photoshop 中发生的色彩空间/配置文件更改,它比 NSColorSpace 可以做的要复杂一些。您可以在此处看到该帖子: Using ApplescriptObjC to convert color spaces of an image using NSColorSpace and iccProfileData

所以我需要帮助的是要么从 CGColorSpace 添加以下内容,要么重新创建脚本的某些部分,以便它们从一开始就使用 Core Graphics。我希望完成的功能是: CGColorRenderingIntent using kCGRenderingIntentPerceptual kCGColorConversionBlackPointCompensation Plus 使用抖动作为颜色空间转换的一部分,但我似乎无法在 Apple Objective-C 文档中找到一个选项。NSColor 确实有 NSColorRenderingIntentPerceptual 但似乎在 NSColor 下没有 BlackPointCompensation。

我想我已经确定了构建这个脚本所需的所有部分。我认为剧本已经写到一半了。我只需要一些帮助将最后几位粘合在一起。

我相信脚本仍然需要将配置文件打开到 NSData (该文件是对我正在使用的 ICC 配置文件的 POSIX 文件引用)

set theData to current application's NSData's dataWithContentsOfFile:theFile

现在我需要打开图像,我希望无论使用 NSColor 还是 CGColor 都是一样的:

set theInput to (choose file with prompt "Choose RGB file")
set theOutput to (choose file name default name "Untitled.jpg")
set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:theInput
set imageRep to theImage's representations()'s objectAtIndex:0

这是我看到的最需要帮助的代码行。这实际上是使用 NSColorSpace 进行颜色转换的地方:

set targetSpace to current application's NSColorSpace's alloc's initWithICCProfileData:theData

似乎我应该将 CGColorSpaceCreateICCBased 与 CGDataProviderRef 和 theFile 一起使用,但我怀疑我是否可以将它们代替 NSColorSpace 和 initWithICCProfileData。我还需要使用 kCGRenderingIntentPerceptual 和 kCGColorConversionBlackPointCompensation 将 CGColorRenderingIntent 移植到这条线或新线(如果该选项甚至存在,则使用抖动)。

我不确定接下来的两行是否需要更新,但我很确定第三行可以保持不变(或者我真的很愚蠢,请原谅我)。

set theProps to current application's NSDictionary's dictionaryWithObjects:{1.0, true} forKeys:{current application's NSImageCompressionFactor, current application's NSImageProgressive}
set jpegData to bitmapRep's representationUsingType:(current application's NSJPEGFileType) |properties|:theProps
jpegData's writeToURL:theOutput atomically:true

因此,输入将是具有通用 sRGB 配置文件的 RGB,输出将是具有特定 CMYK 配置文件(确切地说是 GRACoL2013_CRPC6.icc)的 CMYK 文件。

标签: core-graphicsnsimageapplescript-objccgcolorspace

解决方案


输入将是具有通用 sRGB 配置文件的 RGB,输出将是具有特定 CMYK 配置文件的 CMYK 文件 ( GRACoL2013_CRPC6.icc)

如果这准确地概括了目标,您应该能够使用Image Events来做到这一点,这是一个 AppleScriptable 无面程序来处理图像。

使用Image Events,但嵌入一个新的颜色配置文件——这应该是可能的——似乎没有采取,原始的颜色配置文件仍然存在。

所以我写了 AppleScriptObjC 等价物:

use framework "Foundation"
use framework "AppKit"
use scripting additions

property this : a reference to the current application
property nil : a reference to missing value
property _1 : a reference to reference

property NSBitmapImageRep : a reference to NSBitmapImageRep of this
property NSColorSpace : a reference to NSColorSpace of this
property NSData : a reference to NSData of this
property NSImage : a reference to NSImage of this
property NSString : a reference to NSString of this
property NSURL : a reference to NSURL of this

property JPEG : a reference to 3
property PNG : a reference to 4
property NSFileType : {nil, nil, "jpg", "png"}
property options : {NSImageCompressionFactor:0.75, NSImageProgressive:true ¬
    , NSImageColorSyncProfileData:a reference to iccData}

property NSColorRenderingIntent : {Default:0, AbsoluteColorimetric:1 ¬
    , RelativeColorimetric:2, Perceptual:3, Saturation:4}
--------------------------------------------------------------------------------
# IMPLEMENTATION:
set iccProfile to loadICCProfile("~/Path/To/GRACoL2013_CRPC6.icc")
set image to _NSImage("~/Path/To/SourceImage.jpg")
set path of image to "~/Path/To/OutputImage.jpg" -- omit to overwrite source
set iccData to iccProfile's space's ICCProfileData()

my (write image for iccProfile given properties:contents of options)
--------------------------------------------------------------------------------
# HANDLERS & SCRIPT OBJECTS:
# __NSURL__()
#   Takes a posix +filepath and returns an NSURL object reference
to __NSURL__(filepath)
    local filepath

    try
        NSURL's fileURLWithPath:((NSString's ¬
            stringWithString:filepath)'s ¬
            stringByStandardizingPath())
    on error
        missing value
    end try
end __NSURL__

# new()
#   Instantiates a new NSObject
on new(_nsObject)
    local _nsObject
    _nsObject's alloc()
end new

# _NSImage()
#   Creates a new NSImage instance with image data loaded from the +filepath
on _NSImage(filepath)
    local filepath

    script
        property file : __NSURL__(filepath)
        property data : new(NSImage)
        property kind : JPEG
        property path : nil -- write path (nil = overwrite source)
        property size : nil
        property name extension : NSFileType's item kind

        to init()
            my (data's initWithContentsOfURL:(my file))
        end init

        to lock()
            tell my data to lockFocus()
        end lock

        to unlock()
            tell my data to unlockFocus()
        end unlock
    end script

    tell the result
        init()
        set its size to its data's |size|() as list
        return it
    end tell
end _NSImage

# ICCProfile()
#   Loads a ColorSync profile from the +filepath and creates a new NSColorSpace
#   instance 
to loadICCProfile(fp)
    local fp

    script
        property file : __NSURL__(fp)
        property data : NSData's dataWithContentsOfURL:(my file)
        property space : new(NSColorSpace)
        property mode : NSColorRenderingIntent's Perceptual

        to init()
            (my space)'s initWithICCProfileData:(my data)
        end init
    end script

    tell the result
        init()
        return it
    end tell
end loadICCProfile

# write
#   Writes out the +_NSImage data optionally converting it to a new colorspace
to write _NSImage for ICC : missing value ¬
    given properties:(opt as record) : missing value
    local _NSImage, ICC, kind, path, options


    set ImageRep to new(NSBitmapImageRep)

    _NSImage's lock()

    ImageRep's initWithFocusedViewRect:{{0, 0}, _NSImage's size}
    ImageRep's bitmapImageRepByConvertingToColorSpace:(ICC's space) ¬
        renderingIntent:(ICC's mode)
    result's representationUsingType:(_NSImage's kind) |properties|:opt
    set ImageRep to the result

    _NSImage's unlock()


    set fURL to __NSURL__(_NSImage's path)
    if fURL = missing value then set fURL to NSImage's file
    set ext to _NSImage's name extension
    if fURL's pathExtension() as text ≠ ext then ¬
        fURL's URLByDeletingPathExtension()'s ¬
        URLByAppendingPathExtension:ext

    ImageRep's writeToURL:fURL atomically:yes
    if the result = true then return fURL's |path|() as text
    false
end write
---------------------------------------------------------------------------❮END❯

kCGColorConversionBlackPointCompensation正如您所指出的,在转换色彩空间时,Core Graphics 似乎没有等效的 Foundation 类选项。因此,我可能没有为您提供任何您无法做到的脚本方面的内容。然而,我确实观察到,如果在从网站获取GRACoL颜色配置文件后尝试“按原样”使用它们,则会导致 AppleScript 引擎崩溃。无论出于何种原因,必须首先在ColorSync Utility.app中打开配置文件,然后保存(另存为...)或导出(导出...)。覆盖原始文件就可以了,之后AppleScript 就会出现使用它的内容。对于已保存在系统上的其他配置文件,这似乎不是问题。


推荐阅读