给定具有透明背景的.png
图像,我想找到非透明数据的边界框。使用嵌套for
循环QImage.pixel()
非常慢。在Qt中是否有内置的方法?
答案 0 :(得分:4)
有一个选项涉及使用QGraphicsPixmapItem
并查询不透明区域(QGraphicsPixmapItem::opaqueArea().boundingRect()
)的边界框。不确定它是否是最好的方法,但它可行:)可能值得深入研究Qt的源代码,看看代码的核心是什么。
以下代码将打印图像的宽度和高度,后跟图像不透明部分的宽度和高度:
QPixmap p("image.png");
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(p);
std::cout << item->boundingRect().width() << "," << item->boundingRect().height() << std::endl;
std::cout << item->opaqueArea().boundingRect().width() << "," << item->opaqueArea().boundingRect().height() << std::endl;
答案 1 :(得分:4)
如果像素()对你来说太慢,考虑到QImage p:
,考虑更有效的逐行数据寻址int l =p.width(), r = 0, t = p.height(), b = 0;
for (int y = 0; y < p.height(); ++y) {
QRgb *row = (QRgb*)p.scanLine(y);
bool rowFilled = false;
for (int x = 0; x < p.width(); ++x) {
if (qAlpha(row[x])) {
rowFilled = true;
r = std::max(r, x);
if (l > x) {
l = x;
x = r; // shortcut to only search for new right bound from here
}
}
}
if (rowFilled) {
t = std::min(t, y);
b = y;
}
}
我怀疑它会比这更快。
答案 2 :(得分:0)
最简单,也相对较快的解决方案是执行以下操作:
QRegion(QBitmap::fromImage(image.createMaskFromColor(0x00000000))).boundingRect()
如果您使用的是QPixmap
而不是QImage
,则可以使用:
QRegion(pixmap.createMaskFromColor(Qt::transparent)).boundingRect()
QPixmap::createMaskFromColor
在内部会将像素图转换为图像,并执行与上述相同的操作。 QPixmap
的更短解决方案是:
QRegion(pixmap.mask()).boundingRect()
在这种情况下,没有alpha通道的QPixmap
将导致空白区域,因此您可能需要明确检查。顺便说一句,这也是@Arnold Spence提到的QGraphicsPixmapItem::opaqueArea
的依据。
您可能还想尝试QImage::createAlphaMask
,尽管截止点不会是0 alpha,而是半透明。