我正在尝试使用QSharedmemory在两个进程之间传递多个图像(实际上是一个视频)。目前我正在序列化QImages的QVector并将其复制到内存中。这有效,但序列化步骤大约占99%的时间。我怎样才能以独立于平台的方式更快地完成这项工作?
我的发送代码:
int main(int argc, const char* argv[])
{
QObject *parent;
QString program = "python";
QStringList arguments;
QString programPath(PYSOURCE);
arguments << "-u" << programPath+QString("/test.py");
qDebug() << arguments;
QProcess *pyProcess = new QProcess();
pyProcess->start(program, arguments);
QVector<QImage> images;
//.. fill with some images
auto start = std::chrono::system_clock::now();
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
// this takes extremely long ~44s for 80mb
out << images;
int size = buffer.size();
QSharedMemory sharedMemory("process_example");
if (!sharedMemory.create(size)) {
qDebug() << "Unable to create shared memory segment.";
return 0;
}
qDebug() << "sizeof mem: " << sharedMemory.size() << "bufsize:" << buffer.size();
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();
qDebug() << "image copied to shared memory";
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start);
qDebug() << "duration:" << duration.count() << "ms";
while (pyProcess->waitForReadyRead(-1)){
QByteArray newData = pyProcess->readAllStandardOutput();
QString result = QString::fromLocal8Bit(newData);
qDebug(qPrintable(QString("py:")+result));
}
sharedMemory.detach();
return 0;
}
答案 0 :(得分:1)
几天前我遇到了同样的问题。我在网上找不到答案,所以我试着自己写代码。该方法是直接将图像的原始数据复制到共享内存中或从共享内存中复制。这个方法非常非常快。
图片发送功能:
//The image-file names are stored in a QStringList object
void SendImage(QStringList fileList)
{
if (sharedMemory.isAttached())
sharedMemory.detach();
int count = fileList.count();
int totalSize = 0;
QList<QImage> images;
//Load the images
for (int i = 0; i < count; i++)
{
QImage image(fileList.at(i));
images.append(image);
totalSize += image.sizeInBytes();
}
//Total size needed for shared memory
totalSize += (count * 5 + 1) * sizeof(int);
if (!sharedMemory.create(totalSize)) {
throw QString( "Shared memory cannot be allocated!");
return;
}
sharedMemory.lock();
//to points to the target space to write
uchar *to = (uchar *)sharedMemory.data();
//from points to the source to write
uchar *from = (uchar *)&count;
//Write the count of the images from the first byte of the shared memory
memcpy(to, from, sizeof(int));
//Move the pointer forward
to += sizeof(int);
//Write the images one by one
for (int i = 0; i < count; i++) {
//Write the total size of the image and move the pointer forward
int sizeInBytes = images.at(i).sizeInBytes();
from = (uchar *)&sizeInBytes;
memcpy(to, from ,sizeof(int));
to += sizeof(int);
//Write the width of the image and move the pointer forward
int width = images.at(i).width();
from = (uchar *)&width;
memcpy(to, from ,sizeof(int));
to += sizeof(int);
//Write the height of the image and move the pointer forward
int height = images.at(i).height();
from = (uchar *)&height;
memcpy(to, from ,sizeof(int));
to += sizeof(int);
//Write the image format of the image and move the pointer forward
int imageFormat = (int)images.at(i).format() ;
from = (uchar *)&imageFormat;
memcpy(to, from ,sizeof(int));
to += sizeof(int);
//Write the bytes per line of the image and move the pointer forward
int bytesPerLine = images.at(i).bytesPerLine();
from = (uchar *)&bytesPerLine;
memcpy(to, from ,sizeof(int));
to += sizeof(int);
//Write the raw data of the image and move the pointer forward
from = (uchar *)images.at(i).bits();
memcpy(to, from, sizeInBytes);
to += sizeInBytes;
}
sharedMemory.unlock();
}
我接收图像的代码:
QList<QImage> * FetchImages()
{
QList<QImage> * imageList = new QList<QImage>;
if (!sharedMemory.attach())
{
throw QString("The shared memory cannot be attached!");
return imageList;
}
sharedMemory.lock();
//from points to the first byte of the shared memory
uchar * from = (uchar *)sharedMemory.data();
//Get the count of the images and move the pointer forward
int count;
count = *(int *)from;
from += sizeof(int);
//Get the images one by one
for (int i = 0; i < count; i++)
{
//Get the size of the image and move the pointer forward
int sizeInBytes = *(int *)from;
from += sizeof(int);
//Get the width of the image and move the pointer forward
int width = *(int *)from;
from += sizeof(int);
//Get the height of the image and move the pointer forward
int height = *(int *)from;
from += sizeof(int);
//Get the image format of the image and move the pointer forward
int imageFormat = *(int *)from;
from += sizeof(int);
////Get the bytes per line of the image and move the pointer forward
int bytesPerLine = *(int *)from;
from += sizeof(int);
//Generate an image using the raw data and move the pointer forward
QImage image(from, width, height, bytesPerLine, (QImage::Format)imageFormat);
from += sizeInBytes;
//It is very important here and I spent much time.
//A new image object "image1" must be deeply copied from "image" before appended to the imageList.
//Because the raw data of "image" use the space of the shared memory, which will not be accessed after the shared memory is detached.
//The raw data of the newly constructed "image1" use the memory of its own process.
QImage image1 = image.copy(0, 0, width, height);
imageList -> append(image1);
}
sharedMemory.unlock();
sharedMemory.detach();
return imageList;
}
答案 1 :(得分:0)
我认为缓冲区的主要问题是它需要多次调整大小。尝试将基本字节数组的大尺寸设置为更大的尺寸,然后再需要数据。
buffer.buffer ().resize (100000000);
在图像序列化之前调用它。
答案 2 :(得分:0)
尝试使用QImage.save
将其保存到QByteArray
作为&#34; PNG&#34;,然后将其中的数据复制到带有memcpy的QSharedMemory
。