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函数申请内存空间。
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;
}
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;
}
/*!
\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;
}
}
先解除绑定,再设置新值。