2023年7月

参考https://zhuanlan.zhihu.com/p/612916407
上文中说的很好了, 还有GIF动画演示. 针对其中缺少的部分:

  • 一个是地图权限设置, 在文件>选项和设置>选项>全局>安全性>地图和着色地图视觉对象>使用地图和着色地图视觉对象上打钩. 如果没有显示则需要重启Power BI
  • 中国地图JSON转换后的, 可以直接这儿下载使用 不需要在转换了: China_topo.zip

人类的颜色视觉

人类亮视觉主要依靠集中在黄斑区域的视锥细胞, 按其感受波长的长度分为L/M/S型, 其敏感波长和数量占比是: 参考

视锥细胞类型 敏感波长 敏感色 数量占比
S型 437nm 蓝色 2%
M型 533nm 绿色32%
L型 564nm 黄绿色 64%

哈哈, 想不到吧, L型看到的564nm其实是黄绿色!可是大多数文章都将L型视锥细胞敏感波长说成是红色! 如下图, 正好处在黄色和绿色的边界.

从波长上看, M和L只差了31nm, 其实是距离很近的. 而S型和和M型相差96nm. 从生物演化角度, M型也是从L型演化出来的.
色盲最多的也是红绿色盲, 也就是红绿无法分辨. 我猜测是L和M细胞缺少分化这一步导致的.

还有就是, S型细胞出奇的少, 不知这和蓝光容易损害黄斑区是否有一定关系,也就是不清楚对蓝光敏感的细胞容易受损还是不敏感的容易受损.

显示器颜色

显示器颜色的红绿蓝, 我测试了一下我的手机屏幕, 峰值分别为458/522/620nm. 其中蓝色和绿色间隔64nm, 绿色和红色间隔98nm.
这个奇怪的是和视锥细胞敏感色并不一致.

LED 波长 与视杆细胞敏感波长距离
458nm +21nm
绿 522nm -11nm
620nm +56nm

三原色

参考: https://www.kxting.com/article/20221114/949298.html
由国际照明委员会(EIC)定义,选择红色(波长λ=700.00nm),绿色(波长λ=546.1nm),蓝色(波长λ=438.8nm)三种单色光作为表色系统的三基色。其中R(red)、G(Green)、B(Blue)分别是红绿蓝的英文首字母。

三原色|波长|与视杆细胞敏感波长距离
--|--|
B | 439nm |+2nm
G | 546nm |+13nm
R | 700nm |+136nm

可见也是有很大差异.
这个标准三原色, 经过人的视锥细胞, 是否能看到所有的色彩(380~780nm)呢? 这就和色度图联系起来了, 参考https://www.jianshu.com/p/213e4500dbea
色度图只有x,y两个坐标, 怎么对应RGB三个值? 那当然就是相当于把亮度取消了. 怎么取消? 把RGB值归一化处理, 让R+G+B=1就可以了,也即是只表示一个颜色中RGB分别所占的比例, 而不考虑其强度.
要让RGB对应可见光380~780nm的所有颜色, 数学上可能,实际上不可能, 为什么? 因为需要R是负值, 用r/g的平面图表示如下:

为了在图上再次归一化, 也就是x,y坐标取值在0~1之间, CIE发明了x/y/z和RGB的换算关系, 这样就把上面的马蹄挤到了1x1的方框里,就得到了经典的马蹄图CIE1931

马蹄的上沿一圈就是光谱的波长, 当然不是均衡分布的. RGB三个波长组成的三角, 就是显示器能显示的范围了. 嗯, 这个图要在显示器上显示, 我想一定是失真的了.
至于为什么用视锥细胞的敏感波长反而不能组合出完整的色彩感受, 还需要进一步的研究.

变量赋值与常量比较

先看个例子:

#include <stdio.h>
int main()
{
   char c = 0xff;
    if(c == 0xff){
        printf("true");
    }else{
        printf("false");
    }

   return 0;
}

你觉得是打印true还是false? 结果出乎意料是false!
因为c赋值为0xff之后, c的值就会变为-1. -1当然就不等于255了.
另外, c要和255比较, 估计还需要升位到int才行, 因为char类型装不下255, unsignd char装不下-1, 就得升到int才能比较.

length选择哪种数据类型

length取值最好为int. 原因是很多第三方返回length的函数都是使用int, 如uart读取. 虽然有时候你觉得char就够用了, 但为了避免反复的类型转换, 还是统一int比较好.
length常常用来确定数组的长度, 此时表示length的变量会被用作数组下标, 而数组下标不能为char.
除非内存真的要非常节约...

字符串和二进制缓存用那种数据类型

字符串多选择char类型, 指针是char , 数组是char string[]. 因为标准库中字符串的处理函数都是char的.
而二进制(16进制)缓存,也就是buffer, 最好使用unsigned char类型. 原因是buffer的值常常表示十六进制也就是0x, 在进行比较的时候会出现被赋值的变量不等于赋值的常量的情况, 如char c = 0xff,而比较时c != 0xff, 因为已经溢出为-1了.