Изменить цвет RGB на HSV Swift - PullRequest
0 голосов
/ 11 июня 2019

Хорошего дня.Я делаю RGB LED приложение для изменения цвета.Я делаю выбор цвета с HSB.Эти цвета имеют оттенки, насыщенность, яркость и альфа-значения.Я сохраняю эти значения в базе данных.Я читаю эти данные с Arduino.Но как мне узнать, к какому цвету относятся эти значения цвета?Так как мне найти эквивалент цвета, который я выбрал через Arduino?

import Foundation
import UIKit

// The view to edit HSB color components.
public class EFHSBView: UIView, EFColorView, UITextFieldDelegate {

    let EFColorSampleViewHeight: CGFloat = 30.0
    let EFViewMargin: CGFloat = 20.0
    let EFColorWheelDimension: CGFloat = 200.0

    private let colorWheel: EFColorWheelView = EFColorWheelView()
    let brightnessView: EFColorComponentView = EFColorComponentView()
    private let colorSample: UIView = UIView()

    private var colorComponents: HSB = HSB(1, 1, 1, 1)
    private var layoutConstraints: [NSLayoutConstraint] = []

    weak public var delegate: EFColorViewDelegate?

    public var isTouched: Bool {
        if self.colorWheel.isTouched {
            return true
        }

        if self.brightnessView.isTouched {
            return true
        }

        return false
    }

