Как мне преобразовать UIColor в шестнадцатеричную строку 3/4/6/8 цифр в Swift? - PullRequest
0 голосов
/ 10 мая 2018

Как мне преобразовать UIColor в шестнадцатеричную строку из 3/4/6/8 цифр в Swift?

Как получить спецификацию? например, получить "# 0000FFFF", позвонив UIColor.blue.eightDigitsString

Пожалуйста, смотрите это :

5.2. Шестнадцатеричные обозначения RGB: # RRGGBB

В шестнадцатеричной цветовой нотации CSS можно указать цвет, задав каналы в виде шестнадцатеричных чисел, что аналогично тому, как цвета часто записываются непосредственно в компьютерном коде. Это также короче, чем запись того же цвета в нотации rgb ().

Синтаксис a представляет собой токен , значение которого состоит из 3, 4, 6 или 8 шестнадцатеричных цифр. Другими словами, шестнадцатеричный цвет записывается как хэш-символ «#», за которым следует некоторое количество цифр 0–9 или букв af (регистр букв не имеет значения - # 00ff00 идентичен # 00FF00).

Количество заданных шестнадцатеричных цифр определяет, как декодировать шестнадцатеричное представление в цвет RGB:

6 цифр
Первая пара цифр, интерпретируемая как шестнадцатеричное число, указывает красный канал цвета, где 00 представляет минимальное значение, а ff (255 в десятичном виде) представляет максимум. Следующая пара цифр, интерпретируемая таким же образом, обозначает зеленый канал, а последняя пара обозначает синий. Альфа-канал цвета полностью непрозрачен. Другими словами, # 00ff00 представляет тот же цвет, что и rgb (0 255 0) (зеленый лайм).

8 цифр
Первые 6 цифр интерпретируются идентично 6-значной записи. Последняя пара цифр, интерпретируемая как шестнадцатеричное число, указывает альфа-канал цвета, где 00 представляет полностью прозрачный цвет, а ff - полностью непрозрачный цвет. Другими словами, # 0000ffcc представляет тот же цвет, что и rgb (0 0 100% / 80%) (слегка прозрачный синий).

3 цифры
Это более короткий вариант 6-значного обозначения. Первая цифра, интерпретируемая как шестнадцатеричное число, указывает красный канал цвета, где 0 представляет минимальное значение, а f представляет максимум. Следующие две цифры представляют зеленый и синий каналы, соответственно, одинаково. Альфа-канал цвета полностью непрозрачен. Этот синтаксис часто объясняется тем, что он идентичен 6-значному обозначению, полученному путем «дублирования» всех цифр. Например, запись # 123 задает тот же цвет, что и запись # 112233. Этот метод определения цвета имеет более низкое «разрешение», чем 6-значная запись; в трехзначном шестнадцатеричном синтаксисе можно выразить только 4096 возможных цветов, в отличие от примерно 17 миллионов в шестнадцатеричном шестнадцатеричном синтаксисе.

4 цифры
Это более короткий вариант 8-значного обозначения, «расширенный» так же, как и 3-значное обозначение. Первая цифра, интерпретируемая как шестнадцатеричное число, указывает красный канал цвета, где 0 представляет минимальное значение, а f представляет максимум. Следующие три цифры обозначают зеленый, синий и альфа-канал соответственно.

Теперь я уже знаю, как преобразовать объект UIColor в шестизначную шестнадцатеричную строку. Но я не уверен, как преобразовать его в шестнадцатеричную / 4-значную / 8-значную шестнадцатеричную строку и что следует заметить.

