前端需要了解的颜色模型,RGB、HSL和HSV

目录

RGB模型

RGB颜色值

rgb 转 hex

hex 转 rgb

HSL模型

HSV(B)模型

RGB 与 HSL 的转换

rgb 转 hsl

hsl 转 rgb

颜色模型,是用来表示颜色的数学模型。比如最常见的 RGB模型,使用红绿蓝三色来表示颜色。
一般的颜色模型,可以按照如下分类:

  • 面向硬件设备的颜色模型:RGB,CMYK,YCrCb。
  • 面向视觉感知的颜色模型:HSL,HSV(B),HSI,Lab。

不同的颜色模型有不同的应用场景,而RGB模型适合于显示器这样的的设备。

其中,前端支持的是 RGB、HSL,即在前端页面中只有这两种模型的颜色值可以有效展示出来。  
而对于HSV,则是我们在创建颜色选择器插件时所需要了解的一种模型。  
目前,chrome浏览器实现的H5的颜色色盘,就是基于HSV模型:  
注意:fixfore浏览器支持的仍然是电脑系统色盘(如win系统下,与画图软件中编辑颜色的色盘一样)。

本文将主要介绍 RGB、HSL、HSV 这三种模型。

RGB模型

RGB 即常说的红(R)绿(G)蓝(B)三原色模型,是运用最广泛的颜色模型。  
特别是在前端开发中,几乎都使用该模型处理颜色。如:rgb(0, 0, 255),#d3d3d3。  
该模型通过红绿蓝三个颜色通道的变化和相互之间的混合叠加,使用不同的强度,表现出不同的颜色。  
它是一种加色混色模型,在叠加混合的过程中,亮度等于色彩亮度的综合,混合的越多亮度就越高。

根据三色的取值不同,一般有以下几种类型:

+ R5G5B5(A1):16位,各色都用5位表示,取值范围0-31(2^5 - 1),剩余1位作Alpha通道或者不用。
+ R5G6B5:16位,R和B占用5位,取值范围0-31(2^5);G占用6位,取值范围0-63(2^6 - 1)。
+ R8G8B8:24位,各色都用8位表示,取值范围为0-255(2^8 - 1)。  
  最多能有2^24种颜色,从24位开始的颜色就是真彩色,基本达到人眼极限。
+ R8G8B8(A8):32位,各色都用8位表示,取值范围为0-255(2^8 - 1),剩余8位作Alpha通道或者不用。

这其中,最常见的当然就是24位和32位的类型。  
三色通道中每个颜色有256阶的亮度,为0时最暗,255时最亮。  
如果三色的数值都相同时,就会产生不同灰度值的灰度色调,都为0时最暗黑色,都为255时最亮白色。

RGB颜色值

先看下RGB颜色值在前端的展现,如红色:

'rgb(255, 0, 0)'
'rgba(255, 0, 0, 1)' // 带透明度
'#ff0000'
'#f00' // 缩写
'red' // 颜色名称

描述RGB模型,使用的颜色值,有rgbhex16进制两种方式。

  • rgb(0,0,0)表示法,一般情况下,红绿蓝三色分别取值范围0-255,如果加上alpha透明通道,则为 rgba(0,0,0,1) 。
  • hex 16进制表示法,采用十六进制对24比特的一种展示方式,如#000000,共6位,每两位分别对应红绿蓝,相同时可缩写为 #000。hex也可以使用 #00000000,后面加上透明度的十六进制数值。

此外,在前端开发中,还可以使用颜色名称如 redgreengray 等标识颜色。
但实际上,这里的颜色名称仍然是对应的一个RGB颜色值,有一个规定的颜色名称与值的关系表。大部分的颜色单词基本都能使用。

上面两种表示法的简单转换关系,如下所示。

rgb 转 hex

function getHex (num) {
  let val = num.toString(16)
  val = (val.length === 1) ? ('0' + val) : val
  return val
}
function rgbaToHexa (red, green, blue, alpha) {
  red = getHex(red)
  green = getHex(green)
  blue = getHex(blue)
  alpha = Math.round(alpha * 255)
  alpha = getHex(alpha)
  return '#' + red + green + blue + alpha
}

hex 转 rgb

