QColor::valueF()だけじゃない!Qtで「明るさ」を扱う代替メソッド

2025-05-26

QtプログラミングにおけるQColor::valueF()は、QColorオブジェクトが持つHSV (Hue, Saturation, Value) カラーモデルにおける「Value (明度/輝度)」の値をfloat型で取得するための関数です。

HSVカラーモデルは、色を以下の3つの要素で表現します。

  • Value (明度/輝度)
    色の明るさを表します。色がどれだけ暗いか、どれだけ明るいかを示します。
  • Saturation (彩度)
    色の鮮やかさを表します。色がどれだけ純粋な色か、どれだけ灰色に近いかを示します。
  • Hue (色相)
    色の種類(赤、緑、青など)を表します。通常は0〜359の角度で表現されます。

valueF()の機能

QColorクラスでは、色の各成分を整数(0〜255)で取得する関数と、浮動小数点数(0.0〜1.0)で取得する関数が用意されています。

  • float QColor::valueF() const: Value(明度/輝度)の値を浮動小数点数(0.0〜1.0)で返します。0.0が最も暗く、1.0が最も明るい状態です。
  • int QColor::value() const: Value(明度/輝度)の値を整数(0〜255)で返します。0が最も暗く、255が最も明るい状態です。

valueF()は、特に色をより細かく、または標準化された範囲で扱いたい場合に便利です。例えば、グラフィックライブラリによっては色の成分を0.0〜1.0の範囲で扱うことが一般的であるため、valueF()を使用することで他のシステムとの連携がしやすくなります。

#include <QColor>
#include <QDebug>

int main() {
    // 赤色のQColorオブジェクトを作成
    QColor redColor(255, 0, 0);

    // HSV形式でのValue(明度/輝度)を整数で取得
    int valueInt = redColor.value();
    qDebug() << "Value (int):" << valueInt; // 通常は255が出力されます

    // HSV形式でのValue(明度/輝度)をfloatで取得
    float valueFloat = redColor.valueF();
    qDebug() << "Value (float):" << valueFloat; // 通常は1.0が出力されます

    // 暗い青色のQColorオブジェクトを作成
    QColor darkBlueColor(0, 0, 128);

    // HSV形式でのValue(明度/輝度)をfloatで取得
    float darkBlueValueF = darkBlueColor.valueF();
    qDebug() << "Dark Blue Value (float):" << darkBlueValueF; // 128 / 255 ≒ 0.50が出力されます

    return 0;
}


QtのQColor::valueF()自体は非常にシンプルな関数であり、直接的なエラーが発生することは稀です。しかし、その使い方や、他のカラーモデルとの混同、期待する結果とのギャップなどから、誤解や予期せぬ挙動が生じることがあります。ここでは、QColor::valueF()に関連する一般的な落とし穴と、そのトラブルシューティングについて説明します。

期待する「明るさ」とvalueF()の値が一致しない

これが最もよくある誤解です。

  • トラブルシューティング
    • 知覚的な明るさを求める場合
      QColor::valueF()だけでなく、RGB成分(redF(), greenF(), blueF())を人間の視覚特性に合わせて重み付けして計算する(輝度計算)方法を検討してください。一般的な輝度計算式は以下のようになります(Rec. 709標準などに基づいています)。
      // 輝度 (Luminance) の計算例
      float luminance = 0.2126f * color.redF() + 0.7152f * color.greenF() + 0.0722f * color.blueF();
      
      この輝度値は、0.0(黒)から1.0(白)の範囲で、より人間の感覚に近い明るさを表します。
    • HSVモデルの理解を深める
      valueF()は、HSVモデルの定義通りに動作しています。HSVモデルの特性を理解することで、なぜその値が返されるのかを納得できるでしょう。
  • 原因
    valueF()が返す「Value (明度/輝度)」は、HSVカラーモデルにおける明るさであり、人間の視覚が感じる「明るさ」とは必ずしも一致しません。例えば、鮮やかな黄色と鮮やかな青を比較した場合、HSVのValueは両方とも高い(例えば1.0)かもしれませんが、人間の目には黄色の方が明るく見えることがあります。これは、HSVモデルが色の純粋な明るさを定義しているのに対し、人間の知覚は色相によって明るさの感じ方が異なるためです。

