12,788
回編集
編集の要約なし |
|||
1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
Qtでは画像を取り扱うクラスとして、<code>QBitmap</code>クラス、<code>QPixmap</code>クラス、<code>QImage</code>クラスの3種類あり、それぞれ使い分けが必要である。<br> | |||
<br> | <br> | ||
ここでは、ウィジェット上に画像を表示する手順を記載する。<br> | ここでは、ウィジェット上に画像を表示する手順を記載する。<br> | ||
7行目: | 7行目: | ||
== QGraphicsViewクラスを使用する == | == QGraphicsViewクラスを使用する == | ||
画像を表示する機能を持っているウィジェットは無いため、ビュークラスを継承して派生クラスを作成する。<br> | 画像を表示する機能を持っているウィジェットは無いため、ビュークラスを継承して派生クラスを作成する。<br> | ||
( | (元々、<code>QGraphicsView</code>クラスは、<code>QGraphicsScene</code>クラスを表示するためのものである)<br> | ||
<br> | <br> | ||
ビュークラスを継承した派生クラスには、元の画像のデータを保持するメンバ変数を定義する。<br> | ビュークラスを継承した派生クラスには、元の画像のデータを保持するメンバ変数を定義する。<br> | ||
31行目: | 31行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
<code>QGraphicsView</code>クラスの<code>paintEvent</code>メソッドは、再描画時に呼び出される仮想関数である。<br> | |||
<code>paintEvent</code>メソッドをオーバーライドして描画部分を記述する。<br> | |||
<br> | <br> | ||
paintEventメソッドとsetImgメソッドの定義は、以下の通りである。<br> | paintEventメソッドとsetImgメソッドの定義は、以下の通りである。<br> | ||
<br> | <br> | ||
以下の例では、paintEventメソッドを使用して<code>QImage</code>クラスのインスタンス(描画用)を生成して、<code>QPainter::drawImage</code>メソッドで描画している。<br> | |||
描画用の画像は、ウィジェットのサイズに合わせてリサイズしている。<br> | 描画用の画像は、ウィジェットのサイズに合わせてリサイズしている。<br> | ||
<br> | <br> | ||
57行目: | 57行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
OpenCVライブラリの<code>cv::Mat</code>メソッドを使用する場合、OpenCVで画像を処理してその画像を表示するには、以下のように記述する。<br> | |||
カラー画像の場合は、色配列をRGBからBGRに変換する必要がある。<br> | <u>カラー画像の場合は、色配列をRGBからBGRに変換する必要がある。</u><br> | ||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
void MyGraphicsView::paintEvent(QPaintEvent *event) | void MyGraphicsView::paintEvent(QPaintEvent *event) | ||
65行目: | 65行目: | ||
widgetpainter.setWorldTransform(m_matrix); | widgetpainter.setWorldTransform(m_matrix); | ||
// | // メンバ変数m_imgはcv::Matクラスのインスタンス | ||
QImage qimg = QImage(m_img.ptr(), m_img.cols, m_img.rows, m_img.step, QImage::Format_RGB888); | QImage qimg = QImage(m_img.ptr(), m_img.cols, m_img.rows, m_img.step, QImage::Format_RGB888); | ||
qimg = qimg.scaled(viewport()->width(), viewport()->height(), Qt::KeepAspectRatio,Qt::FastTransformation); | qimg = qimg.scaled(viewport()->width(), viewport()->height(), Qt::KeepAspectRatio,Qt::FastTransformation); | ||
91行目: | 91行目: | ||
<br><br> | <br><br> | ||
== | == 画像の拡大・縮小・移動 == | ||
画像を表示する機能には、拡大・縮小、移動等の制御が必要になる場合が多い。<br> | |||
これらの機能を実装するには、<code>QTransform</code>クラスを使用する。<br> | |||
<br> | <br> | ||
まず、<code>QTransform</code>クラスのメンバ変数を2つ宣言する。<br> | |||
<code>QTransform</code>クラスのデフォルトコンストラクタを呼び出す場合、単位行列で初期化される。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
QTransform m_matrix; | QTransform m_matrix; | ||
102行目: | 102行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
次に、<code>QGraphicsView</code>クラスの<code>paintEvent</code>メソッドをオーバーライドする。<br> | |||
以下のように記述することで、<code>QTransform</code>クラスの情報が反映されるようになる。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
void MyGraphicsView::paintEvent(QPaintEvent *event) | void MyGraphicsView::paintEvent(QPaintEvent *event) | ||
116行目: | 116行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
拡大・縮小の機能は、以下の通りである。<br> | |||
<br> | <br> | ||
以下の例では、拡大・縮小の限界値を設定して、変換行列に拡大率を設定する。<br> | |||
既に拡大・縮小が適用されている場合のために、予め、ズームの中心を移動している。<br> | |||
<br> | |||
第1引数には、拡大する場合は正の値、縮小する場合は負の値を指定する。<br> | |||
第2引数には、拡大・縮小の中心となる点を指定する。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
void MyGraphicsView::scaleView(qreal factor, QPointF center) | void MyGraphicsView::scaleView(qreal factor, QPointF center) | ||
159行目: | 159行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
controlImagePositionメソッドは、拡大する時、余白が表示されないように画像位置を調整する。<br> | |||
controlImagePositionメソッドの最後で、viewport()->update();を実行して画面を更新する。<br> | controlImagePositionメソッドの最後で、viewport()->update();を実行して画面を更新する。<br> | ||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
166行目: | 166行目: | ||
qreal left, top, right, bottom; | qreal left, top, right, bottom; | ||
//after check top-left, bottom right corner to avoid getting "out" during zoom/panning | // after check top-left, bottom right corner to avoid getting "out" during zoom/panning | ||
m_matrix.map(0, 0, &left, &top); | |||
if(left > 0) | |||
{ | |||
m_matrix.translate(-left, 0); | |||
left = 0; | |||
} | |||
if(top > 0) | |||
{ | |||
m_matrix.translate(0, -top); | |||
top = 0; | |||
} | |||
QSize sizeImage = size(); | |||
m_matrix.map(sizeImage.width(), sizeImage.height(), &right, &bottom); | |||
if(right < sizeImage.width()) | |||
{ | |||
m_matrix.translate(sizeImage.width() - right, 0); | |||
right = sizeImage.width(); | |||
} | |||
if(bottom < sizeImage.height()) | |||
{ | |||
m_matrix.translate(0, sizeImage.height() - bottom); | |||
bottom = sizeImage.height(); | |||
} | |||
m_matrix_inv = m_matrix.inverted(); | |||
viewport()->update(); | viewport()->update(); | ||
203行目: | 203行目: | ||
<br> | <br> | ||
以下の例では、移動はマウスの左ボタンを押してドラッグする場合に適用している。<br> | 以下の例では、移動はマウスの左ボタンを押してドラッグする場合に適用している。<br> | ||
また、拡大している場合にのみ適用している。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
void MyGraphicsView::mouseMoveEvent(QMouseEvent *event) | void MyGraphicsView::mouseMoveEvent(QMouseEvent *event) | ||
335行目: | 335行目: | ||
if(left > 0) | if(left > 0) | ||
{ | { | ||
m_matrix.translate(-left,0); | m_matrix.translate(-left, 0); | ||
left = 0; | left = 0; | ||
} | } | ||
341行目: | 341行目: | ||
if(top > 0) | if(top > 0) | ||
{ | { | ||
m_matrix.translate(0,-top); | m_matrix.translate(0, -top); | ||
top = 0; | top = 0; | ||
} | } | ||
359行目: | 359行目: | ||
if(bottom < limBottom) | if(bottom < limBottom) | ||
{ | { | ||
m_matrix.translate(0, limBottom-bottom); | m_matrix.translate(0, limBottom - bottom); | ||
bottom = limBottom; | bottom = limBottom; | ||
} | } |