本書で使うQtの機能とその使用法

  1. C++について
  2. Qtの導入
  3. 画像処理で有用なQtのクラス
  4. Qtのプログラミングの雛形と例

C++について

C++では、変数と関数をひとまとめにした、クラスという概念を用いる。
クラスは構造体を拡張したようなものであり、構造体の扱いによく似ている。 構造体に対しての知識が不足しているものはC言語の構造体を学んでおくと、 理解しやすいだろう。

クラス内の関数の呼び方

クラスは変数と関数をひとまとめにしたものである。
変数へのアクセスと全く同じであるが簡単に例を示しておく。

Fooクラスのvoid fanc()関数を呼ぶ場合

Foo foo;//Fooクラスオブジェクトの宣言
foo.fanc();

このようにオブジェクトの実体が宣言された場合、 「.」(ドット)で関数を呼び出せる。

ポインタ型のFooクラスのvoid fanc()を呼ぶ場合

Foo* foo;//ポインタ型Fooクラスオブジェクトの宣言
foo = new Foo();//Fooクラスオブジェクトの生成
foo->fanc();

このようにオブジェクトへのポインタが宣言された場合、 「->」で関数を呼び出せる。

Qtの導入

各OSのQtのインストール,インストール、 設定方法を参照してほしい。

画像処理で有用なQtのクラス

不要と思われる引数をいくつか省略したものもあり、 また、各クラスにはその他有用な関数が容易されている。 詳しくはマニュアル を参照すること。

QLabelクラス

QLabelクラスはテキストや図のラベルを管理するクラスである。 また、このクラスはQWidgetを継承しており、windowの機能も持っている。
画像を表示するために使用する。

void show ()

windowを表示する(宣言するだけでは表示されない)。

void setFixedWidth(int width)

windowの幅をwidthに修正する。

void setFixedHeight(int Height);

windowの高さをHeightに修正する。

void setCaption("string");

windowに表示されるタイトル(キャプション)を文字列(string)で与える。

void setPixmap(QPixmap pixmap);

windowにpixmapをセットする。

Pixmap とは「作業用ウィンドウ」と思えばよい。 文字も描けるし、線も描ける。Pixmap と Window はとても似ている。 違うのは「画面に直接表示できない」こと。 Window に対して線を引くと、実際に画面上に線が引かれるが Pixmap に対して行っても実際には見えない。
Pixmap から Window にコピーすると画面上では、瞬時に Window に線や文字が描画されたように見える。 ちらつきが起こらないという利点がある。


QApplication

GUIアプリケーションのコントロールと主要の設定を行うためのクラスである。 Qtを使ったアプリケーションには 必ず一つのQApplicationオブジェクトが必要で、また、どのオブジェクトよりも先に宣言される必要がある。

void setMainWidget(QWidget *mainWidget)

メインとなるwidgetを指定する関数。


QImageクラス

QImageクラスは画像の入出力、処理のための関数を提供する。

int width()

画像の幅を返す。

int height()

画像の高さを返す。

QImage copy()

画像をコピーする("="で代入するだけでは、参照が渡され、コピー出来ない)

bool load("fileName")

画像ファイルを読み込む。対応するファイル形式は、BMP、PPM、PBM、PGM、PNG、JPGなど。 成功したらTRUEを返す。

bool save("fileName", "format")

画像ファイルを指定ファイル名、フォーマットで保存する。 成功したらTRUEを返す。

QRgb pixel(int x, int y)

指定座標のピクセルの色情報を得る。
赤緑青の値はそれぞれ、int qRed(QRgb), int qGreen(QRgb), int qBlue(QRgb)
得ることができる。
また、グレーの値はint qGray(QRgb)で得ることが出来る。

void setPixel(int x, int y, QRgb qRgb)

指定座標のピクセルを指定色にする。


QPixmap

図などを描画するためのクラス。QLabelに画像を設置するには QPixmapでなくてはならない。そのため、QImageからQPixmapに変換し それを保持するために用いる。

QPixmap convertFromImage(QImage image)

QImageをQPixmapに変換し、そのQPixmapを返す関数。

QString

