「Qtの基礎 - 画像処理」の版間の差分

236行目: 236行目:
<br>
<br>
画像がウインドウの一辺に合わせて全体が表示されている場合は縦横比のみを考慮すればよいが、<br>
画像がウインドウの一辺に合わせて全体が表示されている場合は縦横比のみを考慮すればよいが、<br>
ズームイン・ズームアウト・移動している場合、座標を取得することは困難である。<br>
拡大・縮小・移動している場合、座標を取得することは困難である。<br>
<br>
<br>
Qtでは、ズームイン・ズームアウト・移動の情報は変換行列が持っているため、それを元に逆算することで簡単に座標を取得できる。<br>
Qtでは、拡大・縮小・移動の情報は変換行列が持っているため、それを元に逆算することで簡単に座標を取得できる。<br>
<br>
<br>
以下の例では、画像をクリックする時に座標を渡してシグナルを発行している。<br>
以下の例では、画像をクリックする時に座標を渡してシグナルを発行している。<br>
271行目: 271行目:
   
   
     emit mousePressed(QPoint(p.x() / dScale, p.y() / dScale));
     emit mousePressed(QPoint(p.x() / dScale, p.y() / dScale));
}
</syntaxhighlight>
<br><br>
== 拡大・縮小時の画像の解像度を上げる ==
上記のセクション群では、画像を拡大・縮小する場合、画像の解像度はビューポートのサイズのままである。<br>
また、描画および再描画ごとに表示用の画像を作成しているため非効率である。<br>
<br>
そこで、拡大・縮小するごとに表示用の画像の解像度を上げるようにする。<br>
<syntaxhighlight lang="c++">
void MyGraphicsView::scaleView( qreal factor, QPointF center )
{
    factor /= 5;  // -0.1 <-> 0.1
    factor+=1;  // 0.9 <-> 1.1
    // limit zoom out ---
    if(m_matrix.m11() == 1 && factor < 1)
    {
      return;
    }
    if(m_matrix.m11() * factor < 1)
    {
      factor = 1 / m_matrix.m11();
    }
    // limit zoom in ---
    if(m_matrix.m11() > 100 && factor > 1)
    {
      return;
    }
    // inverse the transform
    int a = 0,
        b = 0;
    m_matrix_inv.map(center.x(), center.y(), &a, &b);
    m_matrix.translate(a-factor*a,b-factor*b);
    m_matrix.scale(factor,factor);
    // ここで表示用画像を作成、上記コードのOpenCVの場合
    m_qimg = QImage( m_img.ptr(), m_img.cols, m_img.rows, m_img.step, QImage::Format_RGB888 );
    if(viewport()->width() < m_qimg.width())
    {
      m_qimg = m_qimg.scaled(viewport()->width() * m_matrix.m11(), viewport()->height() * m_matrix.m11(),
                              Qt::KeepAspectRatio,Qt::FastTransformation);
    }
    controlImagePosition();
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
void MyGraphicsView::controlImagePosition()
{
    qreal left, top, right, bottom;
    qreal limRight, limBottom;
    // 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() * (qreal)m_matrix.m11();
    m_matrix.map(sizeImage.width(), sizeImage.height(), &right, &bottom);
    limRight = sizeImage.width() / m_matrix.m11();
    limBottom = sizeImage.height() / m_matrix.m11()
    if(right < limRight)
    {
      m_matrix.translate(limRight - right, 0);
      right = limRight;
    }
    if(bottom < limBottom)
    {
      m_matrix.translate(0, limBottom-bottom);
      bottom = limBottom;
    }
    m_matrix_inv = m_matrix.inverted();
    viewport()->update();
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{
    // ウィンドウサイズ・画像サイズの比を計算
    double dScale = (double)viewport()->width() / (double)m_pimg->width;
    if(dScale > ( (double)viewport()->height() / (double)m_pimg->height))
    {
      dScale = (double)viewport()->height() / (double)m_pimg->height;
    }
    dScale *= m_matrix.m11()
    // 画像座標を計算してシグナルを発行
    pnt = m_matrix_inv.map(event->pos());
    QPoint pntI = pnt / dScale;
    emit mousePressed(pntI);
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>