QGis二次开发基础 -- 栅格图像增强显示

作为一个GIS软件,对栅格图像的基本支持也是必须的。QGis能够打开显示多种格式的栅格图像,包括常用的JPEG、PNG,以及遥感图像格式ENVI Image、GeoTIF等。今天想来聊一聊简单的几个调整栅格图像对比度、亮度以及拉伸增强显示的基本功能。

关于如何添加数据显示,请参考 栅格矢量数据显示

两个类

QgsRasterLayer

栅格图层 QgsRasterLayer 与 QgsVectorLayer 一样,都是 QgsMapLayer 的子类,是作为地图空间显示的图层对象。这个对象包含了许多栅格图层的属性以及显示方式等方法,今天我们关心的重点在于拉伸显示、对比度、亮度等调整,因此从API文档中,重点关注几个地方:

  • setContrastEnhancement 方法
  • 对比度和亮度的控制

setContrastEnhancement 是栅格图层控制拉伸显示的方法,它通过特定的拉伸方式、拉伸值域范围、显示图像的范围等参数来增强显示的样式。定义如下:
这里写图片描述
其中我们需要特别关注前三个参数。

QgsContrastEnhancement::ContrastEnhancementAlgorithm 为选用的拉伸算法,具体包括:

  • NoEnhancement –> 无增强
  • StretchToMinimumMaximum –> 最小最大值拉伸
  • StretchAndClipToMinimumMaximum –> 最小最大值拉伸并裁剪值域范围
  • ClipToMinimumMaximum –> 裁剪值域范围到最小最大值
  • UserDefinedEnhancement –> 用户自定义

而 QgsRaster::ContrastEnhancementLimits 为控制增强的值域范围,包括:

  • ContrastEnhancementNone –> 无增强
  • ContrastEnhancementMinMax –> 最小最大值(默认)
  • ContrastEnhancementStdDev –> 标准差方差范围
  • ContrastEnhancementCumulativeCut –> 累计裁剪范围

QgsRectangle 就是选择要统计值域的范围了,这个参数可以控制拉伸是用全图的值域拉伸还是仅仅根据当前显示范围的值域进行拉伸。

从QgsRasterLayer 的API文档中,我们看到分别包含一个控制对比度显示的类 QgsBrightnessContrastFilter 的引用,于是下面我们关注一下这个类。

QgsBrightnessContrastFilter

QGis中用于控制栅格图像对比度和亮度的对象为 QgsBrightnessContrastFilter ,来看看他的基本方法:
QGis二次开发基础 -- 栅格图像增强显示_第1张图片
可以看到,调整栅格图层显示亮度的方法为 setBrightness(), 调整显示对比度的方法为 setContrast()。很明了,利用这两个方法就能控制亮度和对比度了,非常简单。

两个方法

QGis当中控制栅格图层增强的工具栏上大概有8个按钮,如图所示:

这里写图片描述
前面4个控制拉伸显示,后面4个分别是亮度和对比度的增加、减少。

我们刚才讲了,拉伸显示具有好几种方式,为了能够重用代码,QGis将工具栏中这几个按钮的事件进行了整合,定义了两个基本函数:

  • histogramStretch
  • adjustBrightnessContrast

调用这两个函数,但传递不同参数来控制不同的显示方式。下面给出这两个函数的实现代码并做相应注释说明:

