【问题标题】:Proper way to convert CGColors between colorspaces在色彩空间之间转换 CGColors 的正确方法
【发布时间】:2012-08-16 15:36:28
【问题描述】:

关于在 Apple 平台上的色彩空间之间转换颜色有几个问题。不幸的是,答案经常涉及NSColorUIColor——不可移植的Objective-C 类,不能在OS X 和iOS 上互换使用。

所以我想问一个非常具体的问题,我确定肯定有一个很好的答案。我简直不敢相信 Apple 不会预见到这种需求。

如何以通用方式将CGColor 从一种颜色空间(例如单色)转换为另一种颜色空间(例如RGB),支持所有CGColorSpace 类型,同时仅使用可移植的Core Graphics 功能?


一些上下文。我需要将在线服务提供的值与存储在UIColor 中的值相乘。在iOS5之前,终于引入了-[UIColor getRed:green:blue:alpha:]的方法,提取RGB分量的正确方法是使用CGColorGetComponents()。然后我将此颜色与从在线服务获取的颜色相乘。如果使用+[UIColor grayColor] 生成UIColor,则此操作失败。意思是,我需要将颜色从灰度颜色空间转换为 RGB。在这种情况下,这很容易。提供其他一些色彩空间呢?或者如果在理论上的未来场景中我只想处理单个像素的颜色怎么办?

有一个建议是我将一个像素绘制到位图上下文中,然后读取这个像素。这太疯狂了,我希望这不是唯一的方法。显然绘图方法可以弄清楚如何进行转换;我们如何在不创建位图上下文仅在其中绘制像素的情况下利用这一点?


补充研究:

  • This article 关于颜色转换,除了UIColor 的无证/私有方法-styleString,更有趣的是还提到了无证CGColorTransforms。
  • ColorCG.cpp from WebKit 表明有一个名为 CoreGraphics/CGColorTransform.h 的标头。不幸的是,这个标题不存在,至少在 Mountain Lion 上不存在。为什么 Apple 会隐藏这些 API?
  • 我发现提到 CGColorTransforms 的唯一其他合理资源是 FreeQuartz,它是 Core Graphics 的免费/开源重新实现。

向 Apple 提交了雷达 #12141580,以打开并记录 CGColorTransform。不过,我并没有屏住呼吸,所以如果有其他明智的建议,我会全神贯注。

【问题讨论】:

  • 多年来我一直在使用 vImage(加速)或位图上下文来执行此操作。对您所建议的此类实用程序的需求很低 - 苹果为什么要投入时间和精力来做这些?给定 RGB 格式的像素,您可以使用易于在线查找的 C 代码转换为其他空间,处理数据,然后再转换回 RGB。
  • @DavidH:你的论点很愚蠢。那苹果为什么要提供-[NSString pathExtension]呢?人们乐于使用其他语言的子字符串。如果需求这么低,苹果为什么要加-[UIColor getRed:green:blue:alpha:]?你谈到能源——如果苹果可以的话,为什么成千上万的开发人员会投入精力来重新发明轮子一千次?我理解你的观点,但我礼貌地不同意它,因为我相信可以在不创建上下文或 NSImage/CGImage 的情况下完成某些事情。使用 vImage 听起来很有趣,愿意发布一个示例作为答案吗?
  • 发泄不满的正确方法是在 bug report.apple.com 上输入增强错误。在过去的 8 年里,我已经进入了 300 左右。或者,你可以选择做一个不错的开源项目来做这个,放到github上(我有几个这样的项目),通过它获得名利!
  • @DavidH:呵呵——过去三年我只提交了大约 10 个文件,只有两个被关闭。是的,我对 Apple 缺乏转换色彩空间的简单可见方法感到沮丧 :-) 但我感谢您对这个问题的关注(尽管您没有提供确切的答案以及您最初的建议,即我正在询问存在“低需求”(即不必要的)功能)。创建一个开源项目也没有发现 Apple 是如何做到这一点并期望我们做到这一点那么有趣的。另外,我对颜色配置文件一无所知,所以我几乎不是合适的人选。 :-)

标签: ios macos colors core-graphics cgcolorspace


【解决方案1】:

Apple 在 iOS 9 和 macOS 10.11 中添加了此 API:

  • 对象:CGColorCreateCopyByMatchingToColorSpace
  • 斯威夫特:CGColor.converted(to:intent:options:)

【讨论】:

    【解决方案2】:

    Apple 对 rdar #12141580 的官方回应,我要求公开CGColorTransform

    非常感谢您的反馈。

    工程部门已确定该行为不会基于 关于以下信息:

    使用 ColorSync。

    如果您对此问题的解决有任何疑问,请 使用该信息更新您的错误报告。

    我们现在关闭此错误报告。

    请务必定期检查新的 Apple 版本是否有任何更新 这可能会影响这个问题。

    撰写该回复的人显然感到有必要详细解释该决定。尤其是建议使用高度复杂的 API(如 ColorSync)的决定。

    【讨论】:

      【解决方案3】:

      问题明确表示他们希望避免在仅为转换颜色而创建的位图上下文上绘图,但我没有意识到并想出了这个。

      我将把它作为任何可能偶然发现这个问题并想知道如何通过在临时位图上绘制来进行转换的人的参考

      CGColorRef source;
      CGColorSpaceRef targetColorSpace;
      int components = CGColorSpaceGetNumberOfComponents(targetColorSpace);
      CGFloat temp-buffer[components];
      CGContextRef temp-bmp = CGBitmapContextCreate(
          temp-buffer,
          1,1,8 * sizeof(CGFloat),components,
          targetColorSpace,
          kCGBitmapFloatComponents );
      CGContextSetFillColorWithColor(temp-bmp,source);
      CGContextFillRect(temp-bmp,CGRectMake(0,0,1,1));
      CGColor target = CGColorCreate(targetColorSpace,temp-buffer);
      
      /* then you cleanup and destroy created objects */
      

      我没有尝试此代码,它可能需要一些修复。

      【讨论】:

      • 这种方法适用于其他看到帖子主题并希望得到答案的人。但是,在 OP 中指定这已经是 a) 已知解决方案和 b) 特别是 OP(和我自己 - 赏金投资者)希望避免的程序。来自 OP:“我们如何在不创建位图上下文仅在其中绘制像素的情况下利用它?”。该插图对其他人来说会派上用场 - 所以尽管它是 Ivan 和我希望避免的解决方案,但请随意留下它。
      • 对不起,我没有读到。我只读到需要一种可移植的解决方案,并且不需要有关色彩空间的知识。
      猜你喜欢
      • 1970-01-01
      • 2019-11-28
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      相关资源
      最近更新 更多