色の変換における丸め誤差

  • トラブルシューティング
    • 厳密な浮動小数点比較を避ける
      浮動小数点数を==で比較するのではなく、許容誤差(イプシロン)を設けて比較するようにします。
      const float EPSILON = 0.0001f;
      if (qAbs(color.valueF() - expectedValue) < EPSILON) {
          // 値はほぼ一致している
      }
      
    • 整数値での比較を検討
      0〜255の整数値で十分な精度であれば、value()intを返すバージョン)を使用して丸め誤差のリスクを軽減することもできます。
  • 原因
    QColorは内部的にRGB(Red, Green, Blue)で色を保持しており、HSVへの変換は計算によって行われます。浮動小数点数(float)で値を扱うため、連続的な値の変換においては、ごくわずかな丸め誤差が生じる可能性があります。これは通常、問題になることはありませんが、厳密な比較を行う場合などに影響を与える可能性があります。

無効なQColorオブジェクトからの取得

  • トラブルシューティング
    • QColor::isValid()で確認
      valueF()を呼び出す前に、QColor::isValid()関数を使用してQColorオブジェクトが有効な色を持っているかを確認します。
      QColor myColor; // デフォルトコンストラクタで初期化された無効な色
      // QColor myColor(Qt::red); // 有効な色
      
      if (myColor.isValid()) {
          float val = myColor.valueF();
          qDebug() << "Value:" << val;
      } else {
          qDebug() << "QColor object is invalid.";
      }
      
    • 適切な初期化
      QColorオブジェクトを使用する前に、必ず適切な方法(例: QColor(Qt::red)QColor("#RRGGBB")QColor(r, g, b)など)で初期化してください。
  • 原因
    QColorオブジェクトが有効な色を表していない場合(例: デフォルトコンストラクタで初期化され、まだ色が設定されていない場合など)、valueF()を呼び出すと予期しない値が返される可能性があります。

ゼロ彩度(Saturation)の色におけるvalueF()の意味

  • トラブルシューティング
    • saturationF()と合わせて確認
      彩度が低い色、特にsaturationF()が0.0に近い色の場合、valueF()はその色の明るさを正確に表しますが、その色相は無意味な値になる可能性があることを覚えておきましょう。
    • 灰色の扱いの理解
      灰色はRGB成分が全て同じ値になる色であり、HSVでは彩度が0になります。この状態でのvalueF()は、そのRGB値の大きさ(明るさ)と一致します。
  • 原因
    彩度(Saturation)がゼロ、つまり灰色(黒、白を含む)の色の場合、色相(Hue)は意味を持たなくなります。しかし、Value(明度/輝度)は依然としてその灰色の明るさを表します。この特性を理解せずに「なぜHueが期待通りでないのか」と混乱することがあります。

valueF()とlightnessF()の混同

  • トラブルシューティング
    • カラーモデルの明確化
      どちらのカラーモデル(HSVかHSLか)で色の明るさを扱いたいのかを明確にします。
      • HSV (Hue, Saturation, Value)
        最も明るい色がValue 1.0、最も暗い色がValue 0.0。飽和した色はValue 1.0になる傾向があります。
      • HSL (Hue, Saturation, Lightness)
        黒がLightness 0.0、白がLightness 1.0、飽和した中間調の色がLightness 0.5になる傾向があります。
    • 適切な関数を使用
      目的のカラーモデルに合わせてvalueF()またはlightnessF()を選択してください。
  • 原因
    QtのQColorには、valueF()(HSVのValue)の他に、lightnessF()(HSLのLightness)という似たような名前の関数があります。これらは異なるカラーモデルに基づいているため、異なる値を返します。

QColor::valueF()は、HSVカラーモデルの「Value(明度/輝度)」を浮動小数点数で取得するためのシンプルで強力な関数です。しかし、その値が人間の視覚的な明るさや他のカラーモデルの明るさと異なる場合があるため、これらの違いを理解し、必要に応じて適切な輝度計算などを行うことがトラブルシューティングの鍵となります。 Qt の QColor::valueF() は、HSV (Hue, Saturation, Value) カラーモデルにおける「Value (明度/輝度)」を float 型 (0.0 から 1.0 の範囲) で取得する便利な関数ですが、これに関連する一般的なエラーやトラブルシューティングは、直接この関数がエラーを引き起こすというよりは、QColor オブジェクトの不正な状態や、値の解釈と使用方法に起因することが多いです。

