Qt有办法找到图像的边界框吗?

时间:2010-09-15 19:10:07

标签: qt

给定具有透明背景的.png图像,我想找到非透明数据的边界框。使用嵌套for循环QImage.pixel()非常慢。在Qt中是否有内置的方法?

3 个答案:

答案 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,而是半透明。