void qgis_dev::histogramStretch( bool visibleAreaOnly /*= false*/, QgsRaster::ContrastEnhancementLimits theLimits /*= QgsRaster::ContrastEnhancementMinMax */ )
{
    QgsMapLayer* myLayer = m_layerTreeView->currentLayer();
    if ( !myLayer ) // 判断是否为地图图层
    {
        return;
    }

    QgsRasterLayer* myRasterLayer = qobject_cast<QgsRasterLayer*>( myLayer );
    if ( !myRasterLayer ) // 判断是否为栅格图层
    {
        return;
    }

    QgsRectangle myRectangle;
    if ( visibleAreaOnly ) // 这里控制是否仅用当前可见范围的值域进行拉伸
    {
        myRectangle = m_mapCanvas->mapSettings().outputExtentToLayerExtent( myRasterLayer, m_mapCanvas->extent() );
    }
    // 这一句是关键
    myRasterLayer->setContrastEnhancement( QgsContrastEnhancement::StretchToMinimumMaximum, theLimits, myRectangle );
    m_mapCanvas->refresh();
}
void qgis_dev::adjustBrightnessContrast( int delta, bool updateBrightness /*= true */ )
{
    foreach( QgsMapLayer* layer, m_layerTreeView->selectedLayers() ) // 遍历所有选择的图层
    {
        if ( !layer )// 判断是否为地图图层
        {
            return;
        }

        QgsRasterLayer* rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
        if ( !rasterLayer )// 判断是否为栅格图层
        {
            return;
        }

        // 这里是关键,用QgsBrightnessFilter类控制亮度与对比度
        QgsBrightnessContrastFilter* brightnessFilter = rasterLayer->brightnessFilter();
        if ( updateBrightness )
        {
            brightnessFilter->setBrightness( brightnessFilter->brightness() + delta );
        }
        else
        {
            brightnessFilter->setContrast( brightnessFilter->contrast() + delta );
        }

        rasterLayer->triggerRepaint(); // 重画栅格图层
    }
}

封装调用

我想调用起来就已经很简单了,不过是不同参数的组合而已。这里就以QGis控制栅格图层增强显示的这几个工具为例,给出它们的实现代码。

/// 显示栅格图像的一些功能定义
    //! 局部拉伸显示
    void localHistogramStretch();
    //! 全局拉伸显示
    void fullHistogramStretch();
    //! 局部累计裁剪拉伸显示
    void localCumulativeCutStretch();
    //! 全局累计裁剪拉伸显示
    void fullCumulativeCutStretch();
    //! 增加显示亮度
    void increaseBrightness();
    //! 减少显示亮度
    void decreaseBrightness();
    //! 增加显示对比度
    void increaseContrast();
    //! 减少显示对比度
    void decreaseContrast();
// 以下是实现
void qgis_dev::localHistogramStretch()
{
    histogramStretch( true, QgsRaster::ContrastEnhancementMinMax );
}

void qgis_dev::fullHistogramStretch()
{
    histogramStretch( false, QgsRaster::ContrastEnhancementMinMax );
}

void qgis_dev::localCumulativeCutStretch()
{
    histogramStretch( true, QgsRaster::ContrastEnhancementCumulativeCut );
}

void qgis_dev::fullCumulativeCutStretch()
{
    histogramStretch( false, QgsRaster::ContrastEnhancementCumulativeCut );
}

void qgis_dev::increaseBrightness()
{
    int step = 1;
    if ( QgsApplication::keyboardModifiers() == Qt::ShiftModifier )
    {
        step = 10;
    }
    adjustBrightnessContrast( step );
}

void qgis_dev::decreaseBrightness()
{
    int step = -1;
    if ( QgsApplication::keyboardModifiers() == Qt::ShiftModifier )
    {
        step = -10;
    }
    adjustBrightnessContrast( step );
}

void qgis_dev::increaseContrast()
{
    int step = 1;
    if ( QgsApplication::keyboardModifiers() == Qt::ShiftModifier )
    {
        step = 10;
    }
    adjustBrightnessContrast( step, false );
}

void qgis_dev::decreaseContrast()
{
    int step = -1;
    if ( QgsApplication::keyboardModifiers() == Qt::ShiftModifier )
    {
        step = -10;
    }
    adjustBrightnessContrast( step, false );
}

最后,有关QGis二次开发这个系列博客的内容,我整合到了一个工程中并放在了GitHub上,地址是 https://github.com/Jacory/qgis_dev, 需要参考的同学可以直接去clone或者fork代码。

谢谢阅读。

你可能感兴趣的:(Gis)