以下に、考えられる一般的な問題とそれに対するトラブルシューティングを説明します。

QColor オブジェクトが不正な状態の場合

valueF()QColor オブジェクトのメソッドであるため、そのオブジェクト自体が有効でない場合、予期せぬ結果やエラーにつながることがあります。

一般的なエラー

  • 無効な QColor オブジェクトからの呼び出し
    QColor が適切に初期化されていない、または無効な色値で作成された場合に、valueF() を呼び出すと、期待する値が得られないことがあります。Qtのドキュメントには、「無効な色を使用した場合の結果は未定義」と記載されています。

トラブルシューティング

  • 適切な初期化
    QColor オブジェクトを初期化する際には、RGB、HSV、CMYK、名前付き色など、使用するコンストラクタが有効な値を受け入れるように注意します。
    • QColor(int r, int g, int b, int a = 255): 各成分は0〜255の範囲。
    • QColor(Qt::GlobalColor color): Qt::red などの定義済み色を使用。
    • QColor(const QString &name): "red" などの色名を使用。ただし、知らない色名の場合は無効な QColor になる可能性があります。
  • isValid() で確認する
    valueF() を呼び出す前に、QColor::isValid() メソッドを使用して QColor オブジェクトが有効な状態であるかを確認します。
    QColor myColor(500, 0, 0); // 無効なRGB値
    if (!myColor.isValid()) {
        qDebug() << "エラー: 無効な色です!";
        // または、デフォルトの色を設定するなど、適切なエラーハンドリングを行う
        myColor = Qt::black;
    }
    float value = myColor.valueF();
    

valueF() の戻り値の解釈の誤り

valueF() は 0.0 から 1.0 の float 値を返しますが、この値を他のシステムやライブラリに渡す際に、そのシステムが期待する範囲と異なる場合に問題が生じることがあります。

一般的なエラー

  • 浮動小数点数の精度に関する考慮不足
    float 型を使用しているため、ごくわずかな精度誤差が生じることがあります。これはほとんどの場合問題になりませんが、厳密な比較を行う場合などには注意が必要です。
  • 値のスケールの不一致
    valueF() は 0.0〜1.0 の範囲ですが、一部のAPIは0〜255、または0〜100(パーセント)の範囲を期待する場合があります。このスケールの変換を忘れると、色が正しく表示されないことがあります。

トラブルシューティング

  • 浮動小数点数の比較
    浮動小数点数を厳密に比較する際には、直接 == 演算子を使用するのではなく、許容誤差 (epsilon) を考慮した比較を行います。
    float val1 = myColor.valueF();
    float val2 = someOtherColor.valueF();
    if (qFuzzyCompare(val1, val2)) { // QtのqFuzzyCompare関数を使用
        qDebug() << "Valueはほぼ同じです。";
    }
    
  • 期待される範囲への変換
    valueF() で取得した値を、使用するAPIが期待する範囲に変換します。
    QColor myColor = Qt::blue;
    float valueF = myColor.valueF(); // 例: 1.0
    int value255 = static_cast<int>(valueF * 255.0f); // 0〜255の範囲に変換
    int value100 = static_cast<int>(valueF * 100.0f); // 0〜100の範囲に変換
    

他のカラーモデルとの混同

QColor はRGB、HSV、CMYKなど複数のカラーモデルを内部で扱えますが、valueF()HSVモデルのValueを返します。他のモデルの明るさや輝度と混同すると、期待する結果と異なることがあります。

一般的なエラー

  • アルファ値との混同
    valueF()は色の明度であり、透明度(アルファ値)とは関係ありません。透明度はalphaF()で取得します。
  • RGBの輝度と混同
    RGBモデルの輝度(例えば、QColor::lightnessF()QColor::redF()などの成分)とHSVのValueを混同してしまう。

トラブルシューティング

  • 意図した通りの関数を使用
    • HSVの明度が欲しい場合は valueF() (0.0-1.0) または value() (0-255)。
    • RGBの輝度が欲しい場合は lightnessF() (0.0-1.0) または lightness() (0-255)。
    • 透明度が欲しい場合は alphaF() (0.0-1.0) または alpha() (0-255)。
  • ドキュメントの確認
    QColor のドキュメントを読み、どの関数がどのカラーモデルのどの成分を返すのかを正確に理解します。