guard let components = cgColor.components, components.count >= 3 else {
    return nil
}
let r = Float(components[0])
let g = Float(components[1])
let b = Float(components[2])
var a = Float(1.0)
if components.count >= 4 {
    a = Float(components[3])
}
if alpha {
    // rrggbbaa mode
    // is there any difference between rrggbbaa and aarrggbb?
    return String(format: "%02lX%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255), lroundf(a * 255))
} else {
    // rrggbb mode
    return String(format: "%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255))
}

ПРИМЕЧАНИЕ: UIColor в строку, а не в UIColor

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Любой экземпляр UIColor может быть представлен 8 шестнадцатеричными цифрами: например, #336699CC. Для некоторых цветов может использоваться более короткое представление:

  • для непрозрачных цветов (не определено альфа или 1,0), альфа-компонент можно отключить: #336699FF становится #336699
  • если все компоненты цвета состоят из пар одной и той же цифры, цифру необходимо указывать только один раз: #336699CC становится #369C, но #335799CC не может быть сокращено
  • два вышеуказанных правила можно объединить: #336699FF становится #369

Следующая функция вернет самое короткое допустимое представление, допустимое для данного UIColor.

struct HexRepresentationOptions: OptionSet {
    let rawValue: UInt

    static let allowImplicitAlpha = HexRepresentationOptions(rawValue: 1 << 0)
    static let allowShortForm = HexRepresentationOptions(rawValue: 1 << 1)

    static let allowAll: HexRepresentationOptions = [
        .allowImplicitAlpha, 
        .allowShortForm
    ]
}

func hexRepresentation(forColor color: UIColor, 
                       options: HexRepresentationOptions = .allowAll) -> String? {
    var red: CGFloat = 0.0
    var green: CGFloat = 0.0
    var blue: CGFloat = 0.0
    var alpha: CGFloat = 0.0

    guard color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
        return nil
    }

    let colorComponents: [CGFloat]
    if options.contains(.allowImplicitAlpha) && alpha == 1.0 {
        colorComponents = [red, green, blue]
    } else {
        colorComponents = [red, green, blue, alpha]
    }

    let hexComponents = colorComponents.map { component -> (UInt8, UInt8, UInt8) in
        let hex = UInt8(component * 0xFF)
        return (hex, hex & 0x0F, hex >> 4)
    }

    let hasAlpha = colorComponents.count == 4
    let useShortForm = options.contains(.allowShortForm) && 
        !hexComponents.contains(where: { c in c.1 != c.2 })

    let hexColor: UInt64 = hexComponents.reduce(UInt64(0)) { result, component in
        if useShortForm {
            return (result << 4) | UInt64(component.1)
        } else {
            return (result << 8) | UInt64(component.0)
        }
    }

    switch (useShortForm, hasAlpha) {
    case (true, false):
        return String(format: "#%03X", hexColor)
    case (true, true):
        return String(format: "#%04X", hexColor)
    case (false, false):
        return String(format: "#%06X", hexColor)
    case (false, true):
        return String(format: "#%08X", hexColor)
    }
}
0 голосов
/ 10 мая 2018

Вот расширение для UIColor, которое может предоставлять hexStrings во многих форматах, включая 3, 4, 6 и 8-значные формы:

extension UIColor {
    enum HexFormat {
        case RGB
        case ARGB
        case RGBA
        case RRGGBB
        case AARRGGBB
        case RRGGBBAA
    }

    enum HexDigits {
        case d3, d4, d6, d8
    }

    func hexString(_ format: HexFormat = .RRGGBBAA) -> String {
        let maxi = [.RGB, .ARGB, .RGBA].contains(format) ? 16 : 256

        func toI(_ f: CGFloat) -> Int {
            return min(maxi - 1, Int(CGFloat(maxi) * f))
        }

        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0

        self.getRed(&r, green: &g, blue: &b, alpha: &a)

        let ri = toI(r)
        let gi = toI(g)
        let bi = toI(b)
        let ai = toI(a)

        switch format {
        case .RGB:       return String(format: "#%X%X%X", ri, gi, bi)
        case .ARGB:      return String(format: "#%X%X%X%X", ai, ri, gi, bi)
        case .RGBA:      return String(format: "#%X%X%X%X", ri, gi, bi, ai)
        case .RRGGBB:    return String(format: "#%02X%02X%02X", ri, gi, bi)
        case .AARRGGBB:  return String(format: "#%02X%02X%02X%02X", ai, ri, gi, bi)
        case .RRGGBBAA:  return String(format: "#%02X%02X%02X%02X", ri, gi, bi, ai)
        }
    }

    func hexString(_ digits: HexDigits) -> String {
        switch digits {
        case .d3: return hexString(.RGB)
        case .d4: return hexString(.RGBA)
        case .d6: return hexString(.RRGGBB)
        case .d8: return hexString(.RRGGBBAA)
        }
    }
}

Примеры

print(UIColor.red.hexString(.d3))  // #F00
print(UIColor.red.hexString(.d4))  // #F00F
print(UIColor.red.hexString(.d6))  // #FF0000
print(UIColor.red.hexString(.d8))  // #FF0000FF

print(UIColor.green.hexString(.RGB))  // #0F0
print(UIColor.green.hexString(.ARGB))  // #F0F0
print(UIColor.green.hexString(.RGBA))  // #0F0F
print(UIColor.green.hexString(.RRGGBB))  // #00FF00
print(UIColor.green.hexString(.AARRGGBB))  // #FF00FF00
print(UIColor.green.hexString(.RRGGBBAA))  // #00FF00FF

print(UIColor(red: 0.25, green: 0.5, blue: 0.75, alpha: 0.3333).hexString()) // #4080c055
...