function hexaToRgba (color) {
  const value = color.slice(color.indexOf('#') + 1)
  const isShort = value.length === 3 || value.length === 4
  const hasAlpha = value.length === 4 || value.length === 8
  const r = isShort ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2)
  const g = isShort ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4)
  const b = isShort ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6)
  let a = hasAlpha ? (isShort ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF'
  a = parseFloat((parseInt(a, 16) / 255).toFixed(2))
  return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), a]
}

HSL模型

前端在颜色的处理上,除了支持RGB模型外,另外支持的就只有HSL模型,所以我们需要了下解该模型。

HSL颜色值表示,红色:

hsl(0, 100%, 50%)
hsla(0, 100%, 50%, 1) // 带透明度

HSL 是对色相H(hue)饱和度S(saturation)亮度L(lightness)的处理得到颜色的一种模型。  

色相(H):
色相、色调,代表人眼所能看到的不同的颜色,本质就是一种颜色。与HSV(B)模型中的H概念相同。
色相的定义中,许多的颜色分布在一个圆环上,取值范围则是0-360度,每个角度代表着一种颜色。  
在HSL和HSV的模型中,色相是以六大主色为基础,他们分别按 60 度的间隔排列在圆环上。这六大主色分别是:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红
而在前端进行处理时,常常把圆环处理成长方形的色块,通过颜色的线性渐变方式进行分段处理,角度换算成一定的比例,如下所示:

