LED灯控制

357 阅读3分钟

前言

最近做了一个调节LED灯的demo, 实现的效果是发送给云端的是R,G,B这三个值, App页面上显示值是HSB. UI要实现如下效果:

led灯效果图.png

RGB和HSB

RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。 HSB又称HSV,表示一种颜色模式:在HSB模式中,H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度HSB模式对应的媒介是人眼。 HSB模式中S和B呈现的数值越高,饱和度明度越高,页面色彩强烈艳丽,对视觉刺激是迅速的,醒目的效果,但不益于长时间的观看。 色相(H,hue):在0~360°的标准色轮上,色相是按位置度量的。在通常的使用中,色相是由颜色名称标识的,比如红、绿或橙色。黑色和白色无色相。 饱和度(S,saturation):表示色彩的纯度,为0时为灰色。白、黑和其他灰色色彩都没有饱和度的。在最大饱和度时,每一色相具有最纯的色光。取值范围0~100%。 亮度(B,brightness或V,value):是色彩的明亮度。为0时即为黑色。最大亮度是色彩最鲜明的状态。取值范围0~100%。

网上有很多rgb互转hsb的算法,我最先开始也是网上找的方法, 后来在实际设备中测试后发现rgb互转hsb出来的值不一致, 网上的方法还是需要再次验证, 慎用.

后来发现UIColor中有相应的方法:

    func rgbTohsb(r: Float, g: Float, b: Float) ->(Array<Float>) {
        let rgbColor = UIColor(red: CGFloat(r/255.0), green: CGFloat(g/255.0), blue: CGFloat(b/255.0), alpha: 1.0)
        var hue: CGFloat = 0
        var saturation: CGFloat = 0
        var brightness: CGFloat = 0
        rgbColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil)
        return [Float(hue * 360), Float(saturation * 100), Float(brightness * 100)]
    }

    func hsbTorgb(h: Float, s: Float, b: Float) ->(Array<Float>) {
        let hsbColor = UIColor(hue: CGFloat(h/360.0), saturation: CGFloat(s/100), brightness: CGFloat(b/100), alpha: 1.0)
        var red:   CGFloat = 0
        var green: CGFloat = 0
        var blue:  CGFloat = 0
        var alpha: CGFloat = 0
        hsbColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        red *= 255
        green *= 255
        blue *= 255
        return [(Float(red)), Float(green), Float(blue)]
    }

功能实现

发送数据

效果图中颜色, 饱和度和亮度的值对应HSB中的H-色相(0-360),S-饱和度(0-100),B-亮度(0-100)

通过获取UISlider中的

    let rgbs = hsbTorgb(h: Float(hueValue), s: Float(saturationValue), b: Float(brightnessValue))

控制灯的数据端点.png

在真实的设备调试过程中, 由于硬件是几天做出来的产品, 还有很多功能没完善, 发送过去的hsb的取值范围并不是理论上的, 实际取值范围是: H-色相(0-345),S-饱和度(2-100),B-亮度(80-100)

接收数据

数据更新返回的是RGB的值, 把转换后的hsb的值赋给对应的UISlier

    let getHSB = rgbTohsb(r: Float(red), g: Float(green), b: Float(blue))

补充

  • UISlier中有个属性isContinuous, 当设置为false时, 滑动过程中只有在放开的时候才会触发事件, 要是不设置这个属性的时候, 当滑动的时候会发送很多数据到设备端.

  • 分享个获取图片上指定位置上的颜色方法

- (UIColor *) getPixelColorAtLocation:(CGPoint)point {
    UIColor* color = nil;
    CGImageRef inImage = self.CGImage;
    CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
    if (cgctx == NULL) {
        return nil; /* error */
    }
    
    size_t w = CGImageGetWidth(inImage);
    size_t h = CGImageGetHeight(inImage);
    CGRect rect = {{0,0},{w,h}};
    
    CGContextDrawImage(cgctx, rect, inImage);
    
    unsigned char* data = CGBitmapContextGetData (cgctx);
    if (data != NULL) {
        //offset locates the pixel in the data from x,y.
        //4 for 4 bytes of data per pixel, w is width of one row of data.
        int offset = 4*((w*round(point.y))+round(point.x));
        int alpha =  data[offset];
        int red = data[offset+1];
        int green = data[offset+2];
        int blue = data[offset+3];
        //NSLog(@"offset: %i colors: RGB A %i %i %i  %i",offset,red,green,blue,alpha);
        color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
    }
    
    CGContextRelease(cgctx);
    if (data) { free(data); }
    return color;
}