2

我正在 Qt 中创建一个应用程序,类似于 scribble(在示例应用程序中给出)。目的是让用户徒手绘制,一旦完成,将这些绘图上传到网上。截至目前,我每 5 秒将绘图保存为 PNG 图像,以便在意外关闭时数据丢失最小(我保留 5 秒以最小化写入操作;非常需要实时) .
但问题是,我每 5 秒将整个页面保存为图像,其中添加的新数据可能只有几个像素。我想知道我是否可以只写入添加到磁盘中的新像素;没有限制我应该在保存时使用 PNG;当用户说他完成时,我可以在最后将数据转换为 PNG。

保存非常基本的一段代码;

void SaveData(const QString &fileName, const char *fileFormat, QImage image)
{
    mutex.lock();
    QImage visibleImage = image;

    if (visibleImage.save(fileName, fileFormat, 50)) 
    {
    system("sync");
    mutex.unlock();
    return true;

    } else {

    mutex.unlock();
        return false;

    }
}

我只是想知道如果可能的话,如果可能的话,是否实时保存像素被添加..!

提前致谢

丹麦

4

4 回答 4

4

我建议你使用瓷砖来保存图像。将画布分割成许多例如 64x64 的矩形。并将每个矩形保存到单独的文件中。当某些东西发生变化时,你只需要重写几个小文件,而不是重写整个画面。

您的代码中还有另一个危险的东西。当您运行时QImage::save,它很可能会擦除文件内容并写入新内容。如果系统在两次操作之间关闭,您的文件将变为空。因此,将新内容写入临时文件然后将其移动到正确位置非常重要。保留文件的多个旧版本也很有用。谁知道文件系统在关机时会如何反应。

于 2013-06-17T11:37:04.317 回答
2

您可以使用内存映射文件,例如:

    QFile file("rawimage.dat");
    file.open(QIODevice::ReadWrite);
    // Make sure there is enough memory for the image
    quint32 width = 16;
    quint32 height = 16;
    quint32 bpp32 = 4;
    qint64 file_size = width * height * bpp32;
    file.resize(file_size);
    uchar* mem = file.map(0, file_size);

    // make a QImage that uses the file as memory
    QImage img(mem, 16, 16, QImage::Format_ARGB32);
    // Do some drawing in the image
    img.fill(0);

    // finished with the file
    file.unmap(mem);
    file.close();

您需要检查它是否确实正确地刷新到磁盘 - 我还没有测试过这个。理想情况下,在 Windows 上,您希望能够在内存映射句柄上调用“FlushViewOfFile”,以确保将修改后的页面写入磁盘。看起来在 Qt 中没有调用它的方法,因此您可能需要在此处执行特定于操作系统的操作,以确保磁盘映像在您希望时保持一致。

于 2013-06-17T13:19:52.680 回答
1

您可以创建绘制项目的 QPainterPath 对象列表,然后将其渲染到 QImage。您需要更改鼠标事件以执行以下操作:-

  • Mouse Down : 创建一个新的 QPainterPath (painterPath) 并调用painterPath->moveTo
  • 鼠标移动:调用painterPath->LineTo
  • Mouse Up :将 QPainterPath 存储在列表中。

在绘画事件中,您然后传递每个要绘制的新 QPainterPath

要备份,每隔 n 秒,打开一个文件并附加自上次保存列表以来的新 QPainterPaths 流。

要恢复,打开文件,将它们流回并将它们绘制到图像上。

这可以优化以检查新项目,如果不存在则不打扰保存。此外,您可以维护在 QPainterPath 中创建的许多点,而不是基于时间,并且仅在超过一定数量时才保存。

请注意,如果您确实走这条路,您可能还希望使用每个 QPainterPath 存储 Painter 设置,如果用户还可以更改诸如笔颜色、宽度等之类的内容。

使用 QPainterpath 带来的其他优势 - 例如,用户可以打开一个图像,然后打开第二个图像,选择将其绘制在第一个图像之上。

于 2013-06-17T12:46:54.400 回答
0

如果您想要实时保存,那么我建议您使用未压缩的位图格式。更改像素就像在文件中寻找 xy 坐标一样简单,通常计算为

file.seek(y * lineWidth + x * pixelDataSize);
file.write(pixelData);
于 2013-06-17T16:03:46.397 回答