XWindow/GDK对颜色的管理

时间:2023-01-24 14:14:57
                                    XWindow/GDK对颜色的管理
出处: http://www.newsmth.net/pc/pccon.php?id=6592&nid=264088&order=&tid=18261
GDK是建立在xwindow的基础上的, 因此要先搞清楚Xwindow对颜色的管理.
 

1.基本概念

1)Visual: visual表示了显示设备为某特定屏幕使用已经产生或者可能产生的颜色的特性,有Direct Color, True Color(read only),  Pseudo Color, Static Color(read only), GrayScale, StaticGray(read only).  一个显示设备至少支持一种Visual, 在高级工作站上, 可以同时支持多个Visual, 每个窗口使用不 同的Visual.2)Pixel: 屏幕又若干个Pixel构成, 每个Pixel都通过像素值来显示某个颜色, 从而构成整个屏幕的图形图像.3)Colormap: Colormap是一个颜色表, 根据索引就能在表中找到相应的颜色. Pixel Value像素值就是用来寻找颜色的索引. 在TrueColor, StaticGray, StaticCo lor下Colormap是不可以修改的, 而DirectColor, GrayScale, PseudoColor下Colormap是可以修改的. 每个窗口都可以使用系统默认的Colormap, 也可以创建 自己私有的Colormap(虚拟Colormap). 多数显示设备都只有一个硬件Colormap,当某个拥有私有虚拟Colormap的窗口被激活的时候, 系统自动把该虚拟colormap装进 硬件Colormap中, 从而显示该窗口需要的颜色.4)Color: 颜色, 一般用RGB三个分量来表示,5)color Depth: 颜色深度,即表示颜色的位数. 24bit下能表示2^24种颜色.
 

2.颜色表的颜色单元

在单色显示器/灰度级显示器中, 直接以Pixel Value作为所由, 从而在Colormap中得到颜色值.在高性能颜色显示器中, Pixel Value的若干位分别用作R值/G值/B值的索引, Colormap中分别保存了R/G/B的三个表, 用Pixel Value的R索引/G索引/B索引, 到R表/G表/B表中求得RGB值。
	例1, 某个16色显示器, Colormap中只有16个单元, 保存了16种颜色. PixelValue有效取值范围是0-15.
	例2, 某个16bit深度Direct Color显示设备, 每个PixelValue有16个bit,RGB各占用5/6/5bit, 有效PixelValue取值范围是0-2^16-1. Colormap分开为R/G/B, R单元有32个(32=2^5, 编号0-31), G单元有64个(64=2^6, 编号0-63), B单元有32个(32=2^5, 编号0-31), 表示的颜色有2^5*2^6*2^5=2^16种.单色取值范围是0~65535, 一般是平均分配到所有的单色单元中, 取值为i*65535/31/63, i=0~31/63
	例3, 某个24bit深度Direct Color显示设备, 每个PixelValue有24个bit,RGB各占用8bit, 有效PixelValue取值范围是0-2^24-1. Colormap分开为R/G/B, 各有256个单元(256=2^8, 编号0-255),单色取值范围是0~65535, 一般是平均分配到所有的单色单元中, 取值为i*65535/255, i=0~255
 

3.XWindow颜色函数

XCreateColormap: 创建ColormapXFreeColormap: 释放ColormapXListInstalledColormaps: 列出系统安装的ColormapXSetWindowColormap: 设置某个窗口的ColormapXAllocColorCells: 申请分配颜色表单元XStoreColor: 向已经分配好的颜色表单元设置颜色XFreeColors: 释放颜色表单元
 

4.RGB与Pixel Value的换算

Colormap实际上规定了如何将Pixel Value与颜色RGB互相转换.
	从Pixel Value得到RGB: 找到Pixel Value中分别表示R/G/B的bit作为索引, 从而找到R/G/B颜色值.
	从RGB计算Pixel Value: 将RGB分解, 找到R/G/B分量, 然后在Colormap中找到对应的索引, 拼接成Pixel Value.
	从前面我们可以看出, R/G/B的值是从0~65535均匀分布在0-255号单元中, 分别为0, 65535/255, 65535*2/255, ..., 65535*i/255 ,..., 65535, i=0~255. 因此对于不等于这255个数字的颜色值, 计算其Pixel要采用近似法则. 这在视觉上是可以接受的: 对于颜色A(rgb), r为1,2,3,..的时候, 尽管颜色表没有存放这些颜色值, 但可以近似为r=0来显示, 因为人眼不足以区分如此细小的颜色差别, 也就是说颜色A<2, 0, 65535> 与颜色B<0, 3, 65533>尽管不相等, 但是在换算后Pixel值都是255(0x00 00 FF), 显示出来的颜色都是<0, 0, 65535>(蓝色).
 

5.GDK颜色管理

每个Drawable对象(包括GdkWindow和GdkPixmap)关联一个Visual, Visual关联一个Colormap
GdkDrawable::get/set colormap, get/set visual
GdkColormap_new::(visual)
+-----------+       get/set
| Drawable  |-----------------+
+-----------+                 |
     ^                        |
     |                        |
     |                        V
+-----------+  winattr   +----------+
| GdkWindow |----------->|  Visual  |
+-----------+    get     +----------+
     |                        |
     |                        |
     |    set/get        +----------+    *  +------------+
     +------------------>| Colormap |------>| GdkColor   |[pixel-rgb]
                         +----------+       +------------+
GdkWindow: create with attr
Colormap: create with visual
gdk_colormap_new: 创建Colormap. 对于Direct Color, gdk_colormap_new直接分配所有的颜色,调用XCreateColormap(, , ,AllocAll), 申请所有颜色单元,按默认平均分配算法填充colorcells, 即将平均分配到颜色单元中.
gdk_colormap_free_colors: 直接返回, 不调用XFreeColors. 只有pseudocolor和grayscale才会调用XFreeColors
gdk_colors_free: 直接返回, 不调用XFreeColors. 只有pseudo color和grayscale才会调用XFreeColors
gdk_colormap_alloc_colors: 对Direct Color和True Color, 不做实质性分配, 只把计算结果返回,不调用XAllocColorCell
gdk_colors_alloc: 直接调用XAllocColorCells
 

6.绘图颜色运算gc function

屏幕上所有的颜色运算, 都是针对Pixel Value的, 因此RGB要转换成Pixel Value来运算. 当我们把绘图颜色设置成红色<65535, 0, 0>, 实际上是设置参与绘图运算参数src为 0xFF0000.
src: gc中设置的颜色, Pixel Value
dest: the existing pixel on the drawable
Function Name     Value   Operation
-----------------------------------------------
GXclear            0x0    0
GXand              0x1    src AND dst
GXandReverse       0x2    src AND NOT dst
GXcopy             0x3    src
GXandInverted      0x4    (NOT src) AND dst
GXnoop             0x5    dst
GXxor              0x6    src XOR dst
GXor               0x7    src OR dst
GXnor              0x8    (NOT src) AND (NOT dst)
GXequiv            0x9    (NOT src) XOR dst
GXinvert           0xa    NOT dst
GXorReverse        0xb    src OR (NOT dst)
GXcopyInverted     0xc    NOT src
GXorInverted       0xd    (NOT src) OR dst
GXnand             0xe    (NOT src) OR (NOT dst)
GXset              0xf    1
计算公式:
result = ((src FUNC dst) AND plane-mask) OR (dst AND (NOT plane-mask))
一般情况下, plane-mask所有bit为1, 也就是说像素值所有bit都参加运算, 因此
result = src FUNC dest