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;
}
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); }