Qt源码分析--QImage(2)

59 篇文章 1 订阅
37 篇文章 1 订阅

1. QRgb pixel(int x, int y) const;

QRgb QImage::pixel(int x, int y) const
{
    if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
        qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y);
        return 12345;
    }
    const uchar *s = d->data + y * d->bytes_per_line;
    int index = -1;
    switch (d->format) {
    case Format_Mono:
        index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
        break;
    case Format_MonoLSB:
        index = (*(s + (x >> 3)) >> (x & 7)) & 1;
        break;
    case Format_Indexed8:
        index = s[x];
        break;
    default:
        break;
    }
    if (index >= 0) {    // Indexed format
        if (index >= d->colortable.size()) {
            qWarning("QImage::pixel: color table index %d out of range.", index);
            return 0;
        }
        return d->colortable.at(index);
    }
    switch (d->format) {
    case Format_RGB32:
        return 0xff000000 | reinterpret_cast<const QRgb *>(s)[x];
    case Format_ARGB32: // Keep old behaviour.
    case Format_ARGB32_Premultiplied:
        return reinterpret_cast<const QRgb *>(s)[x];
    case Format_RGBX8888:
    case Format_RGBA8888: // Match ARGB32 behavior.
    case Format_RGBA8888_Premultiplied:
        return RGBA2ARGB(reinterpret_cast<const quint32 *>(s)[x]);
    case Format_BGR30:
    case Format_A2BGR30_Premultiplied:
        return qConvertA2rgb30ToArgb32<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
    case Format_RGB30:
    case Format_A2RGB30_Premultiplied:
        return qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
    case Format_RGB16:
        return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
    case Format_RGBX64:
    case Format_RGBA64: // Match ARGB32 behavior.
    case Format_RGBA64_Premultiplied:
        return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
    default:
        break;
    }
    const QPixelLayout *layout = &qPixelLayouts[d->format];
    uint result;
    return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr);
}

首先,判断x,y的值有没有超出范围。

可以把图像想象成一个二维数组。

const uchar *s = d->data + y * d->bytes_per_line;

先找到像素所在的行。

然后根据图像格式找到对应的颜色值。

比如Format_RGB32, 返回x所在列的颜色值。

2. QList<QRgb> colorTable() const;

QList<QRgb> QImage::colorTable() const
{
    return d ? d->colortable : QList<QRgb>();
}

3.int colorCount() const;

int QImage::colorCount() const
{
    return d ? d->colortable.size() : 0;
}

对于 32-bpp 图像,colorCount() 返回 0,因为这些图像不使用颜色表,而是将像素值编码为ARGB

4.int pixelIndex(int x, int y) const;

int QImage::pixelIndex(int x, int y) const
{
    if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
        qWarning("QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
        return -12345;
    }
    const uchar * s = scanLine(y);
    switch(d->format) {
    case Format_Mono:
        return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
    case Format_MonoLSB:
        return (*(s + (x >> 3)) >> (x & 7)) & 1;
    case Format_Indexed8:
        return (int)s[x];
    default:
        qWarning("QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
    }
    return 0;
}

const uchar *QImage::scanLine(int i) const
{
    if (!d)
        return nullptr;
    Q_ASSERT(i >= 0 && i < height());
    return d->data + i * d->bytes_per_line;
}

5. QRgb color(int i) const;

QRgb QImage::color(int i) const
{
    Q_ASSERT(i < colorCount());
    return d ? d->colortable.at(i) : QRgb(uint(-1));
}

参数i 就是pixelIndex()获取的index.

6.bool hasAlphaChannel() const;

bool QImage::hasAlphaChannel() const
{
    if (!d)
        return false;
    const QPixelFormat format = pixelFormat();
    if (format.alphaUsage() == QPixelFormat::UsesAlpha)
        return true;
    if (format.colorModel() == QPixelFormat::Indexed)
        return d->has_alpha_clut;
    return false;
}

7.bool allGray() const;

bool QImage::allGray() const
{
    if (!d)
        return true;
    switch (d->format) {
    case Format_Mono:
    case Format_MonoLSB:
    case Format_Indexed8:
        for (int i = 0; i < d->colortable.size(); ++i) {
            if (!qIsGray(d->colortable.at(i)))
                return false;
        }
        return true;
    case Format_Alpha8:
        return false;
    case Format_Grayscale8:
    case Format_Grayscale16:
        return true;
    case Format_RGB32:
    case Format_ARGB32:
    case Format_ARGB32_Premultiplied:
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    case Format_RGBX8888:
    case Format_RGBA8888:
    case Format_RGBA8888_Premultiplied:
#endif
        for (int j = 0; j < d->height; ++j) {
            const QRgb *b = (const QRgb *)constScanLine(j);
            for (int i = 0; i < d->width; ++i) {
                if (!qIsGray(b[i]))
                    return false;
            }
        }
        return true;
    case Format_RGB16:
        for (int j = 0; j < d->height; ++j) {
            const quint16 *b = (const quint16 *)constScanLine(j);
            for (int i = 0; i < d->width; ++i) {
                if (!qIsGray(qConvertRgb16To32(b[i])))
                    return false;
            }
        }
        return true;
    default:
        break;
    }
    uint buffer[BufferSize];
    const QPixelLayout *layout = &qPixelLayouts[d->format];
    const auto fetch = layout->fetchToARGB32PM;
    for (int j = 0; j < d->height; ++j) {
        const uchar *b = constScanLine(j);
        int x = 0;
        while (x < d->width) {
            int l = qMin(d->width - x, BufferSize);
            const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr);
            for (int i = 0; i < l; ++i) {
                if (!qIsGray(ptr[i]))
                    return false;
            }
            x += l;
        }
    }
    return true;
}
inline constexpr bool qIsGray(QRgb rgb)
{ return qRed(rgb) == qGreen(rgb) && qRed(rgb) == qBlue(rgb); }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值