linear-gradient(90deg, #f00, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00);

饱和度(S):
饱和度是指颜色的强度或纯度,使用0 ~ 100%的百分比来度量。
表示色相中颜色成分所占的比例,数值越大,颜色中的灰色越少,颜色越鲜艳,呈现的是一种从灰色到色相颜色的变化。

亮度(L):
表现颜色的明暗程度,使用0 ~ 100%的百分比来度量。
反映色彩中混入的黑白两色,50% 处只有纯色,小于 50% 时,数值越小混入的黑色越多,越接近于黑色;大于 50% 时,数值越大混入的白色越多,越接近于白色。
L最大时必为白色,L最小时必为黑色。
体现的是从黑色到色相(H)选择颜色再到白色的过渡。

HSV(B)模型

HSV 颜色值表示,红色:

// 前端不支持
hsv(0, 100%, 100%)
hsva(0, 100%, 100%, 1) // 带透明度

HSV 采用色相H(hue)饱和度S(saturation)明度V(Value)3个参数来表示颜色的一种方式。  
HSV和HSL两个模型都是更偏向于视觉上直观的感觉。  
而HSV与HSB的内容基本是一样的,可以理解为两种不同写法而已,其中 B( brightness )。

色相(H):
同HSL模型中的 H色相。
饱和度(S):
饱和度是指颜色的强度或纯度,使用0 ~ 100%的百分比来度量。  
在HSV中更多的是反映色相的颜色中混入白色的值,值越大白色越少色相颜色越纯,值越小白色越多色相颜色越淡。
明度(V):
表现颜色的明暗程度,使用0 ~ 100%的百分比来度量。
反映色相的颜色中混入的黑色的值,值越小黑色越多颜色更暗(黑),值越大黑色越少颜色更纯(亮)。
 体现的是从黑色到色相(H)选择颜色的过渡。

RGB 与 HSL 的转换

下面是常用的 rgb 颜色值与 hsl 之间互相转换的代码。
注意:
这两个过程中,由于取整去除了小数位,并不是完全可逆的,可能存在个别个位数的差值。
虽有些微差别,但在页面颜色显示上基本没分别,因为人眼分辨不出来。

rgb 转 hsl

function rgbToHsl (red, green, blue) {
  red = red / 255
  green = green / 255
  blue = blue / 255
  let hue = saturation = lightness = 0
  const max = Math.max(red, green, blue)
  const min = Math.min(red, green, blue)
  const diff = max - min
  const sum = max + min

  lightness = sum / 2
  
  if (diff) {
    saturation = lightness > 0.5 ? diff / (2 - sum) : diff / sum
    switch (max) {
      case red:
        hue = (green - blue) / diff + (green < blue ? 6 : 0)
        break
      case green:
        hue = (blue - red) / diff + 2
        break
      case blue:
        hue = (red - green) / diff + 4
        break
    }
    hue = hue / 6
  }

  hue = Math.round(hue * 360)
  saturation = Math.round(saturation * 100)
  lightness = Math.round(lightness * 100)
  return [hue, saturation, lightness]
}

hsl 转 rgb

function hslToRgb(hue, saturation, lightness) {
  hue = hue / 360
  saturation = saturation / 100
  lightness = lightness / 100
  let red, green, blue
  const hue2rgb = (val1, val2, vH) => {
    vH = vH < 0 ? (vH + 1) : vH > 1 ? (vH - 1) : vH

    if (vH < 1 / 6) {
      return val1 + (val2 - val1) * 6 * vH
    }
    if (vH < 1 / 2) {
      return val2
    }
    if (vH < 2 / 3) {
      return val1 + (val2 - val1) * (2 / 3 - vH) * 6
    }
    return val1
  }

  if (saturation === 0) {
    red = green = blue = lightness;
  } else {
    const val2 = lightness <= 0.5 ? lightness * (saturation + 1) : (lightness + saturation) - (lightness * saturation)
    const val1 = lightness * 2 - val2

    red = hue2rgb(val1, val2, hue + 1 / 3)
    green = hue2rgb(val1, val2, hue)
    blue = hue2rgb(val1, val2, hue - 1 / 3)
  }

  red = Math.round(red * 255)
  green = Math.round(green * 255)
  blue = Math.round(blue * 255)
  return [red, green, blue]
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
将BLOB类型的二进制数据以RGB565的形式显示在前端界面,可以通过以下步骤实现: 1. 在后端,将BLOB类型的二进制数据转换为RGB565格式的二进制数据。 ```java // 获取BLOB类型的二进制数据 byte[] blobData = resultSet.getBytes("blob_column_name"); // 将BLOB数据转换为RGB数组 int[] rgbArray = convertBlobToRGB(blobData); // 将RGB数组转换为RGB565格式的二进制数据 byte[] rgb565Data = convertRGBToRGB565(rgbArray); ``` 2. 在前端,使用canvas元素将RGB565格式的二进制数据绘制为图片。 ```html <canvas id="canvas" width="320" height="240"></canvas> ``` ```javascript // 获取RGB565格式的二进制数据 var rgb565Data = ...; // 获取canvas元素 var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); // 创建ImageData对象,并将RGB565格式的二进制数据复制到该对象中 var imageData = context.createImageData(canvas.width, canvas.height); for (var i = 0; i < rgb565Data.length; i += 2) { var pixel = convertRGB565ToRGB(rgb565Data[i], rgb565Data[i + 1]); imageData.data[i * 4] = pixel.r; imageData.data[i * 4 + 1] = pixel.g; imageData.data[i * 4 + 2] = pixel.b; imageData.data[i * 4 + 3] = 255; } // 在canvas元素中绘制图片 context.putImageData(imageData, 0, 0); ``` 其中,`convertBlobToRGB()`函数将BLOB类型的二进制数据转换为RGB数组,`convertRGBToRGB565()`函数将RGB数组转换为RGB565格式的二进制数据,`convertRGB565ToRGB()`函数将RGB565格式的二进制数据转换为RGB对象。这些函数的具体实现可以参考以下代码: ```java private int[] convertBlobToRGB(byte[] blobData) { int[] rgbArray = new int[blobData.length / 3]; for (int i = 0; i < blobData.length; i += 3) { int r = blobData[i] & 0xff; int g = blobData[i + 1] & 0xff; int b = blobData[i + 2] & 0xff; rgbArray[i / 3] = (r << 16) | (g << 8) | b; } return rgbArray; } private byte[] convertRGBToRGB565(int[] rgbArray) { byte[] rgb565Data = new byte[rgbArray.length * 2]; for (int i = 0; i < rgbArray.length; i++) { int r = (rgbArray[i] >> 16) & 0xff; int g = (rgbArray[i] >> 8) & 0xff; int b = rgbArray[i] & 0xff; int rgb565 = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); rgb565Data[i * 2] = (byte) (rgb565 >> 8); rgb565Data[i * 2 + 1] = (byte) rgb565; } return rgb565Data; } private static class RGB { public int r; public int g; public int b; public RGB(int r, int g, int b) { this.r = r; this.g = g; this.b = b; } } private RGB convertRGB565ToRGB(byte b1, byte b2) { int rgb565 = ((b1 & 0xff) << 8) | (b2 & 0xff); int r = (rgb565 >> 11) & 0x1f; int g = (rgb565 >> 5) & 0x3f; int b = rgb565 & 0x1f; return new RGB((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2)); } ``` 注意,以上代码仅供参考,具体实现可能需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端江湖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值