我在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;
}
}
我只是想知道真实实时保存是否可以添加像素......!
提前致谢
DK
答案 0 :(得分:4)
我建议您使用图块来保存图像。将画布分成许多例如64x64矩形。并将每个矩形保存到单独的文件中。当某些内容发生变化时,您只需要重写几个小文件而不是重写整个图片。
您的代码中还有另一个危险的事情。当您运行QImage::save
时,它很可能会删除文件内容并写入新内容。如果系统在两个操作之间关闭,则您的文件将变为空。因此,将新内容写入临时文件然后将其移动到正确的位置非常重要。保留几个旧版本的文件也很有用。谁知道文件系统在关机时会如何反应。
答案 1 :(得分: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中看起来没有办法调用它,因此您可能需要在此处执行特定于操作系统的操作,以确保磁盘映像在您希望的情况下保持一致。
答案 2 :(得分:1)
您可以创建绘制项目的QPainterPath对象列表,然后将其呈现给QImage。您需要更改鼠标事件以执行以下操作: -
在paint事件中,然后传递每个要绘制的新QPainterPath
要备份,每隔n秒,打开一个文件并附加自上次保存列表以来的新QPainterPath流。
要恢复,请打开文件,将其重新流入并将其绘制到图像上。
这可以优化以检查新项目,如果不存在则不打扰保存。此外,您可以维护QPainterPath中创建的多个点,而不是基于时间,只有当它超过一定数量时才会保存。
请注意,如果你确实沿着这条路线走下去,你可能还想用每个QPainterPath存储Painter设置,如果用户也可以更改笔颜色,宽度等内容。
使用QPainterpath会带来其他好处 - 例如,用户可以打开一个图像然后再打开第二个图像,选择将其绘制在第一个图像之上。
答案 3 :(得分:0)
如果您想要实时保存,我建议您使用未压缩的位图格式。改变像素就像在文件内部寻找x-y坐标一样简单,通常计算为
file.seek(y * lineWidth + x * pixelDataSize);
file.write(pixelData);