将QImage分割成较小的部分

7
我有一张图片,想把它分成n个部分。那么我想知道如何使用QImage来实现这个目标?或者有没有更好(性能方面)的Qt类可用于此任务?
例如,假设我有一张由1920x1080像素组成的图像,并且我想将其分成100个部分,这意味着每个部分将由192x108像素组成。请注意,我不想创建缩放到192x108的相同部分。每个部分都是主图片的独立部分。
我附上了一张图片以使我的问题更清楚。该图片由1920x1080像素组成,每个带网格的部分由192x108像素组成,我想将它们中的每一个都视为QImage对象,而不实际将其分成100个部分。
是否有一种方法可以使用QImage来实现这一点?性能很重要,因为我将分析每个部分,通常会有超过1000个部分。
感谢您的帮助!
编辑:两种方法都完美地工作,但alexisdm的方法有点更复杂,更低级别,但速度更快。jmk的方法更易于使用,但速度较慢。
感谢两位答案提供者。
3个回答

14

通过使用与源图像相同的步幅(每行字节数)和格式,并将原始数据缓冲区传递到 QImage 的其中一个构造函数中,可以创建不复制任何数据的 QImage

QImage createSubImage(QImage* image, const QRect & rect) {
    size_t offset = rect.x() * image->depth() / 8
                    + rect.y() * image->bytesPerLine();
    return QImage(image->bits() + offset, rect.width(), rect.height(),
                  image->bytesPerLine(), image->format());
}

只要子QImage存在,源图像就必须存在。

但是如果分析代码尝试直接访问图像原始数据而不使用QImage::bytesPerLine()QImage::scanLine()QImage::pixel(),可能会导致问题。


这太完美了,非常感谢!正是我在寻找的东西,但我对图像处理非常陌生,不太明白为什么要将深度除以8,我猜想这是因为每个颜色通道都是8位,所以你才要将深度除以8? - Malkavian
3
QImagedepth() 文档说明它返回每个像素的位数。第一个参数是指向原始数据的指针,必须增加以字节为单位指定的偏移量,这就是为什么要除以 8。 - jmk

3

3
你可以通过创建所需尺寸的新 QImage 对象,然后将源图像的适当部分绘制到其中来实现此目的。为此,请从空白目标图像创建一个 QPainter,并使用 drawImage() 方法来复制特定的子矩形。
但是,如果性能很重要,您可能想查看避免不必要的源图像副本的方法。例如,如果您的算法只需要一次查看图片的 192x108 部分,它是否只能限制其分析到原始图像的特定子矩形中?
如果您可以以这种方式重构代码,则可以完全避免创建其他图像。

谢谢!那是个好主意,我以前从来没用过QPainter,所以不知道可以这样做。其实我的算法永远不会创建额外的图像,因为在分析完每个碎片后,我会销毁那个QImage对象并继续处理下一个碎片,所以我永远不会存储这些碎片,但是我需要把它们当作QImage来处理,因为我想使用QImage函数来分析这些碎片。 - Malkavian
我有一节课要上,但我会在回家后尽快尝试您的方法,并在它对我起作用时接受答案。再次感谢! - Malkavian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接