2018年7月13日金曜日

Qt で扱える画像フォーマット

QImage と QPixmap で扱える画像フォーマットはQt Image Formats で説明されています。しかし、内容が現状と合わなくなっています。

Qt 5.6 以降で QImage と QPixmap が扱える画像フォーマットは以降のようになっています。

標準のロードフォーマット

BMP CUR DDS*4 GIF HEIC*2 HEIF*2 ICNS ICO JP2*1 JPEG JPG MNG*5 PBM PGM PNG PPM SVG*3 SVGZ*3 TGA TIF TIFF WBMP WEBP XBM XPM

標準のセーブフォーマット

BMP CUR DDS*4 HEIC*2 HEIF*2 ICNS ICO JP2*1 JPEG JPG MNG*5 PBM PGM PNG PPM TIF TIFF WBMP WEBP XBM XPM
*1 Qt 5.7 以上、Windows と Linux はバイナリープラグインなし
*2 Qt 5.11 以上、macOS と iOS のみ。ただし Qt 5.7〜5.10 では libqmacjp2 プラグイン経由で読めてしまうが書き込みはできない。Android と Windows 10 も サポートしているが Qt は未対応。
*3 iOS と Android はなし。
*4 DDS は Qt 5.7 のみ。セキュリティー上の理由から Qt 5.8 でバイナリープラグインなし。
*5 MNG はセキュリティー上の理由から Qt 5.6 でバイナリープラグインなし。

SVG は QSvgGenerator で生成しファイルに保存できます。

JPEG と JPG、TIFF と TIF は画像ファイルサフィックスの違いです。

Qt の画像フォーマットの扱いは GUI アプリケーションとして使うには充分です。しかし、画像フォーマット変換などの画像処理には適さない場合があることに注意が必要です。例えば TIFF 16bit の精度は 8bit になり、BMP の一部の形式は扱えず、セーブ時に画像フォーマットのすべてのオプション指定はできません。

Qt 5.12 で QImage::Format_RGBA64 と QImage::Format_RGBA64_Premultiplied が追加され 16-16-16-16 で使えます。

2018年7月11日水曜日

外部 JavaScript のモジュール化

外部 JavaScript をモジュール化するとファイルパスではなくモジュールとしてインポートできます。
${HOME}/src/qt/examples/qml/javascript/module/
 +-- lib/
 |   +-- jsmodule/
 |   |   +-- qmldir
 |   |   +-- utils.js
 +-- use-jsmodule.qml
モジュール化する外部 JavaScript ファイルを上記のように配置して、qmldir ファイルに以下のように記述します。
qmldir:

Utils 1.0 utils.js
Utils は外部 JavaScript ファイル内の関数や変数、定数を参照するときに指定するプリフィック名で、1.0 はモジュールのバージョン番号 (メジャー.マイナー) です。
utils.js:

.pragma library

function colorName(color) {
    function formatElement(e) {
        return ("00" + Math.round(255*e).toString(16)).slice(-2);
    }

    const r = formatElement(color.r);
    const g = formatElement(color.g);
    const b = formatElement(color.b);
    const a = formatElement(color.a);

    return `#${a}${r}${g}${b}`
}

// Typical mono space font on each platform.
// const monoFont = function() { // Qt 5.11
var monoFont = function() {      // Qt 5.12 regression
    if (Qt.platform.os == "linux") {
        return Qt.font({ family: "DejaVuSansMono" });
    } else if (Qt.platform.os == "windows") {
        return Qt.font({ family: "Lucida Console" });
    } else if (Qt.platform.os == "osx") {
        return Qt.font({ family: "Osaka", styleName: "Regular-Mono" });
    } else {
        return Qt.font({ family: "Lucida Console" });
    }
}();

// Returns a gray for the specified color. Same as qGray() in Qt C++.
function grayFor(color) {
    return ((255*color.r*11 + 255*color.g*16 + 255*color.b*5)/32)/255;
}

// Retruns a contrast gray color for background to clearly display text.
function textColorFor(aBackgroundColor) {
    return grayFor(aBackgroundColor) > 0.5 ? "black" : "white";
}
上記のような外部 JavaScript ファイルを用意したときに、以下のようにしてモジュール化した JavaScript を使えます。
use-jsmodule.qml:

import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.12
import lib.jsmodule 1.0

ApplicationWindow {
    visible: true

    minimumWidth: 300
    minimumHeight: 300

    title: "JavaScript Module"

    Rectangle {
        width: 200
        height: 200
        anchors.centerIn: parent

        radius: 5
        color: Qt.rgba(Math.random(), Math.random(), Math.random())

        Text {
            anchors.centerIn: parent

            text: Utils.colorName(parent.color)
            font {
                family: Utils.monoFont
                pointSize: 32
            }
            color: Utils.textColorFor(parent.color)
        }
    }
}
JavaScript モジュールの import 文には、インポートパス以下の外部 JavaScript ファイルのパスをピリオドで区切って指定します。1.0 は qmldir に記述したバージョン番号です。実行するにはインポートパスを指定して以下のようにします。
$ qml -I ${HOME}/src/qt/examples/qml/javascript/module use-jsmodule.qml

参考情報

Module Definition qmldir Files