Qtで扱われる文字列を管理するクラス。ここでは、定石としてしまって構わない。

QString::QString ( const char * str )

C言語で扱われる文字列をQStringに変換する。

雛形

ここで画像処理プログラムの雛形として、

  1. モノクロ画像を読み込み
  2. 画像処理の関数を呼び
  3. 結果を別windowに表示させる

を行うプログラムを雛形として作成する。

#include<stdio.h>
#include<stdlib.h>
#include<qlabel.h>
#include<qpixmap.h>
#include<qimage.h>
#include<qapplication.h>

//本来はParam.h内で定義し、includeする。
#define X_SIZE 256
#define Y_SIZE 256	
///////////////////////////////////////

int main( int argc, char *argv[]);//本来はProto.h内で定義し、includeする

/*********************************************************************
    main fanction
*********************************************************************/
int main( int argc, char *argv[] ){
    QApplication application( argc, argv );
    QLabel widget_in(NULL, "in");//window for input image    
    QLabel widget_out(NULL, "out");//window for output image
    QImage input_image, output_image;//Input image and output image    
    QPixmap pixmap_in, pixmap_out;//pixmap for label
    char inFilename[20], outFilename[20];
    int saveCheck;
    int loop_x, loop_y;

    //グレースケールデータ格納配列
    unsigned char image_in[Y_SIZE][X_SIZE];
    unsigned char image_out[Y_SIZE][X_SIZE];
    
    application.setMainWidget( &widget_in );//Set main application
    
    //Load image
    printf("Please input oepn file name : ");
    scanf("%s", inFilename);
    if(!input_image.load(QString::QString(inFilename))){
        printf("Can't load the file.\n");
        exit(0);
    }
    
    //出力画像を初期化
    output_image = QImage(X_SIZE, Y_SIZE, 32); 
    
    //配列に格納する
    for(loop_y=0; loop_y<Y_SIZE; loop_y++){
        for(loop_x=0; loop_x<X_SIZE; loop_x++){
            image_in[loop_y][loop_x] = 
                (char)qGray(input_image.pixel(loop_x, loop_y));
        }
    }
    
    /********************************************************************
    ここで自作の関数を呼び、出力画像の配列(image_out)にデータを格納する
    *********************************************************************/
    
    //配列から画像に格納する
    for(loop_y=0; loop_y<Y_SIZE; loop_y++){
        for(loop_x=0; loop_x<X_SIZE; loop_x++){
            output_image.setPixel(loop_x, loop_y,
                      qRgb(image_out[loop_y][loop_x],
                           image_out[loop_y][loop_x],
                           image_out[loop_y][loop_x]));
        }
    }
    
    printf("Save output image? \n");
    printf("1:yes\nothers:no\n");
    printf("Input number : ");
    
    scanf("%d",&saveCheck);
    if(saveCheck == 1){
        printf("Please input save file name : ");
        scanf("%s", outFilename);
    //Save as bmp file
        if(!output_image.save(QString::QString(outFilename), "BMP")){
            printf("Can't save the file.\n");
            exit(0);
        }
    }
    
    widget_in.setFixedWidth(X_SIZE);//Fix window size
    widget_in.setFixedHeight(Y_SIZE);
    widget_out.setFixedWidth(X_SIZE);
    widget_out.setFixedHeight(Y_SIZE);
    widget_in.setCaption("Base image");
    widget_out.setCaption("Processed image");
    pixmap_in.convertFromImage(input_image);//convert to set to window
    pixmap_out.convertFromImage(output_image);
    widget_in.setPixmap(pixmap_in);//Show input window
    widget_out.setPixmap(pixmap_out);
    widget_in.show();//Show window
    widget_out.show();   
    
    return application.exec();//Pass control to Qt
}

コードをターミナルからコンパイルするには、

[yourname@localhost qt]qmake -project -o project_name.pro
[yourname@localhost qt]qmake
[yourname@localhost qt]make

のように実行すればよい(project_nameは任意)。
filename.bmpを同じフォルダに用意し、プログラムを実行した結果、 下のようなwindowが表示される。
画像処理の関数を呼び出していないので、結果のウィンドウには何も表示されていない。
結果