诞生背景

我们知道,计算机的根本是二进制。而二进制是整数的一种表达形式。换句话来说,计算机本质上只能储存整数。

那怎么行!只能储存整数的计算机还能玩?我们要想办法让计算机储存更多种类的数据!那么有什么办法呢?有!把所有数据都转化为整数来储存不就行了!

小数怎么保存?那我就先把小数转化为科学计数法,比如:526.41 就转换为 5.2641 x 10^2,这样我只要储存两个整数:52641 和 2 就行了。

文本怎么保存?简单!字符和数字一一对应就行了!比如规定 A 对应 65,B 对应 66,a 对应 97 等,列出一个大大的表,让世界上所有的字符都有与之对应的数字,这样就可以储存任意文本了!

但是,只保存数字和文本还是不够,我们还希望他能储存图像!

在这种背景下,就涌现出了多种将颜色转换为整数数据的转换方案,RGBHSV 就是其中的两种。

十六进制

二进制是计算机的根本,但是十分不便于阅读。十进制是人们的日常生活习惯,但是用十进制无法体现计算机计数的特殊性质。因此,十六进制应运而生。

二进制的个位只有 0 和 1,十进制的个位是 0~9,而十六进制的个位不仅有 0~9,还增加了 abcdef(或 ABCDEF)六个字母,其中 a(或 A)表示 10,b(或 B)表示 11,c(或 C)表示 12,d(或 D)表示 13,e(或 E)表示 14,f(或 F)表示 15。

十六进制转换为十进制的方式就是把第 n 位乘上 16 的 n - 1 次幂再相加,如将 4dc2 转换为十进制就是 4 x 16^3 + 13 x 16^2 + 12 x 16^1 + 2 x 16^0 = 19906

十六进制与二进制的转换十分方便,因为十六进制一位就代表了二进制的四位。例如 4dc2,只要把每一位分别转换为四位二进制:4 对应 0100,d 对应 1101,c 对应 1100,2 对应 0010,再连接起来,0100110111000010 就是 4dc2 的二进制表示方式了。

为什么更多地使用十六进制,而不是更接近十进制的八进制?这是因为,在计算机中,一比特就是一位二进制,但是内存的基本计量单位并不是比特,而是字节(等于八比特),比如一个中文字符占两个字节,一个英文字母占一个字节。两位十六进制刚好能够表示一个字节,这是八进制做不到的,因此十六进制更加适用于计算机中。

两位十六进制的最大值是 ff,即十进制的 255,这个值也是一个字节所能储存的最大数据。因此,你可以在很多地方接触到 255 这个数据(通常作为值的上限,如 ip 地址)。

RGB 颜色系统

RGB,即红(Red),绿(Green),蓝(Blue)。

红绿蓝三色是光的三原色。这三种颜色按不同比例混合,可以得到几乎所有的颜色。所以,RGB 颜色系统,实际上就是把一种颜色用红、绿、蓝三种颜色的强度来表示并且储存。

在传统的 RGB 颜色系统中,红绿蓝三种颜色通常分为 256 个强度(0~255),0 表示完全没有,255 表示最强。只要储存红绿蓝三者的强度,就可以把几乎任何一种颜色保存在计算机中(一共能储存 256 x 256 x 256 = 16777216 种颜色)。例如:

  • (0, 0, 0) 表示黑色。
  • (255, 255, 255) 表示白色。
  • (255, 0, 0) 表示红色。
  • (255, 128, 0) 表示橙色。

在很多语言中,通常都支持用十六进制来表示颜色。

如:#ff0000(或 #FF0000)代表红色,# 是十六进制说明符(大多数情况下,GML 不同,使用 $),六位十六进制数字中,前两位是 red 的值,中间两位是 green 的值,后两位是 blue 的值。ff 是 255 的十六进制,所以 #ff0000 表示 (255, 0, 0),即红色。

在 GM 中,我们可以在图像编辑器里用 RGB 自定义颜色。(RGU 和 ESL是源自微软画图工具的说法,实际上几乎不使用这种称呼,他们等效于 RGB 和 HSL)