QColor::valueF() 関数自体が直接コンパイルエラーの原因になることは稀ですが、QColor クラスが正しくインクルードされていない、またはQtのGUIモジュールがリンクされていない場合にエラーが発生する可能性があります。

一般的なエラー

  • ライブラリのリンク不足
    QColor クラスが属するQtのモジュール(QtGui または QtWidgets など)がプロジェクトファイル(.pro)に正しく追加されていない。
  • ヘッダファイルの不足
    QColor が定義されているヘッダファイルがインクルードされていない。
  • .pro ファイルにモジュールを追加
    Qtのプロジェクトファイル(.pro)に QtGui モジュールが追加されていることを確認します。
    QT += core gui // または QT += widgets gui
    
    古いQtのバージョンでは QT += gui だけで QColor が使えましたが、新しいバージョンでは widgets など他のモジュールが必要な場合があります。
  • 必要なヘッダをインクルード
    #include <QColor> // 必須
    #include <QDebug> // qlDebug() を使う場合
    


基本的なvalueF()の取得

最も基本的な使い方です。様々な色に対してvalueF()がどのような値を返すかを確認します。

#include <QCoreApplication>
#include <QColor>
#include <QDebug> // qCDebug() を使用するために必要

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    qDebug() << "--- QColor::valueF() の基本的な使用例 ---";

    // 純粋な赤色 (RGB: 255, 0, 0)
    QColor red(255, 0, 0);
    // HSV: Hue=0, Saturation=255, Value=255
    qDebug() << "赤色のValueF:" << red.valueF(); // 1.0 (最も明るい)

    // 半分の明るさの赤色 (RGB: 128, 0, 0)
    QColor darkRed(128, 0, 0);
    // HSV: Hue=0, Saturation=255, Value=128
    qDebug() << "暗い赤色のValueF:" << darkRed.valueF(); // 128/255 ≒ 0.50196

    // 青色 (RGB: 0, 0, 255)
    QColor blue(0, 0, 255);
    // HSV: Hue=240, Saturation=255, Value=255
    qDebug() << "青色のValueF:" << blue.valueF(); // 1.0

    // 黒色 (RGB: 0, 0, 0)
    QColor black(0, 0, 0);
    // HSV: Hue=0, Saturation=0, Value=0
    qDebug() << "黒色のValueF:" << black.valueF(); // 0.0 (最も暗い)

    // 白色 (RGB: 255, 255, 255)
    QColor white(255, 255, 255);
    // HSV: Hue=0, Saturation=0, Value=255
    qDebug() << "白色のValueF:" << white.valueF(); // 1.0

    // 灰色 (RGB: 128, 128, 128)
    QColor gray(128, 128, 128);
    // HSV: Hue=0, Saturation=0, Value=128
    qDebug() << "灰色のValueF:" << gray.valueF(); // 128/255 ≒ 0.50196

    return app.exec(); // QCoreApplicationのイベントループを開始(デバッグ出力には必須ではありませんが、通常のQtアプリケーションの構造を示します)
}

解説

  • グレーや暗い色は、その明るさに応じた中間的な値(0.0〜1.0)を返します。
  • 黒はValueが最小値の0.0になります。
  • 純粋な色(赤、青など)や白はValueが最大値の1.0になります。これは、これらの色が最も明るい状態であることを意味します。
  • QColor オブジェクトを作成し、valueF() を呼び出すだけで、その色のHSVのValue成分を0.0から1.0の範囲で取得できます。

valueF() を使った色の明るさ調整

valueF() を取得し、それを元に新しい色を生成することで、色の明るさを調整できます。

