现在的位置: 首页 > 综合 > 正文

Qt Quick里的图形效果——颜色(Color)

2016年10月22日 ⁄ 综合 ⁄ 共 6171字 ⁄ 字号 评论关闭

    Qt Quick提供了通过改变一个 Item 的颜色来产生各种各样效果的元素。有下面几种:

  • BrightnessContrast,调整亮度和对比度
  • ColorOverlay,在源 Item 上覆盖一层颜色
  • Colorize,设置源 Item 的 HSL 颜色空间
  • Desaturate,降低颜色的饱和度
  • GammaAdjust,使用 gamma 曲线来改变源 Item 的照度
  • HueSaturation,在 HSL 颜色空间改变源 Item 的颜色
  • LevelAdjust,在 RGBA 颜色空间调整源 Item 的颜色水平

    因为有多种颜色效果,每种又支持不同的、可调整的属性,所以在设计示例时和上次讲的 Blend 又有不同。

ColorExample示例介绍

    我设计了一个示例: ColorExample.qml 。这个 QML 文档与 BlendExample 一样,都被加入到 GraphicalEffects 项目中的 qrc 中。使用到的图片 bug.jpg 和 butterfly.png 也在 qrc 中。

    看一下效果:

                图 1 颜色效果示例

    如图 1 所示,界面分三个部分,与 Blend 示例类似。上方是原始图片,下方左侧是颜色效果类型列表,下方右侧用来展示某个效果类型的用法和效果。

    如你所见,右下方白色背景那部分,会根据 Color Effects 列表中的条目而变化,是动态加载的,在代码中通过 Loader 来动态加载某个效果对应的 qml 文档。

    到现在为止,我们的示例中的 qml 文档,已经分了三层:

  1. main.qml 构造最外层的示例框架
  2. ColorExample.qml 实现颜色效果的框架
  3. BrightnessContrastEx.qml 之类 qml 文档展示某个特定的颜色效果类的用法

颜色效果元素

    颜色效果种类太多了,我真想说:看 Qt 帮助去吧。可这太不负责任了不是,所以我决定还是挑一个来讲一下,就挑 BrightnessContrast 吧,它不是最简单的,也不是复杂的。

    与 Blend 类似的是,各种颜色效果元素操作 source 的结果是产生一个新的 Item 。不同的是,颜色效果元素只有一个 source 属性,没有 foregroundSource 属性,即:它只需要一个源 Item ,通过改变源 Item 的颜色来产生图形效果。

BrightnessContrast

    看名字就知道了,这个元素是改变亮度和对比度的,所以它有两个属性, brightness 和 contrast ,分别改变源 Item (通过 source 属性指定)的亮度和对比度;它们的取值范围都是 -1.0 ~ 1.0 ,默认值都是 0.0 。

    另外还有一个 cached 属性,介绍 Blend 时已经提到了,设置为 true 可以缓存处理后的图像,提高渲染速度。默认值为 false 。

    每一个颜色效果的示例我都在一个单独的 qml 文档中实现,当用户点击图 1 中的颜色效果列表时,通过改变 Loader 的 source 属性来动态加载对应的 QML 文档。 BrightnessContrast 对应的 qml 文档是 BrightnessContrastEx.qml ,内容如下:

import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.2

Rectangle {
    anchors.fill: parent;
    Image {
        id: opImage;
        x: 4;
        y: 4;
        width: 250;
        height: 250;
        source: "bug.jpg";
        sourceSize: Qt.size(250, 250);
        smooth: true;
        visible: false;
    }

    BrightnessContrast {
        anchors.fill: opImage;
        source: opImage;
        brightness: bslider.value;
        contrast: cslider.value;
    }
    Text {
        id: blabel;
        text: "Brightness:";
        anchors.left: opImage.left;
        anchors.top: opImage.bottom;
        anchors.margins: 4;
    }

    Slider {
        id: bslider;
        anchors.left: blabel.right;
        anchors.leftMargin: 8;
        anchors.verticalCenter: blabel.verticalCenter;
        width: 200;
        height: 40;
        minimumValue: -1.0;
        value: 0.5;
    }
    Text {
        id: clabel;
        text: "Contrast:";
        anchors.left: blabel.left;
        anchors.top: bslider.bottom;
        anchors.topMargin: 4;
    }

    Slider {
        id: cslider;
        anchors.left: bslider.left;
        anchors.verticalCenter: clabel.verticalCenter;
        width: 200;
        height: 40;
        minimumValue: -1.0;
        value: 0.5;
    }
}

    看到 BrightnessContrast 对象的定义你可能觉得很熟悉,没错,和 “”一文中Blend 对象的定义类似。这里我把 brightness 属性绑定到 id 为 bslider 的滑块上,bslider 的 minimumValue 设置为 -1.0 ,默认的 maximumValue 默认为 1.0 ,不需要改变。 contrast 属性是类似的。

    当我们拖动滑块时, BrightnessContrast 对象的相应属性值就会随着滑块的拖动而改变,我们看到的目标 Item 的效果就跟着变了。