Color Selector

同样,我们也可以使用函数 make_color_rgb(red, green, blue) 来自定义颜色,它的返回值可以直接用作各个函数的颜色参数,和 GM 自带的 c_redc_green 等效。

HSV 颜色系统

HSV 系统复杂又难理解,并非一定要掌握。

HSV,即色调(Hue,或译作色相),饱和度(Saturation),亮度(Value,或译作明度)。

HSV Model

色调(Hue)为角度,在 0~360 之间,常用的颜色角度如下图:

Hue

饱和度(Saturation)是指颜色的鲜艳程度,取值范围为 0~1,或者说 0%~100%,如图:

Saturation

饱和度为 0 时,颜色与色调无关,只由亮度决定,亮度为 0 则是黑色,为 1 则是白色,之间则是灰色。

亮度(Value)是指颜色的明暗程度,取值范围也是 0~1,0 就是黑色,1 就是纯正的颜色。如图:

Value

在 GM8 中的特殊性

在 GM 中,为了便于储存,将色调、饱和度、亮度的取值范围都放缩到了 0~255。

例如:

  • (任意, 任意, 0) 表示黑色。
  • (任意, 0, 255)表示白色。
  • (0, 255, 255)表示红色。
  • (42, 255, 255)表示黄色。(60 x 255 / 360 ≈ 42)

在 GM 有函数 make_color_hsv(hue, saturation, value) 根据 hsv 生成颜色。

HSL 颜色系统

HSL 颜色系统即在 HSV 的基础上,将 V 改成了 L(Lightness),当 V = 2L 时,二者等效。而当 L 大于 0.5 时,颜色会向纯白色靠近,当 L 为 1 时,无论 H 和 S 是什么值,必定是白色。

HSL Model

在 GM 的图像编辑器中,RGB 坐标的 ESL 实际上就是 HSL 的旧缩写。

在图像编辑器中,HSL 并不是放缩到 0~255 之间,而是 H 为 0~239,S 和 L 为 0~240,我原本以为这是 Overmars 脑子抽了,但是后来我发现 Windows 自带的画图工具也是这么放缩的。。。所以来一起大喊巨硬萨比吧。

RGBA 颜色系统与 HSVA 颜色系统

现在,我们已经能储存所有种类的颜色了,但是这还不够。有的时候,我们需要一张图片本身是半透明的,甚至这张图片各个地方的透明度还不一样,RGB 和 HSV就已经无法满足我们了。

RGBA 和 HSVA,即是在原有的基础之上,再添加了一项新的内容——透明度(Alpha)。透明度(Alpha)的取值范围为 0~1,0 表示完全透明,1 表示完全不透明,在 0~1 之间则是半透明。在 GM 中,透明度的范围也放缩到了 0~255 以便于储存(有时是 0~1)。

在 GM 的图像编辑器中,也可以自定义颜色的透明度。

Alpha

后话

除了 RGB 和 HSV/HSL 之外,还有很多种颜色系统,其中常用的还有 YCbCr,CMYK,Lab,Ycc,YUV 等等,各自在合适的领域发挥自己的作用。

除了图像以外,其他类型的数据,如音频,视频,软件等,都是以整数的二进制形式储存的,他们都以各种各样的规律把自己和整数对应起来互相转换。

从数据转化到二进制储存(或其他形式,如电子脉冲)的过程叫做编码,反之叫做解码,编码和解码几乎渗透于计算机的方方面面,和计算机打交道,就不可避免需要和编码打交道。

明白了编码的意义,我们就可以去理解一些以前无法理解的东西。

比如,乱码是怎么来的?学了编码之后,我们就可以知道,原来文本都是通过编码转换为二进制储存的,但是,这种转化方式并不唯一,除了最常用的 Unicode 编码,ASCII 编码,ANSI 编码,shift-JIS 编码等也在很多地方被使用,这些编码的区别是,同一个字符对应的数字是不一样的,所以,用某一种编码方式转换为二进制的文本,被另一种编码方式解码,就会被解码成与原本完全不同的文本内容,所以就有了“乱码”的存在。