计算互补色、三元色、四元色和类似色
Computing complementary, triadic, tetradic, and analagous colors
我创建了 swift 函数,我将颜色值发送到 return 三元和四元值。它有点工作,但我对颜色结果不满意。任何人都可以帮我微调公式吗?
我关注的资源不多,但是 returned 的颜色与几个基于 Web 的在线配色方案相比太亮或太饱和。我知道这也是一个偏好问题,我有点喜欢下面代码的结果,但在某些颜色实例中,一种颜色 returned 的结果与原始颜色太接近了,所以它几乎不可见.它仅适用于几种颜色...
我使用的是这里的公式:
我的代码:
func getTriadColor(color: UIColor) -> (UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let triadHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let triadColor1 = UIColor(hue: (triadHue + 0.33) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let triadColor2 = UIColor(hue: (triadHue + 0.66) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (triadColor1, triadColor2)
}
func getTetradColor(color: UIColor) -> (UIColor, UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let tetradHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let tetradColor1 = UIColor(hue: (tetradHue + 0.25) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor2 = UIColor(hue: (tetradHue + 0.5) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor3 = UIColor(hue: (tetradHue + 0.75) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (tetradColor1, tetradColor2, tetradColor3)
}
而且我还找到了用于查找互补色的简洁代码,我对结果非常满意
func getComplementColor(color: UIColor) -> UIColor{
let ciColor = CIColor(color: color)
let compRed: CGFloat = 1.0 - ciColor.red
let compGreen: CGFloat = 1.0 - ciColor.green
let compBlue: CGFloat = 1.0 - ciColor.blue
return UIColor(red: compRed, green: compGreen, blue: compBlue, alpha: 1.0)
}
您的屏幕截图是 this web page。该页面上的公式(在 4 年后的这次编辑中仍然)不正确,因为它们指定使用绝对值函数而不是 modulo 函数。也就是说,例如,您的屏幕截图定义
H1 = |(H0 + 180°) - 360°|
但考虑一下这给出的输入 H0 = 90°:
H1 = |(90° + 180°) - 360°| = |270° - 360°| = |-90°| = 90°
你觉得H0 = 90°的补色是H1 = 90°,同一个色相吗?
正确的公式是
H1 = (H0 + 180°) mod 360°
其中“mod”是“modulo”的缩写,意思是“除以后的余数”。换句话说,如果答案高于 360°,则减去 360°。对于 H0 = 90°,这给出了 H1 = 270°.
的正确答案
但是你的代码中甚至没有这个问题,因为你的代码中没有使用绝对值函数(或者modulo函数)。由于您没有采取任何措施将色调值保持在 0…1 范围内,因此小于零的色调值被裁剪为零,高于 1 的色调值被裁剪为 1(零和 1 均表示红色).
你的getComplementColor
也完全不是“补色”的标准定义
正确的定义如下:
extension UIColor {
var complement: UIColor {
return self.withHueOffset(0.5)
}
var splitComplement0: UIColor {
return self.withHueOffset(150 / 360)
}
var splitComplement1: UIColor {
return self.withHueOffset(210 / 360)
}
var triadic0: UIColor {
return self.withHueOffset(120 / 360)
}
var triadic1: UIColor {
return self.withHueOffset(240 / 360)
}
var tetradic0: UIColor {
return self.withHueOffset(0.25)
}
var tetradic1: UIColor {
return self.complement
}
var tetradic2: UIColor {
return self.withHueOffset(0.75)
}
var analagous0: UIColor {
return self.withHueOffset(-1 / 12)
}
var analagous1: UIColor {
return self.withHueOffset(1 / 12)
}
func withHueOffset(offset: CGFloat) -> UIColor {
var h: CGFloat = 0
var s: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
self.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return UIColor(hue: fmod(h + offset, 1), saturation: s, brightness: b, alpha: a)
}
}
这里有一些互补色的例子(原色在上,互补色在下):
这里是分开的补色(原件在上面):
这里是三元色(原件在上):
以下是四色(原件在上):
下面是类似的颜色(原来在中间):
这是我用来生成这些图像的 playground:
import XCPlayground
import UIKit
let view = UIView(frame: CGRectMake(0, 0, 320, 480))
view.backgroundColor = [#Color(colorLiteralRed: 0.9607843137254902, green: 0.9607843137254902, blue: 0.9607843137254902, alpha: 1)#]
let vStack = UIStackView(frame: view.bounds)
vStack.autoresizingMask = [ .FlexibleWidth, .FlexibleHeight ]
view.addSubview(vStack)
vStack.axis = .Vertical
vStack.distribution = .FillEqually
vStack.alignment = .Fill
vStack.spacing = 10
typealias ColorTransform = (UIColor) -> UIColor
func tile(color color: UIColor) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = color
return view
}
func strip(transforms: [ColorTransform]) -> UIStackView {
let strip = UIStackView()
strip.translatesAutoresizingMaskIntoConstraints = false
strip.axis = .Vertical
strip.distribution = .FillEqually
strip.alignment = .Fill
strip.spacing = 0
let hStacks = (0 ..< transforms.count).map { (i: Int) -> UIStackView in
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .Horizontal
stack.distribution = .FillEqually
stack.alignment = .Fill
stack.spacing = 4
strip.addArrangedSubview(stack)
return stack
}
for h in 0 ..< 10 {
let hue = CGFloat(h) / 10
let color = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1)
for (i, transform) in transforms.enumerate() {
hStacks[i].addArrangedSubview(tile(color: transform(color)))
}
}
return strip
}
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].complement }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].splitComplement0 },
{ [=11=].splitComplement1 }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].triadic0 },
{ [=11=].triadic1 }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].tetradic0 },
{ [=11=].tetradic1 },
{ [=11=].tetradic2 }]))
vStack.addArrangedSubview(strip([
{ [=11=].analagous0 },
{ [=11=] },
{ [=11=].analagous1 }]))
XCPlaygroundPage.currentPage.liveView = view
我创建了 swift 函数,我将颜色值发送到 return 三元和四元值。它有点工作,但我对颜色结果不满意。任何人都可以帮我微调公式吗?
我关注的资源不多,但是 returned 的颜色与几个基于 Web 的在线配色方案相比太亮或太饱和。我知道这也是一个偏好问题,我有点喜欢下面代码的结果,但在某些颜色实例中,一种颜色 returned 的结果与原始颜色太接近了,所以它几乎不可见.它仅适用于几种颜色...
我使用的是这里的公式:
我的代码:
func getTriadColor(color: UIColor) -> (UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let triadHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let triadColor1 = UIColor(hue: (triadHue + 0.33) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let triadColor2 = UIColor(hue: (triadHue + 0.66) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (triadColor1, triadColor2)
}
func getTetradColor(color: UIColor) -> (UIColor, UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let tetradHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let tetradColor1 = UIColor(hue: (tetradHue + 0.25) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor2 = UIColor(hue: (tetradHue + 0.5) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor3 = UIColor(hue: (tetradHue + 0.75) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (tetradColor1, tetradColor2, tetradColor3)
}
而且我还找到了用于查找互补色的简洁代码,我对结果非常满意
func getComplementColor(color: UIColor) -> UIColor{
let ciColor = CIColor(color: color)
let compRed: CGFloat = 1.0 - ciColor.red
let compGreen: CGFloat = 1.0 - ciColor.green
let compBlue: CGFloat = 1.0 - ciColor.blue
return UIColor(red: compRed, green: compGreen, blue: compBlue, alpha: 1.0)
}
您的屏幕截图是 this web page。该页面上的公式(在 4 年后的这次编辑中仍然)不正确,因为它们指定使用绝对值函数而不是 modulo 函数。也就是说,例如,您的屏幕截图定义
H1 = |(H0 + 180°) - 360°|
但考虑一下这给出的输入 H0 = 90°:
H1 = |(90° + 180°) - 360°| = |270° - 360°| = |-90°| = 90°
你觉得H0 = 90°的补色是H1 = 90°,同一个色相吗?
正确的公式是
H1 = (H0 + 180°) mod 360°
其中“mod”是“modulo”的缩写,意思是“除以后的余数”。换句话说,如果答案高于 360°,则减去 360°。对于 H0 = 90°,这给出了 H1 = 270°.
的正确答案但是你的代码中甚至没有这个问题,因为你的代码中没有使用绝对值函数(或者modulo函数)。由于您没有采取任何措施将色调值保持在 0…1 范围内,因此小于零的色调值被裁剪为零,高于 1 的色调值被裁剪为 1(零和 1 均表示红色).
你的getComplementColor
也完全不是“补色”的标准定义
正确的定义如下:
extension UIColor {
var complement: UIColor {
return self.withHueOffset(0.5)
}
var splitComplement0: UIColor {
return self.withHueOffset(150 / 360)
}
var splitComplement1: UIColor {
return self.withHueOffset(210 / 360)
}
var triadic0: UIColor {
return self.withHueOffset(120 / 360)
}
var triadic1: UIColor {
return self.withHueOffset(240 / 360)
}
var tetradic0: UIColor {
return self.withHueOffset(0.25)
}
var tetradic1: UIColor {
return self.complement
}
var tetradic2: UIColor {
return self.withHueOffset(0.75)
}
var analagous0: UIColor {
return self.withHueOffset(-1 / 12)
}
var analagous1: UIColor {
return self.withHueOffset(1 / 12)
}
func withHueOffset(offset: CGFloat) -> UIColor {
var h: CGFloat = 0
var s: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
self.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return UIColor(hue: fmod(h + offset, 1), saturation: s, brightness: b, alpha: a)
}
}
这里有一些互补色的例子(原色在上,互补色在下):
这里是分开的补色(原件在上面):
这里是三元色(原件在上):
以下是四色(原件在上):
下面是类似的颜色(原来在中间):
这是我用来生成这些图像的 playground:
import XCPlayground
import UIKit
let view = UIView(frame: CGRectMake(0, 0, 320, 480))
view.backgroundColor = [#Color(colorLiteralRed: 0.9607843137254902, green: 0.9607843137254902, blue: 0.9607843137254902, alpha: 1)#]
let vStack = UIStackView(frame: view.bounds)
vStack.autoresizingMask = [ .FlexibleWidth, .FlexibleHeight ]
view.addSubview(vStack)
vStack.axis = .Vertical
vStack.distribution = .FillEqually
vStack.alignment = .Fill
vStack.spacing = 10
typealias ColorTransform = (UIColor) -> UIColor
func tile(color color: UIColor) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = color
return view
}
func strip(transforms: [ColorTransform]) -> UIStackView {
let strip = UIStackView()
strip.translatesAutoresizingMaskIntoConstraints = false
strip.axis = .Vertical
strip.distribution = .FillEqually
strip.alignment = .Fill
strip.spacing = 0
let hStacks = (0 ..< transforms.count).map { (i: Int) -> UIStackView in
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .Horizontal
stack.distribution = .FillEqually
stack.alignment = .Fill
stack.spacing = 4
strip.addArrangedSubview(stack)
return stack
}
for h in 0 ..< 10 {
let hue = CGFloat(h) / 10
let color = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1)
for (i, transform) in transforms.enumerate() {
hStacks[i].addArrangedSubview(tile(color: transform(color)))
}
}
return strip
}
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].complement }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].splitComplement0 },
{ [=11=].splitComplement1 }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].triadic0 },
{ [=11=].triadic1 }]))
vStack.addArrangedSubview(strip([
{ [=11=] },
{ [=11=].tetradic0 },
{ [=11=].tetradic1 },
{ [=11=].tetradic2 }]))
vStack.addArrangedSubview(strip([
{ [=11=].analagous0 },
{ [=11=] },
{ [=11=].analagous1 }]))
XCPlaygroundPage.currentPage.liveView = view