LevelAdjust

    这个是颜色效果里最复杂的了……说了这个就不说了,其它的就看帮助吧。先看下效果:

                           图2 LevelAdjust 效果

    LevelAdjust 元素可以根据 gamma 曲线调整源 Item 的 R 、 G 、 B 三个通道的颜色值,这个比 GammaAdjust 更彪悍。 可以用 Qt.vector3d() 构造一个 3d 向量赋值给 LevelAdjust 的 gamma 属性,图 2 就是这么干的。如你所见,我把 3D 向量的构造代码显示出来了,你点击它,可以调出一个对话框,对话框上有三个 Slider 。如下图所示:

               图 3 GammaVector对话框    

    这个对话框我定义在 GammaVector.qml 文档中,代码如下:

import QtQuick 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2

Rectangle {
    id: gammaCreator;
    width: 250;
    height: 30;
    property vector3d gamma: Qt.vector3d(1.0, 1.0, 1.0);
    signal selected();
    color: "lightgray";
    border.width: 1;
    border.color: "darkgray";

    Text {
        id: gammaLabel;
        anchors.centerIn: parent;
        text: "Qt.vector3d(1.0, 1.0, 1.0)";
        color: "darkblue";
    }

    MouseArea {
        anchors.fill: parent;
        onClicked: vectorDlg.visible = true;
    }

    Dialog {
        id: vectorDlg;
        visible: false;
        width: 300;
        height: 200;
        standardButtons: StandardButton.Ok | StandardButton.Cancel;

        onAccepted: {
            gammaCreator.gamma = Qt.vector3d(one.value, two.value, three.value);
            gammaLabel.text = "Qt.vector3d(%1,%2,%3)".arg(one.value.toFixed(1)).arg(two.value.toFixed(1)).arg(three.value.toFixed(1));
            gammaCreator.selected();
        }

        Grid {
            x: 0;
            y: 4;
            width: 300;
            height: 120;
            verticalItemAlignment: Grid.AlignVCenter;
            columns: 3;
            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: one;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }

            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: two;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }

            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: three;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }
        }
    }
}

    关于 QML 里 Dialog 元素的用法,请参考 Qt 帮助吧。

    minimumInput 和 maximumInput 这两个属性是一对。 minimumInput 设定像素的黑色阈值,当一个像素的值小于 minimumInput 指定的颜色值时,就会被替换为黑色。maximumInput 设定像素的白色阈值,当一个像素的值大于 maximumInput 指定的颜色值时,就会被替换为白色。PhotoShop 里有这样的功能,可以批量把一个图片内低于给定值的像素修改为黑色。

    minimumOutput 和 maximumOutput 是一对。minimumOutput 定义每个颜色通道的最小输出水平,这个值增加会让黑暗的区域变量,同时会降低对比度。maximumOutput 定义每个颜色通道的最大输出水平,减小这个值会让明亮的区域变暗,同时会降低对比度。

    minimumInput 、 maximumInput 、 minimumOutput 、 maximumOutput 四个属性的取值范围都是 "#00000000" 到 "#FFFFFFFF"。

    为了让用户能够选择一个颜色,我定义了一个单独的组件(ColorPicker.qml),如果你在图2中看到的那样,点击可以弹出一个颜色选择对话框,选择后这个组件就会改变自己的颜色,并将新颜色的值以字符串("#AARRGGBB")的形式显示出来。用起来还比较方便。

    好了, LevelAdjust 介绍完了,我们看一下 LevelAdjustEx.qml 吧:

import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.2

Rectangle {
    anchors.fill: parent;
    Image {
        id: opImage;
        x: 4;
        y: 4;
        width: 220;
        height: 220;
        source: "butterfly.png";
        sourceSize: Qt.size(220, 220);
        smooth: true;
        visible: false;
    }

    LevelAdjust {
        id: level;
        anchors.fill: opImage;
        source: opImage;
        minimumInput: minInput.color;
        maximumInput: maxInput.color;
        minimumOutput: minOutput.color;
        maximumOutput: maxOutput.color;
    }

    GammaVector {
        id: gammaSelector;
        anchors.left: opImage.left;
        anchors.top: opImage.bottom;
        anchors.topMargin: 4;
        onSelected: level.gamma = gammaSelector.gamma;
    }

    Grid {
        anchors.top: gammaSelector.bottom;
        anchors.topMargin: 4;
        anchors.left: gammaSelector.left;
        columns: 4;
        rowSpacing: 4;
        columnSpacing: 2;
        verticalItemAlignment: Grid.AlignVCenter;
        Text {
            text: "minimumInput:";
        }
        ColorPicker {
            id: minInput;
            width: 90;
            height: 28;
            color: "#00000000";
        }
        Text {
            text: "maximumInput:";
        }
        ColorPicker {
            id: maxInput;
            width: 90;
            height: 28;
            color: "#ffffffff";
        }
        Text {
            text: "minimumOutput:";
        }
        ColorPicker {
            id: minOutput;
            width: 90;
            height: 28;
            color: "#00000000";
        }
        Text {
            text: "maximumOutput:";
        }
        ColorPicker {
            id: maxOutput;
            width: 90;
            height: 28;
            color: "#ffffffff";
        }
    }
}

    具体代码不分析了。

    -------------------------

    图 1 中列出的颜色效果元素,限于篇幅,就不一一介绍了,问道 Qt 帮助吧。

--------

回顾一下我的Qt Quick系列文章:

抱歉!评论已关闭.