尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ReactOS 图形系统分析(19):颜色转换对象 — XLATEOBJ(xlateobj.c/h)

ReactOS 图形系统分析(19):颜色转换对象 — XLATEOBJ(xlateobj.c/h) ReactOS 图形系统分析19颜色转换对象 — XLATEOBJxlateobj.c/h1. 概述xlateobj.c / xlateobj.h位于win32ss/gdi/eng/实现XLATEOBJ颜色转换对象——Windows GDI/DDI 中描述源表面颜色 → 目标表面颜色转换的核心对象。它解决一个本质问题不同位深/格式/调色板的表面之间复制像素时每个像素值如何映射。与《分析_16/17/18》不同xlateobj不是预留服务层而是引擎最核心、被高频调用的模块DIB 引擎每个位深1/4/8/16/24/32bpp的 BitBlt、拉伸、Alpha 混合、文本字形上屏、画刷填充全部经过XLATEOBJ_iXlate做像素级颜色转换。┌─────────────────────────────────────────────────────────────┐ │ 消费方 │ │ DIB 引擎 (dib*.c / BitBlt 内联 XLATEOBJ_iXlate) │ │ eng/bitblt.c (画刷/前景背景色) dib/alphablend.c │ │ dib/stretchblt.c ntgdi(bitblt/fillshap/freetype/palette) │ ├─────────────────────────────────────────────────────────────┤ │ gdi/eng/xlateobj.c本分析对象 │ │ 核心: EXLATEOBJ 结构 pfnXlate 函数指针分发 │ │ ├── ~25 个专用转换函数 (FN_XLATE) │ │ ├── EXLATEOBJ_vInitialize: 按源/目标调色板类型选择函数 │ │ └── DDI 公开: XLATEOBJ_iXlate / cGetPalette / │ │ hGetColorTransform / piVector │ ├─────────────────────────────────────────────────────────────┤ │ ntgdi/palette.c (调色板对象/位掩码) │ │ 提供 gpalRGB/gpalRGB555/gpalRGB565/gppalMono 等全局调色板 │ └─────────────────────────────────────────────────────────────┘2. 核心数据结构2.1 XLATEOBJ — DDI 公开部分[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h#L1254-L1261)typedefstruct_XLATEOBJ{ULONG iUniq;// 唯一编号每次初始化递增用于缓存命中判断FLONG flXlate;// XO_* 标志USHORT iSrcType;// 源调色板类型USHORT iDstType;// 目标调色板类型ULONG cEntries;// 转换表项数ULONG*pulXlate;// 转换表指针可指向内嵌数组或堆分配}XLATEOBJ;2.2 EXLATEOBJ — 引擎扩展[xlateobj.h](file:///d:/reactos/win32ss/gdi/eng/xlateobj.h#L19-L51)typedefstruct_EXLATEOBJ{XLATEOBJ xlo;// 公开头PFN_XLATE pfnXlate;// ← 函数指针分发核心FASTCALL ULONG(pexlo, iColor)PPALETTE ppalSrc;// 源调色板PPALETTE ppalDst;// 目标调色板PPALETTE ppalDstDc;// 目标 DC 调色板DC_PALETTE 用HANDLE hColorTransform;// 颜色变换句柄ICMunion// 6 个 ULONG 的复用池{ULONG aulXlate[6];// ① 内嵌小转换表≤6 项省去堆分配struct{// ② 位域转换参数掩码 旋转偏移ULONG ulRedMask;ULONG ulGreenMask;ULONG ulBlueMask;ULONG ulRedShift;ULONG ulGreenShift;ULONG ulBlueShift;};struct{// ③ 彩色→单色转换参数点积判别常数LONG lDeltaR;LONG lDeltaG;LONG lDeltaB;LONG lHalfDist;}ToMono;};}EXLATEOBJ,*PEXLATEOBJ;设计亮点pfnXlate函数指针 6 个 ULONG 的联合池——同一块内嵌存储按转换类型复用作小表 / 位域掩码偏移 / 单色点积常数避免为小转换表堆分配且转换本身是一条快路径调用。2.3 标志位XO_转换类型标志[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h#L1247-L1249)*标志含义XO_TRIVIAL恒等转换源值即目标值XO_TABLE查表转换XO_TO_MONO转换到单色XO_调色板编号XLATEOBJ_cGetPalette用[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h#L3151-L3155)*XO_SRCPALETTE1、XO_DESTPALETTE2、XO_DESTDCPALETTE3、XO_SRCBITFIELDS4、XO_DESTBITFIELDS5。PAL_调色板类型[palette.h](file:///d:/reactos/win32ss/gdi/ntgdi/palette.h#L10-L28)节选*标志含义PAL_INDEXED索引色查表含颜色表PAL_BITFIELDS位域RGB 掩码 偏移PAL_RGB/PAL_BGR24/32bpp 直接 RGB / BGR 顺序PAL_RGB16_555/PAL_RGB16_56516bpp 高/低 5 位格式PAL_MONOCHROME单色仅 2 色PAL_DIBSECTIONDIB Section 专用转换方向特殊处理2.4 全局单例 gexloTrivialEXLATEOBJ gexloTrivial{{0,XO_TRIVIAL,0,0,0,0},EXLATEOBJ_iXlateTrivial};恒等转换的全局实例flXlateXO_TRIVIALpfnXlateiXlateTrivial当无颜色转换需求时直接引用[bitblt_new.c](file:///d:/reactos/win32ss/gdi/eng/bitblt_new.c#L141)、[mouse.c](file:///d:/reactos/win32ss/gdi/eng/mouse.c#L357)避免每次分配对象。3. 转换函数族~25 个 FN_XLATE全部签名为FASTCALL ULONG(PEXLATEOBJ, ULONG iColor)按用途分五类3.1 单色快速通道函数行为iXlateTrivial恒等返回 iColoriXlateMonoInvertiColor ^ 1黑白互换iXlateMonoTo0/iXlateMonoTo1全部映射为 0 / 1iXlateToMono查 1 项表(iColor pulXlate[0])iXlateRGBToBW/iXlateRGBToWB亮度阈值rgb 383判黑/白仅用于纯黑/纯白目标3.2 彩色→单色点积判别EXLATEOBJ_iXlateRGBToMono(pexlo,rgbColor){LONG lDistr*pexlo-ToMono.lDeltaRg*pexlo-ToMono.lDeltaGb*pexlo-ToMono.lDeltaB;return(lDistpexlo-ToMono.lHalfDist);}把前景/背景色看成 RGB 空间两点预计算前景减背景的方向向量lDelta*与判别阈值lHalfDist (|F|²−|B|²)/2每像素用点积符号判归属——几何意义即像素点落在前背景连线哪一侧。iXlateBGRToMono仅是字节序反转版本GetRValue取蓝。3.3 位格式转换16bpp 家族转换要点RGBtoBGR/ 反向仅交换 R/B 字节(v0x00ff00ff)16RGBto555/BGRto55524bpp → 5-5-5右移掩码含 BGR 序RGBto565/BGRto56524bpp → 5-6-5555toRGB/555toBGR5-5-5 → 24bpp用gajXlate5to8扩位表5bit→8bit 按 8 间隔扩展565toRGB/565toBGR5-6-5 → 24bpp绿用gajXlate6to86bit→8bit4 间隔555to565/565to55516bpp 互转复制最高绿位等位操作扩位查表gajXlate5to8[32]/gajXlate6to8[64]把 5/6 位分量均匀映射到 8 位如 5bit 值 v →v*255/31取整比移位或操作精度更高。3.4 位域转换EXLATEOBJ_iXlateShiftAndMask(pexlo,iColor){iNewColor_rotl(iColor,ulRedShift)ulRedMask;iNewColor|_rotl(iColor,ulGreenShift)ulGreenMask;iNewColor|_rotl(iColor,ulBlueShift)ulBlueMask;returniNewColor;}通用位域重排用循环左移对齐各通道后按掩码提取源/目标的 555/565/掩码位域一律走此函数。3.5 调色板索引转换函数行为RGBtoPal/555toPal/565toPal转 RGB 后PALETTE_ulGetNearestPaletteIndex求最近色索引BitfieldsToPal先 ShiftAndMask 转 RGB 再查最近索引Table通用查表iColor cEntries ? 0 : pulXlate[iColor]越界保护4. EXLATEOBJ_vInitialize — 转换器选择器这是模块的总调度器根据源/目标调色板类型flFlags组合从 ~25 个函数中挑出最优实现是否MONO → MONOMONO → 彩色彩色 → MONOINDEXED → INDEXEDRGB/BGR/555/565/BITFIELDS→ 各目标ShiftAndMask 且偏移全 0pfnXlate TrivialEXLATEOBJ_vInitialize(ppalSrc, ppalDst,crSrcBack, crDstBack, crDstFore)默认 RGB; iUniq 递增; 清空状态ppalDst ppalSrc?pfnXlate Trivial, XO_TRIVIAL非索引调色板 → 预计算PALETTE_vGetBitMasks CalculateShift源/目标类型组合4 情形: trivial / invert / to0 / to12 项查表 (DIB/直接 或 前背景色)iXlateToMono 点积常数(CLR_INVALID 时 vInitRGBToMono)建全量表; cDiff0 → 退化 Trivial(6 项才堆分配)按 5×5 组合表选专用函数尾优化退化 TrivialXO_TRIVIAL关键分支细节MONO→MONO 四情形[xlateobj.c](file:///d:/reactos/win32ss/gdi/eng/xlateobj.c#L541-L589)先按DIB/DDB 方向 前背景色算出iColors[0]/[1]再匹配 4 种简化(0,1)→Trivial、(1,0)→Invert、(0,0)→To0、(1,1)→To1。彩色→MONO 的 CLR_INVALID 特例调用方如NtGdiSetPixel传CLR_INVALID表示直接用 DIB 颜色表做点积判别此时EXLATEOBJ_vInitRGBToMono用目标单色调色板的 0/1 号色初始化点积参数。INDEXED→INDEXED 退化优化构建全量表后若所有项pulXlate[i]i恒等映射则释放堆内存、退回 Trivial表 ≤6 项时直接复用联合池内嵌aulXlate[6]6才EngAllocMemGDITAG_PXLATE。位域偏移预计算CalculateShift由源/目标掩码算旋转偏移使运行时仅_rotl and。三个初始化包装函数用途EXLATEOBJ_vInitXlateFromDCs由源/目标 DC 表面调色板初始化BitBlt 用EXLATEOBJ_vInitXlateFromDCsEx同前但可指定源背景色透明色/掩码 blt 用EXLATEOBJ_vInitSrcMonoXlate强制源为单色调色板gppalMono单色源 blt 用EXLATEOBJ_vCleanup若pulXlate指向堆内存≠内嵌aulXlate则EngFreeMem并复位。5. DDI 公开函数与导出函数行为win32k 导出UMPDgdi32→win32u→umpdstubsXLATEOBJ_iXlate转换入口空指针→原值否则pfnXlate(pexlo, iColor)分发—内部UMPDNtGdiXLATEOBJ_iXlate[umpdstubs](file:///d:/reactos/win32ss/gdi/eng/umpdstubs.c#L718)桩XLATEOBJ_cGetPalette按iPalXO_* 编号返回源/目标/DC 调色板颜色pPalOutNULL时返回项数校验PAL_INDEXED/PAL_BITFIELDS匹配✓[win32k.spec](file:///d:/reactos/win32ss/win32k.spec#L228)NtGdiXLATEOBJ_cGetPalette桩XLATEOBJ_hGetColorTransform返回 ICM 颜色变换句柄✓L229NtGdiXLATEOBJ_hGetColorTransform桩XLATEOBJ_piVector源为索引色时返回转换表指针否则 NULL✓L231—注意XLATEOBJ_iXlate在 xlateobj.c 中定义前先#undef XLATEOBJ_iXlate防御早期 winddi.h 曾把它定义成宏内核态驱动直接调用用户态 UMPD 经NtGdiXLATEOBJ_iXlate。6. 消费方与调用链核心活跃证据ntgdi/bitblt.c IntGdiBitBlt → EXLATEOBJ_vInitXlateFromDCs → XLATEOBJ_iXlate(每像素) ↓ BLTINFO.XlateSourceToDest DIB 引擎 (dib1bpp~dib32bpp, stretchblt, alphablend) 内联宏: XLATEOBJ_iXlate(ColorTranslation, Source) ← 每像素调用 eng/bitblt.c 画刷颜色 → XLATEOBJ_iXlate(pxloBrush, iSolidColor) 前/背景色 → pxloRGB2Dest ntgdi/freetype.c 文本 → exloRGB2Dst / exloDst2RGB (字形掩码与画刷) ntgdi/fillshap.c 椭圆/洪水填充 → 目标色转换 ntgdi/dcutil.c GetPixel/SetPixel → gpalRGB → 表面调色板 ntgdi/palette.c GetNearestColor → EXLATEOBJ_vInitialize iXlate ntgdi/dibobj.c DIB 位图/调色板互转 dib/alphablend.c Alpha 混合 → 3 个 exlo 来回转换/* DIB 引擎内联转换宏dib.h所有位深 BitBlt 的像素必经之路 */#defineXLATEOBJ_iXlate(ColorTranslation,Source)\((ColorTranslation)?\XLATEOBJ_pfnXlate(ColorTranslation)((ColorTranslation),(Source)):(Source))性能设计转换以函数指针单跳实现无分支判断Trivial 情形最普遍如 32bpp→32bpp 同格式退化为直接返回原值DIB 引擎甚至可走无转换快路径。7. 与《分析_4》标注对照标注核对《_4》第 39 行xlateobj.c/h 「颜色转换对象」准确。补充核心活跃模块非预留层由 EXLATEOBJ.pfnXlate 函数指针分发 ~25 个专用转换函数EXLATEOBJ_vInitialize 按调色板类型选择实现8. 源码索引文件关键内容[xlateobj.c](file:///d:/reactos/win32ss/gdi/eng/xlateobj.c)转换函数族、EXLATEOBJ_vInitialize/vInitXlateFromDCs(Ex)/vInitSrcMonoXlate/vCleanup、XLATEOBJ_iXlate/cGetPalette/hGetColorTransform/piVector[xlateobj.h](file:///d:/reactos/win32ss/gdi/eng/xlateobj.h)EXLATEOBJ 结构联合池、PFN_XLATE、初始化声明[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h)XLATEOBJ 结构、XO_* 标志、ENGAPI 声明[palette.h](file:///d:/reactos/win32ss/gdi/ntgdi/palette.h)PAL_* 标志、CalculateShift、gpalRGB 等全局[palette.c](file:///d:/reactos/win32ss/gdi/ntgdi/palette.c)调色板对象、全局调色板初始化[dib.h](file:///d:/reactos/win32ss/gdi/dib/dib.h)XLATEOBJ_iXlate 内联宏BLTINFO 中调用[bitblt.c](file:///d:/reactos/win32ss/gdi/eng/bitblt.c)画刷/前景背景色转换消费[ntgdi/bitblt.c](file:///d:/reactos/win32ss/gdi/ntgdi/bitblt.c)IntGdiBitBlt 初始化 exlo[umpdstubs.c](file:///d:/reactos/win32ss/gdi/eng/umpdstubs.c#L705-L740)NtGdiXLATEOBJ_*UMPD 桩关联模块上层调用者[ntgdi/](file:///d:/reactos/win32ss/gdi/ntgdi/bitblt.c)BitBlt/GetPixel/填充/文本后端消费[gdi/dib/](file:///d:/reactos/win32ss/gdi/dib/)各位深 BitBlt 内联转换调色板来源[ntgdi/palette.c](file:///d:/reactos/win32ss/gdi/ntgdi/palette.c)兄弟对象BRUSHOBJ/CLIPOBJ/SURFOBJ同属 DDI 对象族本文档基于 ReactOS 源代码win32ss/gdi/eng/xlateobj.c/h及关联模块分析2026 年 8 月
返回列表