Qt源码分析--QImage(1)

本文介绍了QImage类的基本功能,包括其作为独立于硬件的图像表示形式,并提供了直接访问像素数据的能力。QImage还支持多种图像格式,如单色、8位、32位和alpha混合图像,并可通过QPainter进行绘图。文章还详细解析了QImage构造函数的工作原理及一些常用成员函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QImage 类提供独立于硬件的图像表示 (允许直接访问像素数据,且可以用作描绘设备)。

QImage 是为 I/O 和直接像素访问和操作而设计和优化的。

因为 QImage 是 QPaintDevice 的子类,所以 QPainter 可用于直接在图像上绘图。在 QImage 上使用 QPainter 时,可以在当前 GUI 线程之外的另一个线程中执行绘画。

QImage 类支持由 Format 枚举描述的几种图像格式。这些包括单色、8 位、32 位和 alpha 混合图像。

QImage 提供了一组函数,可用于获取有关图像的各种信息。还有几个函数可以转换图像。

QImage 对象可以通过值传递,因为 QImage 类使用隐式数据共享。 QImage 对象也可以流式传输和比较。

1.QImage(const QSize &size, Format format);

QImage::QImage(const QSize &size, Format format)
    : QPaintDevice()
{
    d = QImageData::create(size, format);
}



QImageData * QImageData::create(const QSize &size, QImage::Format format)
{
    if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
        return nullptr;                             // invalid parameter(s)
    Q_TRACE_SCOPE(QImageData_create, size, format);
    int width = size.width();
    int height = size.height();
    int depth = qt_depthForFormat(format);
    auto params = calculateImageParameters(width, height, depth);
    if (!params.isValid())
        return nullptr;
    QScopedPointer<QImageData> d(new QImageData);
    switch (format) {
    case QImage::Format_Mono:
    case QImage::Format_MonoLSB:
        d->colortable.resize(2);
        d->colortable[0] = QColor(Qt::black).rgba();
        d->colortable[1] = QColor(Qt::white).rgba();
        break;
    default:
        break;
    }
    d->width = width;
    d->height = height;
    d->depth = depth;
    d->format = format;
    d->has_alpha_clut = false;
    d->is_cached = false;
    d->bytes_per_line = params.bytesPerLine;
    d->nbytes = params.totalSize;
    d->data  = (uchar *)malloc(d->nbytes);
    if (!d->data)
        return nullptr;
    d->ref.ref();
    return d.take();
}

QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth)
{
    ImageSizeParameters invalid = { -1, -1 };
    if (height <= 0)
        return invalid;
    // calculate the size, taking care of overflows
    qsizetype bytes_per_line;
    if (mul_overflow(width, depth, &bytes_per_line))
        return invalid;
    if (add_overflow(bytes_per_line, qsizetype(31), &bytes_per_line))
        return invalid;
    // bytes per scanline (must be multiple of 4)
    bytes_per_line = (bytes_per_line >> 5) << 2;    // can't overflow
    qsizetype total_size;
    if (mul_overflow(height, bytes_per_line, &total_size))
        return invalid;
    qsizetype dummy;
    if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
        return invalid;                                 // why is this here?
#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore
    // Disallow images where width * depth calculations might overflow
    if (width > (INT_MAX - 31) / depth)
        return invalid;
#endif
    return { bytes_per_line, total_size };
}

根据Size和Format初始化私有变量d. 

调用calculateImageParameters函数计算出所需的内存大小,用malloc函数申请内存空间。

2.QSize size() const;

QSize QImage::size() const
{
    return d ? QSize(d->width, d->height) : QSize(0, 0);
}

3.int width() const;

int QImage::width() const
{
    return d ? d->width : 0;
}

4.int height() const;

int QImage::height() const
{
    return d ? d->height : 0;
}

5.int dotsPerMeterX() const;

int QImage::dotsPerMeterX() const
{
    return d ? qRound(d->dpmx) : 0;
}

6.int dotsPerMeterY() const;

int QImage::dotsPerMeterY() const
{
    return d ? qRound(d->dpmy) : 0;
}

7.QRect rect() const;

QRect QImage::rect() const
{
    return d ? QRect(0, 0, d->width, d->height) : QRect();
}

8.bool valid(int x, int y) const;

/*!
    \overload
    Returns \c true if QPoint(\a x, \a y) is a valid coordinate pair
    within the image; otherwise returns \c false.
*/
bool QImage::valid(int x, int y) const
{
    return d
        && x >= 0 && x < d->width
        && y >= 0 && y < d->height;
}

9.QPoint offset() const;

/*!
    \fn QPoint QImage::offset() const
    Returns the number of pixels by which the image is intended to be
    offset by when positioning relative to other images.
    \sa setOffset(), {QImage#Image Information}{Image Information}
*/
QPoint QImage::offset() const
{
    return d ? d->offset : QPoint();
}

10.void setOffset(const QPoint&);

void QImage::setOffset(const QPoint& p)
{
    if (!d)
        return;
    detach();
    if (d)
        d->offset = p;
}

void QImage::detach()
{
    if (d) {
        if (d->is_cached && d->ref.loadRelaxed() == 1)
            QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
        if (d->ref.loadRelaxed() != 1 || d->ro_data)
            *this = copy();
        if (d)
            ++d->detach_no;
    }
}

先解除绑定,再设置新值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天天进步2015

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

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

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

打赏作者

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

抵扣说明:

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

余额充值