Optimize QImage checkForAlphaPixels

This routine is often called to down-convert pixmaps and backing
stores to RGB32.

This patch replaces a comparison in each pixel, with a single AND in
each pixel and a comparison at each line. The new form is also auto-
vectorized by at least GCC.

Change-Id: I3e07585a3ec12f888321d35da57ac99b561dbec4
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
Allan Sandfeld Jensen 2016-05-13 13:33:52 +02:00 committed by Allan Sandfeld Jensen
parent b8a0c6e7c5
commit f15c0b695a

View File

@ -193,74 +193,81 @@ bool QImageData::checkForAlphaPixels() const
break;
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied: {
uchar *bits = data;
const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
uint alphaAnd = 0xff000000;
for (int x=0; x<width; ++x)
has_alpha_pixels |= (((uint *)bits)[x] & 0xff000000) != 0xff000000;
alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
has_alpha_pixels = (alphaAnd != 0xff000000);
bits += bytes_per_line;
}
} break;
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied: {
uchar *bits = data;
const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
uchar alphaAnd = 0xff;
for (int x=0; x<width; ++x)
has_alpha_pixels |= bits[x*4+3] != 0xff;
alphaAnd &= bits[x * 4+ 3];
has_alpha_pixels = (alphaAnd != 0xff);
bits += bytes_per_line;
}
} break;
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_A2RGB30_Premultiplied: {
uchar *bits = data;
const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
uint alphaAnd = 0xc0000000;
for (int x=0; x<width; ++x)
has_alpha_pixels |= (((uint *)bits)[x] & 0xc0000000) != 0xc0000000;
alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
has_alpha_pixels = (alphaAnd != 0xc0000000);
bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_ARGB8565_Premultiplied: {
uchar *bits = data;
uchar *end_bits = data + bytes_per_line;
const uchar *bits = data;
const uchar *end_bits = data + bytes_per_line;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
uchar alphaAnd = 0xff;
while (bits < end_bits) {
has_alpha_pixels |= bits[0] != 0;
alphaAnd &= bits[0];
bits += 3;
}
has_alpha_pixels = (alphaAnd != 0xff);
bits = end_bits;
end_bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB6666_Premultiplied: {
uchar *bits = data;
uchar *end_bits = data + bytes_per_line;
const uchar *bits = data;
const uchar *end_bits = data + bytes_per_line;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
uchar alphaAnd = 0xfc;
while (bits < end_bits) {
has_alpha_pixels |= (bits[0] & 0xfc) != 0;
alphaAnd &= bits[0];
bits += 3;
}
has_alpha_pixels = (alphaAnd != 0xfc);
bits = end_bits;
end_bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB4444_Premultiplied: {
uchar *bits = data;
uchar *end_bits = data + bytes_per_line;
const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
while (bits < end_bits) {
has_alpha_pixels |= (bits[0] & 0xf0) != 0;
bits += 2;
}
bits = end_bits;
end_bits += bytes_per_line;
ushort alphaAnd = 0xf000;
for (int x=0; x<width; ++x)
alphaAnd &= reinterpret_cast<const ushort*>(bits)[x];
has_alpha_pixels = (alphaAnd != 0xf000);
bits += bytes_per_line;
}
} break;