一、基础定位、头文件、继承关系
1. 引入头文件
#include<qgssinglebandpseudocolorrenderer.h>2. 继承链
QgsRasterRenderer ↳ QgsSingleBandRenderer ↳ QgsSingleBandPseudoColorRenderer- QgsRasterRenderer:栅格渲染器顶层抽象基类,所有栅格渲染器统一父类,定义
block()、clone()、XML读写、透明度等通用接口; - QgsSingleBandRenderer:单波段渲染器公共父类,封装「渲染波段号」基础逻辑;
- QgsSingleBandPseudoColorRenderer:单波段伪彩色渲染器,专门实现单波段数值→渐变色/分级上色(DEM、NDVI、温度热力图底层渲染器)。
3. 完整渲染链路总览
QgsRasterLayer ↓ QgsSingleBandPseudoColorRenderer (当前讲解对象:控制渲染波段、透明度、持有QgsRasterShader) ↓ QgsRasterShader (scale/offset、拉伸min/max、Nodata透明、亮度对比度) ↓ QgsColorRampShader (分段色标、插值渐变/离散/精确匹配逻辑)4. 核心职责
- 指定要渲染的目标波段(1起始);
- 持有唯一
QgsRasterShader着色器实例,所有数值转颜色逻辑由shader提供; - 实现栅格像素块渲染入口
block(),从provider读取像素、调用shader上色、输出RGBA画布; - 统一管理图层透明度、灰度转换、图层混合模式;
- 提供克隆、序列化XML(保存到qgs工程)。
二、构造函数
// 空构造,无数据源、无shader,仅用于反序列化加载工程QgsSingleBandPseudoColorRenderer();// 标准业务构造(最常用)// provider:栅格数据源;bandNo:渲染波段;shader:着色器(传入后renderer接管内存)QgsSingleBandPseudoColorRenderer(QgsRasterDataProvider*provider,intbandNo,QgsRasterShader*shader=nullptr);三、核心属性读写API
1. 渲染波段(继承自 QgsSingleBandRenderer)
// 获取当前渲染波段intband()const;// 修改渲染波段,切换后需要重新统计极值、刷新shader拉伸区间voidsetBand(intbandNo);注意:波段号从1开始,传0会渲染失效。
2. 着色器 QgsRasterShader 管理(核心)
// 获取内部着色器,可修改min/max、scale/offset、shaderFunctionQgsRasterShader*rasterShader()const;// 设置新着色器,renderer 获得 shader 所有权,自动释放旧shadervoidsetRasterShader(QgsRasterShader*shader);内存规则:
setRasterShader()传入的shader由渲染器托管,外部禁止手动delete;- 替换shader时,旧着色器会自动销毁,无内存泄漏。
3. 图层全局透明度(继承 QgsRasterRenderer)
// 透明度 0~100,0完全不透明,100完全透明intopacity()const;voidsetOpacity(intopacity);4. 图层混合模式(叠加、正片叠底等)
QPainter::CompositionModecompositionMode()const;voidsetCompositionMode(QPainter::CompositionMode mode);5. Nodata全局透明开关(兼容层,实际优先走shader透明配置)
boolusesTransparentNodata()const;voidsetUsesTransparentNodata(booltransparent);四、核心渲染入口函数 block()
函数签名(重写父类虚函数)
QgsRasterBlock*block(constQgsRectangle&extent,intwidth,intheight,QgsRasterBlockFeedback*feedback=nullptr)override;功能:生成RGBA彩色像素块,供画布绘制
内部完整执行步骤
- 调用
provider->readBlock(band(), extent, width, height)读取原始单波段浮点像素块; - 创建RGBA 4通道输出像素块(Byte类型,0~255);
- 遍历每一行每一列像素:
- 判断是否Nodata:若shader开启透明Nodata,直接填充Alpha=0;
- 取出原始rawVal,交给
rasterShader()->shade()计算RGBA; - 应用图层全局透明度opacity衰减Alpha通道;
- 返回彩色RGBA像素块,上层绘图组件渲染;
- 进度反馈
feedback用于大影像渲染时进度条、取消渲染。
五、克隆、序列化(工程保存/加载必备)
1. 深度克隆 clone()
QgsRasterRenderer*clone()constoverride;- 完整复制:波段号、透明度、混合模式、内部完整QgsRasterShader(连带内部QgsColorRampShader色标列表深度拷贝);
- 返回全新渲染器对象,使用完成必须手动delete。
2. XML读写 writeXml / readXml
voidwriteXml(QDomDocument&doc,QDomElement&parentElem)constoverride;voidreadXml(constQDomElement&rendererElem)override;存储内容:
- 渲染波段、透明度、混合模式;
- 完整序列化
QgsRasterShader(min/max、scale/offset、亮度对比度、transparentNodata); - 嵌套序列化
QgsColorRampShader(全部色标、插值模式clip开关等)。
QGIS工程保存、样式文件(.qml)读写底层依赖这两个接口。
六、自动生成拉伸区间工具函数(高频业务接口)
// 根据栅格波段统计,自动填充shader的min/max(原始像素值,scale=offset=0场景)voidsetShaderMinMaxToNone();voidsetShaderMinMaxToFullExtent();voidsetShaderMinMaxToCurrentExtent(constQgsRectangle¤tExtent);常用场景
// 自动用整幅栅格的波段极值填充shader拉伸窗口renderer->setShaderMinMaxToFullExtent();内部逻辑:调用provider->bandStatistics()获取min/max,赋值给shader的minimumValue/maximumValue。
七、完整分层协作示例代码(DEM伪彩色渲染)
#include<qgsrasterdataprovider.h>#include<qgsrasterbandstats.h>#include<qgsrastershader.h>#include<qgsrastercolorrampshader.h>#include<qgssinglebandpseudocolorrenderer.h>#include<qgsrasterlayer.h>// DEM单波段伪彩色渲染封装函数voidsetupDemPseudoColorRender(QgsRasterLayer*demLayer){QgsRasterDataProvider*prov=demLayer->dataProvider();if(!prov||!prov->isValid())return;intrenderBand=1;// 1. 统计波段原始极值QgsRasterBandStats stats=prov->bandStatistics(renderBand,QgsRasterBandStats::Min|QgsRasterBandStats::Max);if(!stats.isValid())return;// 2. 构建色标(无scale/offset,displayVal=rawVal)QList<QgsColorRampItem>items;items.append(QgsColorRampItem(stats.minVal,QColor(10,40,200),"低海拔"));items.append(QgsColorRampItem((stats.minVal+stats.maxVal)/2,QColor(30,190,50),"中海拔"));items.append(QgsColorRampItem(stats.maxVal,QColor(210,20,20),"高海拔"));// 3. 色带着色函数QgsColorRampShader*rampFunc=newQgsColorRampShader(items,QgsColorRampShader::Interpolated);rampFunc->setClipBelow(true);rampFunc->setClipAbove(true);// 4. 外层ShaderQgsRasterShader*shader=newQgsRasterShader();shader->setMinimumValue(stats.minVal);shader->setMaximumValue(stats.maxVal);shader->setTransparentNodata(true);shader->setRasterShaderFunction(rampFunc);// 5. 创建伪彩色渲染器(核心类)QgsSingleBandPseudoColorRenderer*render=newQgsSingleBandPseudoColorRenderer(prov,renderBand,shader);render->setOpacity(90);// 图层透明度90%render->setCompositionMode(QPainter::CompositionMode_SourceOver);// 6. 绑定到栅格图层demLayer->setRenderer(render);demLayer->triggerRepaint();// 刷新画布}八、与其他栅格渲染器对比区分
| 渲染器类 | 用途 | 是否依赖 QgsRasterShader |
|---|---|---|
| QgsSingleBandPseudoColorRenderer | 单波段渐变/分级伪彩色(DEM、NDVI、热力图) | ✅ 必须依赖 |
| QgsSingleBandGrayRenderer | 单波段黑白灰度拉伸 | ✅ 依赖灰度shader |
| QgsMultiBandColorRenderer | RGB三波段真彩色遥感影像 | ❌ 无shader,直接合成三色 |
| QgsPalettedRasterRenderer | 索引色栅格(自带色表) | ❌ |
关键区分
QgsSingleBandGrayRenderer和QgsSingleBandPseudoColorRenderer同属单波段渲染器,都持有QgsRasterShader:
- 灰度渲染器内部shaderFunction是灰度映射;
- 伪彩色渲染器搭配
QgsColorRampShader实现多色渐变分级。
九、开发高频踩坑点
1. 内存所有权问题
// 正确:renderer接管shader,无需手动delete shaderQgsRasterShader*shader=newQgsRasterShader();QgsSingleBandPseudoColorRenderer*render=newQgsSingleBandPseudoColorRenderer(prov,1,shader);// 错误:外部手动delete shader,渲染器析构时二次释放崩溃deleteshader;2. scale/offset 存在时,shader min/max 不能填原始波段极值
QgsSingleBandPseudoColorRenderer只负责持有shader,不会自动换算scale/offset后的区间;
需要手动计算displayMin = (rawMin-offset)*scale赋值给shader。
3. 切换波段后极值不刷新
调用setBand(2)切换渲染波段后,旧shader的min/max仍是波段1的区间,必须重新统计并更新shader拉伸窗口。
4. 浮点栅格使用 Exact 模式匹配失败
Exact精确匹配仅适合整型分类栅格,浮点存在精度误差,渲染器会大面积透明。
5. 渲染器替换后图层不刷新
修改完renderer必须调用layer->triggerRepaint()触发画布重绘。
6. 多线程渲染限制
block()内部会读取provider,GDAL驱动非线程安全,多线程并行渲染同一图层需要加互斥锁。
十、典型业务使用场景
- DEM数字高程模型渐变伪彩色渲染;
- NDVI、NDWI植被指数热力分级;
- 气温、降雨量、污染物浓度热力图;
- 坡度、地形起伏度离散分级设色;
- 单波段灰度数据自定义渐变色展示。
十一、类层级结构精简总结
QgsRasterRenderer (顶层栅格渲染器) └── QgsSingleBandRenderer (单波段公共父类:管理波段号) └── QgsSingleBandPseudoColorRenderer ├─ 成员:QgsRasterShader* mShader ├─ 核心方法:block() 输出RGBA彩色像素块 ├─ 辅助:setShaderMinMaxToFullExtent() 自动拉伸 ├─ 生命周期:clone()、writeXml/readXml 序列化 └─ 配置:透明度、图层混合模式