使用QtConcurrent使用QImageReader读取图像文件
Read image files with QImageReader using QtConcurrent
我试图使用QImageReader一次读取图像文件的部分(每个磁贴),这样对于非常大的图像,在需要显示之前,它们不会从磁盘读取到内存中。
看来我遇到了一些线程安全问题。
这就是我目前拥有的:
#include "rastertile.h"
QMutex RasterTile::mutex;
RasterTile::RasterTile()
{
}
//RasterTile::RasterTile(QImageReader *reader, int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize)
RasterTile::RasterTile(QString filename, int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize)
: Tile(nBlocksX, nBlocksY, xoffset, yoffset, nXBlockSize, nYBlockSize)
{
this->reader = new QImageReader(filename);
connect(&watcher,SIGNAL(finished()),this,SLOT(updateSceneSlot()));
}
void RasterTile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
if(image.isNull())
{
TilePainter=painter;
TileOption=option;
TileWidget=widget;
future = QtConcurrent::run(this, &RasterTile::LoadTilePixmap);
watcher.setFuture(future);
}else
{
QRectF imageRect = image.rect();
painter->drawImage(imageRect, image);
}
}
QImage RasterTile::LoadTilePixmap()
{
QMutexLocker locker(&mutex);
QImage img(nBlockXSize, nBlockYSize, QImage::Format_RGB32);
QRect rect(tilePosX*nBlockXSize, tilePosY*nBlockYSize, nBlockXSize, nBlockYSize);
reader->setClipRect(rect);
reader->read(&img);
if(reader->error())
{
qDebug("Not null error");
qDebug()<<"Error string is: "<<reader->errorString();
}
return img;
}
因此,这基本上是为每个瓦片实例化一个新的读取器,并更新超类的"image"变量,然后我可以绘制它。
这似乎给了我很多来自阅读器的错误,它们只是简单地说"无法读取图像数据"
我认为这可能与许多瓦片访问同一文件有关,但我不知道如何证明或修复它
我认为Qt使用libjpeg和libpng以及其他任何东西来读取各种图像格式。
查看QImageReader的源代码。
当读取器返回InvalidDataError时,您将得到"无法读取图像数据"。
如果您还阅读了InvalidDataError的解释QT Doc说
图像数据无效,并且QImageReader无法读取图像。如果图像文件已损坏。
所以你的文件可能已经损坏了。
我在这里看到了两个潜在的问题。
- 这不是你真正的问题,但我稍后会遇到小瓷砖的问题。
future
在线程启动后设置为。如果线程在正确设置future
之前完成,这可能会导致问题。(不是100%确定,但比方说…85%,我相信这不太可能发生) - CCD_ 3可以经常被调用。我相信你的问题是,在你的阅读线程完成之前,它被调用了第二次。这将导致另一个线程在第一个线程仍在读取瓷砖时尝试读取瓷砖。你的意志甚至试图同时使用QImageReader的相同实例
您可以尝试添加:
if (reader->canRead())
reader->read(&img);
else
qDebug() << "Could not read from device";
这可能没有多大帮助,但根据文档canRead:如果可以为设备读取图像,则返回true(即,支持图像格式,并且设备似乎包含有效数据);否则返回false。
您可以尝试另一种创建线程以读取瓦片的方法。
从QObject创建一个myReaderObject作为子类。
在主线程构造函数中创建一个成员QThread对象:
m_workerthread=new QThread();
m_workerthread->start();
要读取瓷砖,请执行
myReaderObject *reader=new myReaderObject();
reader->moveToThread(m_workerthread);
connect ( reader, SIGNAL(myFinishSignal() , ...
QMetaObject::invokeMethod(reader,"read", Qt::AutoConnection);
您的myReaderObject当然需要一个读取方法和myFinishSignal信号
相关文章:
- .h 和.cpp文件分离时出错,但仅使用 .h 文件时没有错误.我做错了什么?
- 如何使用文件中的文本,例如变量
- WinVerifyTrust 仅在使用文件而不是内存 blob 时才有效
- 我在使用C++文件时遇到了一些问题
- 使用文件系统时仍然需要链接到带有 C++20 的 stdc++fs?
- 使用文件内容作为硬编码字符串
- 标头,包括在 Swift 项目中使用C++文件时的错误
- 如何在我的 Visual C++ 项目中使用 .a 文件
- 如何使用文件填充结构(下面附有的代码)?
- 调用函数并使用文件作为引用
- 如何在不使用文件扩展名的情况下使用命令行参数打开C++中的文本文件?
- 如何在不包含完整的文件系统头的情况下使用文件系统的类路径C++17?
- 使用文件对话框选择包含特定文件类型的文件夹?
- 如何在EXECUTE_PROCESS中使用文件(GLOB_RECURSE)的结果?
- 使用 C++文件 I/O 输出 pdf 文件
- 如何使用C 文件IO修复程序
- 如何使用文件系统库获取"true"文件大小?(C++17)
- 如何使用文件填充数组并将其与用户输入C 进行比较
- C :使用文件末端(CTRL Z)结束一个循环似乎打破了我程序的其余部分
- 使用文件和结构读取数据并输出数据