1

我正在尝试使用 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;
}
4

3 回答 3

0

我认为您的缓冲区的主要问题是它需要多次调整大小。尝试将下层字节数组的大尺寸设置为比您的数据需要更大的尺寸。

buffer.buffer ().resize (100000000);

在图像序列化之前调用它。

于 2016-01-20T14:42:48.637 回答
0

尝试使用QImage.save将其保存QByteArray为“PNG”,然后将数据从该文件复制到QSharedMemory带有 memcpy 的文件中。

http://doc.qt.io/qt-4.8/qimage.html#save-2

于 2016-01-21T14:34:14.920 回答
0

几天前我遇到了同样的问题。我在网上找不到答案,所以我试着自己写代码。方法是将图像的原始数据直接复制到共享内存中或从共享内存中复制出来。这种方法非常非常快。

图片发送函数:

//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;
}
于 2021-07-31T04:46:57.827 回答