#include <QCoreApplication>
#include <QColor>
#include <QDebug>
#include <QRandomGenerator> // 乱数生成に必要

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    qDebug() << "--- QColor::valueF() を使った明るさ調整 ---";

    QColor originalColor(100, 150, 200); // 青みがかった色
    qDebug() << "元の色 (RGB):" << originalColor.red() << originalColor.green() << originalColor.blue();
    qDebug() << "元の色 (ValueF):" << originalColor.valueF();

    // Value を上げて、より明るい色にする
    // HSV値を取得し、Valueだけを変更して新しいQColorを作成
    qreal h, s, v, a;
    originalColor.getHsvF(&h, &s, &v, &a); // HSVの浮動小数点値を取得

    qreal brighterValue = qMin(v * 1.5f, 1.0f); // Valueを1.5倍し、最大1.0に制限
    QColor brighterColor = QColor::fromHsvF(h, s, brighterValue, a);

    qDebug() << "明るくした色 (RGB):" << brighterColor.red() << brighterColor.green() << brighterColor.blue();
    qDebug() << "明るくした色 (ValueF):" << brighterColor.valueF();

    // Value を下げて、より暗い色にする
    qreal darkerValue = qMax(v * 0.5f, 0.0f); // Valueを0.5倍し、最小0.0に制限
    QColor darkerColor = QColor::fromHsvF(h, s, darkerValue, a);

    qDebug() << "暗くした色 (RGB):" << darkerColor.red() << darkerColor.green() << darkerColor.blue();
    qDebug() << "暗くした色 (ValueF):" << darkerColor.valueF();

    // ランダムな色の明度を変化させる例
    QRandomGenerator generator;
    for (int i = 0; i < 3; ++i) {
        QColor randomColor(generator.bounded(256), generator.bounded(256), generator.bounded(256));
        qDebug() << "\n--- ランダムな色の処理 ---";
        qDebug() << "ランダムな色 (RGB):" << randomColor.red() << randomColor.green() << randomColor.blue();
        qDebug() << "ランダムな色 (ValueF):" << randomColor.valueF();

        randomColor.getHsvF(&h, &s, &v, &a);
        QColor intensifiedColor = QColor::fromHsvF(h, s, qMin(v + 0.2f, 1.0f), a); // Valueを0.2加算して明るくする
        qDebug() << "明るくしたランダムな色 (RGB):" << intensifiedColor.red() << intensifiedColor.green() << intensifiedColor.blue();
        qDebug() << "明るくしたランダムな色 (ValueF):" << intensifiedColor.valueF();
    }

    return app.exec();
}

解説

  • 変更したValue値を使って、QColor::fromHsvF() で新しいQColorオブジェクトを作成します。これにより、色相と彩度を保ったまま明度だけを調整できます。
  • 取得したv (Value) の値を変更(例えば、1.5倍して明るくしたり、0.5倍して暗くしたり)します。qMinqMaxを使って0.0〜1.0の範囲に値をクランプすることが重要です。
  • getHsvF() を使って、現在の色のHue、Saturation、Value、Alphaの浮動小数点値を取得します。

実際のアプリケーションでは、ウィジェットの色を動的に変更する際にvalueF()が役立ちます。

main.cpp

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QSlider>
#include <QLabel>
#include <QColorDialog>
#include <QDebug>

class ColorAdjuster : public QWidget {
    Q_OBJECT // シグナル/スロットを使用するために必要

public:
    ColorAdjuster(QWidget *parent = nullptr) : QWidget(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);

        // 現在の色を表示するラベル
        colorLabel = new QLabel("現在の色");
        colorLabel->setFixedSize(200, 50);
        colorLabel->setAlignment(Qt::AlignCenter);
        updateColorLabel(); // 初期色で更新
        layout->addWidget(colorLabel);

        // 色選択ボタン
        QPushButton *chooseColorButton = new QPushButton("色の選択...");
        layout->addWidget(chooseColorButton);
        connect(chooseColorButton, &QPushButton::clicked, this, &ColorAdjuster::chooseColor);

        // Value (明度) 調整スライダー
        QLabel *valueLabel = new QLabel("明度 (Value):");
        layout->addWidget(valueLabel);

        valueSlider = new QSlider(Qt::Horizontal);
        valueSlider->setRange(0, 100); // 0% から 100%
        valueSlider->setValue(static_cast<int>(m_currentColor.valueF() * 100)); // 初期値設定
        layout->addWidget(valueSlider);
        connect(valueSlider, &QSlider::valueChanged, this, &ColorAdjuster::adjustValue);

        setLayout(layout);
        setWindowTitle("QColor::valueF() サンプル");
    }

