GraphicsView fitInView()在缩小时会产生非常像素化的结果



我到处找,试了两天都找不到任何解决方案。

问题:

我正在做一个具有"使图像适合视图"功能的图像查看器。我在GraphicsView中加载了一张3000多像素的图片(当然要小得多),滚动条就会出现,这很好。当我点击我的btnFitView并执行时:

ui->graphicsView->fitInView(scene->sceneRect(),Qt::KeepAspectRatio);

这是缩小比例,对吧?fitInView()之后,所有行都将像素化。它看起来像是一把锯子越过了图像上的线条。

例如:汽车的图像有线条,纹簿的图像(字母质量很差)。

我的代码示例:

// select file, load image in view
QString strFilePath = QFileDialog::getOpenFileName(
            this,
            tr("Open File"),
             "/home",
            tr("Images (*.png *.jpg)"));
imageObject = new QImage();
imageObject->load(strFilePath);
image = QPixmap::fromImage(*imageObject);
scene = new QGraphicsScene(this);
scene->addPixmap(image);
scene->setSceneRect(image.rect());
ui->graphicsView->setScene(scene);

// on_btnFitView_Clicked() :
ui->graphicsView->fitInView(scene->sceneRect(),Qt::KeepAspectRatio);

在fitInView()之前,尺寸为:

qDebug()<<"sceneRect = "<< scene->sceneRect();
qDebug()<<"viewRect = " << ui->graphicsView->rect();
sceneRect =  QRectF(0,0 1000x750)
viewRect =   QRect(0,0 733x415)  

如果有必要,我可以上传原始加载图像的屏幕截图,并在视图中拟合?

我这样做对吗?网络上的所有示例似乎都使用fitInView进行自动装配。我应该在像素图上使用其他操作吗?

解决方案

// LOAD IMAGE
bool ImgViewer::loadImage(const QString &strImagePath)
{
  m_image = new QImage(strImagePath);
  if(m_image->isNull()){
    return false;
  }
  clearView();
  m_pixmap = QPixmap::fromImage(*m_image);     
  m_pixmapItem = m_scene->addPixmap(m_pixmap); 
  m_scene->setSceneRect(m_pixmap.rect());      
  this->centerOn(m_pixmapItem);
  // preserve fitView if active
  if(m_IsFitInView)
      fitView();
  return true;
}
// TOGGLED FUNCTIONS
void ImgViewer::fitView()
{
    if(m_image->isNull())
      return;
    this->resetTransform();
    QPixmap px = m_pixmap; // use local pixmap (not original) otherwise image is blurred after scaling the same image multiple times
    px = px.scaled(QSize(this->width(),this->height()),Qt::KeepAspectRatio,Qt::SmoothTransformation);
    m_pixmapItem->setPixmap(px);
    m_scene->setSceneRect(px.rect());
}
void ImgViewer::originalSize()
{
    if(m_image->isNull())
       return;
    this->resetTransform();
    m_pixmap = m_pixmap.scaled(QSize(m_image.width(),m_image.height()),Qt::KeepAspectRatio,Qt::SmoothTransformation); 
    m_pixmapItem->setPixmap(m_pixmap);
    m_scene->setSceneRect(m_pixmap.rect());
    this->centerOn(m_pixmapItem); //ensure item is centered in the view.
}

在下降时,这会产生良好的质量。以下是调用这两个函数后的一些统计数据:

//    "originalSize()"  : IMAGE SIZE =   (1152, 2048)
//    "originalSize()"  : PIXMAP SIZE =  (1152, 2048)
//    "originalSize()"  : VIEW SIZE =    (698, 499)
//    "originalSize()"  : SCENE SIZE =   (1152, 2048)
//    "fitView()"   : IMAGE SIZE =   (1152, 2048)
//    "fitView()"   : PIXMAP SIZE =  (1152, 2048)
//    "fitView()"   : VIEW SIZE =    (698, 499) 
//    "fitView()"   : SCENE SIZE =   (280, 499)

现在有一个问题,调用fitView()后查看场景的大小?小得多。

如果fitView()被激活,我现在用视图缩放函数缩放轮子上的图像Event(放大/缩小):scale(factor,factor)。。结果很糟糕。在场景大小等于图像大小的情况下,originalSize()不会发生这种情况。

将视图视为进入场景的窗口。

大量移动视图,放大或缩小,可能会产生看起来不太好的图像。视图只是从场景移开并尽最大努力渲染图像,而不是像您预期的那样缩放图像,但图像没有缩放,只是在场景中进行了变换。

不使用QGraphicsView::fitInView,而是将主图像保留在内存中,并在每次选择fitInView或用户放大/缩小时使用QPixamp::scaled创建图像的缩放版本。然后使用setPixmap在QGraphicsPixmapItem上设置此QPixmap。

你可能还想考虑去掉滚动条,让用户在屏幕上拖动图像,在我看来,这提供了更好的用户界面;当然,这取决于您的要求。

最新更新