    public var color: UIColor {
        get {
            return UIColor(
                hue: colorComponents.hue,
                saturation: colorComponents.saturation,
                brightness: colorComponents.brightness,
                alpha: colorComponents.alpha
            )
        }
        set {

            colorComponents = EFRGB2HSB(rgb: EFRGBColorComponents(color: newValue))
            self.reloadData()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.ef_baseInit()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.ef_baseInit()
    }

    func reloadData() {
        colorSample.backgroundColor = self.color
        colorSample.accessibilityValue = EFHexStringFromColor(color: self.color)
        self.ef_reloadViewsWithColorComponents(colorComponents: colorComponents)
        self.colorWheel.display(self.colorWheel.layer)
    }

    override public func updateConstraints() {
        self.ef_updateConstraints()
        super.updateConstraints()
    }

    // MARK:- Private methods
    private func ef_baseInit() {
        self.accessibilityLabel = "hsb_view"

        colorSample.accessibilityLabel = "color_sample"
        colorSample.layer.borderColor = UIColor.black.cgColor
        colorSample.layer.borderWidth = 0.5
        colorSample.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(colorSample)

        colorWheel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(colorWheel)

        brightnessView.title = NSLocalizedString("Brightness", comment: "")
        brightnessView.maximumValue = EFHSBColorComponentMaxValue
        brightnessView.format = "%.2f"
        brightnessView.translatesAutoresizingMaskIntoConstraints = false
        brightnessView.setColors(colors: [UIColor.black, UIColor.white])
        self.addSubview(brightnessView)

        colorWheel.addTarget(
            self, action: #selector(ef_colorDidChangeValue(sender:)), for: UIControl.Event.valueChanged
        )
        brightnessView.addTarget(
            self, action: #selector(ef_brightnessDidChangeValue(sender:)), for: UIControl.Event.valueChanged
        )

        self.setNeedsUpdateConstraints()
    }

    private func ef_updateConstraints() {
        // remove all constraints first
        if !layoutConstraints.isEmpty {
            self.removeConstraints(layoutConstraints)
        }

        layoutConstraints = UIUserInterfaceSizeClass.compact == self.traitCollection.verticalSizeClass
            ? self.ef_constraintsForCompactVerticalSizeClass()
            : self.ef_constraintsForRegularVerticalSizeClass()

        self.addConstraints(layoutConstraints)
    }

    private func ef_constraintsForRegularVerticalSizeClass() -> [NSLayoutConstraint] {
        let metrics = [
            "margin" : EFViewMargin,
            "height" : EFColorSampleViewHeight,
            "color_wheel_dimension" : EFColorWheelDimension
        ]
        let views = [
            "colorSample" : colorSample,
            "colorWheel" : colorWheel,
            "brightnessView" : brightnessView
        ]

        var layoutConstraints: [NSLayoutConstraint] = []
        let visualFormats = [
            "H:|-margin-[colorSample]-margin-|",
            "H:|-margin-[colorWheel(>=color_wheel_dimension)]-margin-|",
            "H:|-margin-[brightnessView]-margin-|",
            "V:|-margin-[colorSample(height)]-margin-[colorWheel]-margin-[brightnessView]-(>=margin@250)-|"
        ]
        for visualFormat in visualFormats {
            layoutConstraints.append(
                contentsOf: NSLayoutConstraint.constraints(
                    withVisualFormat: visualFormat,
                    options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                    metrics: metrics,
                    views: views
                )
            )
        }
        layoutConstraints.append(
            NSLayoutConstraint(
                item: colorWheel,
                attribute: NSLayoutConstraint.Attribute.width,
                relatedBy: NSLayoutConstraint.Relation.equal,
                toItem: colorWheel,
                attribute: NSLayoutConstraint.Attribute.height,
                multiplier: 1,
                constant: 0)
        )
        return layoutConstraints
    }

    private func ef_constraintsForCompactVerticalSizeClass() -> [NSLayoutConstraint] {
        let metrics = [
            "margin" : EFViewMargin,
            "height" : EFColorSampleViewHeight,
            "color_wheel_dimension" : EFColorWheelDimension
        ]
        let views = [
            "colorSample" : colorSample,
            "colorWheel" : colorWheel,
            "brightnessView" : brightnessView
        ]

        var layoutConstraints: [NSLayoutConstraint] = []
        let visualFormats = [
            "H:|-margin-[colorSample]-margin-|",
            "H:|-margin-[colorWheel(>=color_wheel_dimension)]-margin-[brightnessView]-(margin@500)-|",
            "V:|-margin-[colorSample(height)]-margin-[colorWheel]-(margin@500)-|"
        ]
        for visualFormat in visualFormats {
            layoutConstraints.append(
                contentsOf: NSLayoutConstraint.constraints(
                    withVisualFormat: visualFormat,
                    options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                    metrics: metrics,
                    views: views
                )
            )
        }
        layoutConstraints.append(
            NSLayoutConstraint(
                item: colorWheel,
                attribute: NSLayoutConstraint.Attribute.width,
                relatedBy: NSLayoutConstraint.Relation.equal,
                toItem: colorWheel,
                attribute: NSLayoutConstraint.Attribute.height,
                multiplier: 1,
                constant: 0)
        )
        layoutConstraints.append(
            NSLayoutConstraint(
                item: brightnessView,
                attribute: NSLayoutConstraint.Attribute.centerY,
                relatedBy: NSLayoutConstraint.Relation.equal,
                toItem: self,
                attribute: NSLayoutConstraint.Attribute.centerY,
                multiplier: 1,
                constant: 0)
        )
        return layoutConstraints
    }

    private func ef_reloadViewsWithColorComponents(colorComponents: HSB) {
        colorWheel.hue = colorComponents.hue
        colorWheel.saturation = colorComponents.saturation
        colorWheel.brightness = colorComponents.brightness
        self.ef_updateSlidersWithColorComponents(colorComponents: colorComponents)
    }

    private func ef_updateSlidersWithColorComponents(colorComponents: HSB) {
        brightnessView.value = colorComponents.brightness
    }

    @objc private func ef_colorDidChangeValue(sender: EFColorWheelView) {
        colorComponents.hue = sender.hue
        colorComponents.saturation = sender.saturation
        self.delegate?.colorView(self, didChangeColor: self.color)
        self.reloadData()
    }

    @objc private func ef_brightnessDidChangeValue(sender: EFColorComponentView) {
        colorComponents.brightness = sender.value
        self.colorWheel.brightness = sender.value
        self.delegate?.colorView(self, didChangeColor: self.color)
        self.reloadData()
    }
}

1 Ответ

0 голосов
/ 11 июня 2019

Модель Hue-Saturation-Value - широко используемый метод кодирования цветов.

Hue - циклический параметр, поэтому он кодируется в градусах (360 градусов = полный цикл),красный, зеленый и синий компоненты цвета периодически меняются вдоль оси HUE, находясь при их нижнем значении в течение 120 градусов, затем повышаясь до верхнего значения в течение 60 градусов, остается 120 градусов при верхнем значении и затем снова уменьшается в течение следующих 60 градусов.Цикл повторяется после 360 градусов.

HSV model

Компоненты Red Green и Blue смещены относительно друг друга на 120 градусов, что позволяет кодировать любую пропорцию между ними.

На рисунке выше вы видите, что для каждого значения H один из компонентов RGB имеет верхнее значение, другой - более низкое, а третий изменяется между ними.

Значение Компонент кодирует верхнее значение RGB.Т.е. значение 0% соответствует черному цвету (какими бы ни были значения оттенка и насыщенности), а 100% - самым ярким цветом

Компонент Насыщенность модели HSV кодирует разницу между верхним и нижним значениямикомпонентов RGB, относительно значения V .Т.е. если значение равно 50%, а насыщенность равна 30%, то нижнее значение будет 35%, а верхнее значение будет 50%.

Если насыщенность равна нулю, то цвет серый, независимо от значения оттенка.

Таким образом, код для преобразования HSV в RGB может быть следующим:

float h = ..., s = ..., v = ...; // input values

float r, g, b;

float d = v * s; // difference between upper and lower value
float l = v - d; // calculating the lower value

// code below assumes 0 <= h < 360. Otherwise wrap the value before
if (h < 60) { // 0..60
  r = v;
  g = l + (h / 60.0) * d;
  b = l;
} else if (h < 120) {  // 60..120
  r = u - ((h - 60) / 60.0) * d;
  g = v;
  b = l;
} else if (h < 180) {  // 120..180
  r = l;
  g = v;
  b = l + ((h - 120) / 60.0) * d;
} else if (h < 240) {  // 180..240
  r = l;
  g = u - ((h - 180) / 60.0) * d;
  b = v;
} else if (h < 300) {  // 240..300
  r = l + ((h - 240) / 60.0) * d;
  g = l;
  b = v;
} else { // 300..360
  r = v;
  g = l;
  b = u - ((h - 300) / 60.0) * d;
}

Подробнее в Википедии

Обратите внимание, когда загораются светодиоды RGB сMCU, вы можете получить не тот цвет, который вы видите на дисплее.Это связано с тем, что на дисплеях используется гамма-коррекция , то есть 50% не означает 50% свечения (обычно оно ближе к 25%).Таким образом, вам может потребоваться применить ту же гамма-коррекцию к полученным значениям RGB, прежде чем передавать их на светодиодный ШИМ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...