private slots:
    void chooseColor() {
        QColor initialColor = m_currentColor;
        QColor newColor = QColorDialog::getColor(initialColor, this, "色の選択");
        if (newColor.isValid()) {
            m_currentColor = newColor;
            updateColorLabel();
            // スライダーの値を現在の色のValueFに合わせて更新
            valueSlider->setValue(static_cast<int>(m_currentColor.valueF() * 100));
        }
    }

    void adjustValue(int sliderValue) {
        // スライダーの値 (0-100) を 0.0-1.0 のfloat値に変換
        qreal newV = static_cast<qreal>(sliderValue) / 100.0f;

        qreal h, s, v, a;
        m_currentColor.getHsvF(&h, &s, &v, &a); // 現在の色のHSVを取得

        // Value だけを新しい値で設定
        m_currentColor.setHsvF(h, s, newV, a);

        updateColorLabel();
    }

    void updateColorLabel() {
        // ラベルの背景色を更新
        QPalette palette = colorLabel->palette();
        palette.setColor(QPalette::Window, m_currentColor);
        colorLabel->setAutoFillBackground(true);
        colorLabel->setPalette(palette);

        // ラベルのテキスト色を背景色に応じて調整
        // 明度が低い場合は白文字、高い場合は黒文字にする
        if (m_currentColor.valueF() < 0.5) {
            colorLabel->setStyleSheet("QLabel { color : white; }");
        } else {
            colorLabel->setStyleSheet("QLabel { color : black; }");
        }

        qDebug() << "現在の色 (RGB):" << m_currentColor.red() << m_currentColor.green() << m_currentColor.blue()
                 << "ValueF:" << m_currentColor.valueF();
    }

private:
    QColor m_currentColor = Qt::red; // 初期色
    QLabel *colorLabel;
    QSlider *valueSlider;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    ColorAdjuster window;
    window.show();

    return app.exec();
}

#include "main.moc" // mocファイルを含める(Qt Creatorを使用している場合は自動生成されます)

プロジェクトファイル (.pro)

QT       += widgets

SOURCES += main.cpp

HEADERS +=
  1. QColor m_currentColor: 現在の選択色を保持します。
  2. chooseColor() スロット:
    • QColorDialog::getColor() を使用してユーザーに色を選択させます。
    • 有効な色が選択されたら、m_currentColor を更新し、updateColorLabel() を呼び出してUIを更新します。
    • 同時に、valueSlider の値も新しい色の valueF() に基づいて更新します。
  3. adjustValue(int sliderValue) スロット:
    • スライダーの値 (0〜100) を 0.0f1.0ffloat 値 (newV) に変換します。
    • m_currentColor.getHsvF() で現在の色のHSV成分を取得します。
    • m_currentColor.setHsvF(h, s, newV, a) を使って、HueとSaturationはそのままに、Valueだけをスライダーの値に合わせて変更します。
    • updateColorLabel() を呼び出してUIを更新します。
  4. updateColorLabel() スロット:
    • QLabel の背景色を m_currentColor に設定します。
    • m_currentColor.valueF() を利用して、背景色の明るさに応じてテキスト色(白または黒)を動的に切り替えます。これにより、背景色が暗い場合は白い文字、明るい場合は黒い文字で、テキストが読みやすくなります。


Qtプログラミングにおいて、QColor::valueF() はHSVカラーモデルの「Value (明度/輝度)」を float 型で取得する非常に便利な関数ですが、目的によっては他の代替メソッドも存在します。これらのメソッドは、異なるカラーモデルの「明るさ」の概念や、色の調整に関する異なるアプローチを提供します。

QColor::value() (整数値でのValue取得)

valueF()の最も直接的な代替は、同じHSVモデルのValueを整数で取得するvalue()関数です。

  • valueF() との違い
    返される値の範囲が0.0〜1.0か、0〜255かの違いです。内部的には同じHSVのValue成分を参照しています。
  • 用途
    主に整数値で色のコンポーネントを扱いたい場合や、レガシーコードとの互換性が必要な場合に利用されます。
  • 機能
    HSVモデルのValueを0〜255の範囲の整数値で返します。


#include <QCoreApplication>
#include <QColor>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QColor red(255, 0, 0);
    int valueInt = red.value();
    float valueFloat = red.valueF();

    qDebug() << "赤色のValue (int):" << valueInt;   // 255
    qDebug() << "赤色のValue (float):" << valueFloat; // 1.0

    QColor darkBlue(0, 0, 128);
    int darkBlueValueInt = darkBlue.value();
    float darkBlueValueFloat = darkBlue.valueF();

    qDebug() << "暗い青色のValue (int):" << darkBlueValueInt;   // 128
    qDebug() << "暗い青色のValue (float):" << darkBlueValueFloat; // 128/255 ≒ 0.50196

    return app.exec();
}

QColor::lightnessF() / QColor::lightness() (HSLモデルの輝度)

QColorはHSL (Hue, Saturation, Lightness) カラーモデルもサポートしており、その「Lightness (輝度)」を取得する関数が提供されています。

  • valueF() との違い
    異なるカラーモデルの概念に基づいています。例えば、純粋な赤色のvalueF()は1.0ですが、lightnessF()は0.5になります(純粋な色が中間的な明るさとして扱われるため)。
  • 用途
    HSVのValueと同様に色の明るさを表しますが、HSVのValueが「純粋な色からどれだけ光を当てたか」という概念に近いのに対し、HSLのLightnessは「白と黒の間の相対的な明るさ」という概念に近いです。一般的に、人間の知覚により近い「明るさ」を表すと言われることがあります。
  • 機能
    HSLモデルのLightnessをfloat型 (0.0〜1.0) または整数型 (0〜255) で返します。


#include <QCoreApplication>
#include <QColor>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QColor red(255, 0, 0);
    qDebug() << "赤色のValueF:" << red.valueF();     // 1.0
    qDebug() << "赤色のLightnessF:" << red.lightnessF(); // 0.5

    QColor blue(0, 0, 255);
    qDebug() << "青色のValueF:" << blue.valueF();     // 1.0
    qDebug() << "青色のLightnessF:" << blue.lightnessF(); // 0.5

    QColor black(0, 0, 0);
    qDebug() << "黒色のValueF:" << black.valueF();     // 0.0
    qDebug() << "黒色のLightnessF:" << black.lightnessF(); // 0.0

    QColor white(255, 255, 255);
    qDebug() << "白色のValueF:" << white.valueF();     // 1.0
    qDebug() << "白色のLightnessF:" << white.lightnessF(); // 1.0

    return app.exec();
}

QColor::darker() / QColor::lighter() (相対的な明るさ調整)

これらの関数は、既存のQColorオブジェクトを基準に、相対的に暗い/明るい新しいQColorオブジェクトを生成します。

  • valueF() との違い
    valueF()は単に明るさの値を取得するだけですが、darker()/lighter()は直接新しい色オブジェクトを生成します。内部的にはHSVのValue成分が使われています。
  • 用途
    UI要素のホバー状態やクリック状態など、基調となる色を保ったまま段階的に明るさを変化させたい場合に便利です。HSVやHSLの値を直接操作するよりも、より手軽に明るさを調整できます。
  • 機能
    現在の色の明るさをfactor(デフォルトはlighter()が150、darker()が200)に基づいて調整した新しいQColorを返します。factorはパーセント値で、100が元の明るさです。


#include <QCoreApplication>
#include <QColor>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QColor baseColor(100, 150, 200); // 基準となる色
    qDebug() << "元の色 (RGB):" << baseColor.red() << baseColor.green() << baseColor.blue();
    qDebug() << "元の色 (ValueF):" << baseColor.valueF();

    // デフォルトの明るさで明るくする
    QColor lighterColor = baseColor.lighter();
    qDebug() << "明るくした色 (lighter()) (RGB):" << lighterColor.red() << lighterColor.green() << lighterColor.blue();
    qDebug() << "明るくした色 (lighter()) (ValueF):" << lighterColor.valueF();

    // デフォルトの明るさで暗くする
    QColor darkerColor = baseColor.darker();
    qDebug() << "暗くした色 (darker()) (RGB):" << darkerColor.red() << darkerColor.green() << darkerColor.blue();
    qDebug() << "暗くした色 (darker()) (ValueF):" << darkerColor.valueF();

    // factorを指定してさらに明るくする (factor=200で2倍の明るさ)
    QColor muchLighterColor = baseColor.lighter(200);
    qDebug() << "さらに明るくした色 (lighter(200)) (RGB):" << muchLighterColor.red() << muchLighterColor.green() << muchLighterColor.blue();
    qDebug() << "さらに明るくした色 (lighter(200)) (ValueF):" << muchLighterColor.valueF();

    // factorを指定してさらに暗くする (factor=300で1/3の明るさ)
    QColor muchDarkerColor = baseColor.darker(300);
    qDebug() << "さらに暗くした色 (darker(300)) (RGB):" << muchDarkerColor.red() << muchDarkerColor.green() << muchDarkerColor.blue();
    qDebug() << "さらに暗くした色 (darker(300)) (ValueF):" << muchDarkerColor.valueF();


    return app.exec();
}

厳密にはvalueF()の代替ではありませんが、RGBカラーモデルから輝度(知覚的な明るさ)を独自に算出する方法も存在します。これは、特定の知覚モデルに合わせた輝度が必要な場合に使われます。

  • valueF() との違い
    valueF()はHSVモデルのValueであり、RGBの各成分の最大値に依存します。一方、RGB輝度計算は、人間の目の感度を考慮した各成分の重み付けに基づいて明るさを算出します。
  • 用途
    画像処理でピクセルの明るさを均一に扱いたい場合や、アクセシビリティの観点からテキストと背景のコントラストを評価したい場合など。
  • 機能
    R, G, B各成分から、加重平均などを用いて色の輝度を算出します。
    • 一般的な輝度計算式の一例: 輝度 = 0.299 * R + 0.587 * G + 0.114 * B


#include <QCoreApplication>
#include <QColor>
#include <QDebug>

// RGB値から知覚的な輝度を計算する関数 (0.0 - 1.0)
float calculatePerceivedBrightness(const QColor& color) {
    // ITU-R BT.709 基準に基づく輝度計算
    // 各成分を0-1の範囲に正規化してから計算
    qreal r = color.redF();
    qreal g = color.greenF();
    qreal b = color.blueF();
    return (0.2126 * r + 0.7152 * g + 0.0722 * b); // QColor::lightnessF() とは異なる係数
}

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QColor red(255, 0, 0);
    QColor green(0, 255, 0);
    QColor blue(0, 0, 255);
    QColor yellow(255, 255, 0); // 黄色は明るく感じやすい

    qDebug() << "--- 異なる明るさの概念の比較 ---";

    qDebug() << "赤色:";
    qDebug() << "  ValueF:" << red.valueF();              // 1.0
    qDebug() << "  LightnessF:" << red.lightnessF();          // 0.5
    qDebug() << "  知覚輝度:" << calculatePerceivedBrightness(red); // 0.2126

    qDebug() << "緑色:";
    qDebug() << "  ValueF:" << green.valueF();            // 1.0
    qDebug() << "  LightnessF:" << green.lightnessF();        // 0.5
    qDebug() << "  知覚輝度:" << calculatePerceivedBrightness(green); // 0.7152 (人間の目で最も明るく感じる)

    qDebug() << "青色:";
    qDebug() << "  ValueF:" << blue.valueF();             // 1.0
    qDebug() << "  LightnessF:" << blue.lightnessF();         // 0.5
    qDebug() << "  知覚輝度:" << calculatePerceivedBrightness(blue);  // 0.0722 (人間の目で最も暗く感じる)

    qDebug() << "黄色:";
    qDebug() << "  ValueF:" << yellow.valueF();            // 1.0
    qDebug() << "  LightnessF:" << yellow.lightnessF();        // 1.0 (HSLのLは彩度0の明るさに等しい)
    qDebug() << "  知覚輝度:" << calculatePerceivedBrightness(yellow); // 0.9278 (赤+緑)

    return app.exec();
}

知覚輝度とlightnessF()の違い

上記の例でわかるように、純粋な緑色はvalueF()lightnessF()が共に1.0(または0.5)であるにもかかわらず、calculatePerceivedBrightnessは0.7152と高い値を示します。これは、人間の目が緑色の光に対して最も敏感であるという特性を反映しているためです。QColor::lightnessF()も知覚的な明るさを考慮しますが、RGBの各成分に異なる重み付けをする上記の輝度計算とは異なるアルゴリズムを使用しています。

QColor::valueF()はHSVカラーモデルのValueを取得しますが、代替手段としては以下が挙げられます。

  1. QColor::value(): 整数値でValueを取得したい場合。
  2. QColor::lightnessF() / QColor::lightness(): HSLモデルのLightness(知覚的な明るさ)を取得したい場合。
  3. QColor::darker() / QColor::lighter(): 相対的に明るさを調整した新しい色を直接生成したい場合。
  4. 独自のRGB輝度計算: 特定の知覚モデルや画像処理の要件に合わせて、RGB成分から輝度を算出したい場合。