Modernize setAlphaChannel(), and deprecated alphaChannel()

The two methods have been marked obsolete for a very long time,
setAlphaChannel() is still convenient though, so this patch
modernizes it and removes obsolete from the API, while marking
QImage::alphaChannel() as deprecated. They don't work as getter
and setter anyway, since setAlphaChannel() actually does an
alpha composition.

Change-Id: I634d6463f78c42bb9c5fa3df17500ec01bfcac33
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2019-12-18 17:23:50 +01:00
parent 1f87fb359f
commit aa542be4e0
3 changed files with 32 additions and 69 deletions

View File

@ -4410,99 +4410,61 @@ bool QImage::isDetached() const
/*! /*!
\obsolete
Sets the alpha channel of this image to the given \a alphaChannel. Sets the alpha channel of this image to the given \a alphaChannel.
If \a alphaChannel is an 8 bit grayscale image, the intensity values are If \a alphaChannel is an 8 bit alpha image, the alpha values are
written into this buffer directly. Otherwise, \a alphaChannel is converted used directly. Otherwise, \a alphaChannel is converted to 8 bit
to 32 bit and the intensity of the RGB pixel values is used. grayscale and the intensity of the pixel values is used.
Note that the image will be converted to the Format_ARGB32_Premultiplied If the image already has an alpha channel, the existing alpha channel
format if the function succeeds. is multiplied with the new one. If the image doesn't have an alpha
channel it will be converted to a format that does.
Use one of the composition modes in QPainter::CompositionMode instead. The operation is similar to painting \a alphaChannel as an alpha image
over this image using \c QPainter::CompositionMode_DestinationIn.
\warning This function is expensive. \sa hasAlphaChannel(), alphaChannel(),
{QImage#Image Transformations}{Image Transformations},
\sa alphaChannel(), {QImage#Image Transformations}{Image {QImage#Image Formats}{Image Formats}
Transformations}, {QImage#Image Formats}{Image Formats}
*/ */
void QImage::setAlphaChannel(const QImage &alphaChannel) void QImage::setAlphaChannel(const QImage &alphaChannel)
{ {
if (!d) if (!d || alphaChannel.isNull())
return; return;
int w = d->width;
int h = d->height;
if (w != alphaChannel.d->width || h != alphaChannel.d->height) {
qWarning("QImage::setAlphaChannel: "
"Alpha channel must have same dimensions as the target image");
return;
}
if (d->paintEngine && d->paintEngine->isActive()) { if (d->paintEngine && d->paintEngine->isActive()) {
qWarning("QImage::setAlphaChannel: " qWarning("QImage::setAlphaChannel: "
"Unable to set alpha channel while image is being painted on"); "Unable to set alpha channel while image is being painted on");
return; return;
} }
if (d->format == QImage::Format_ARGB32_Premultiplied) const Format alphaFormat = qt_alphaVersionForPainting(d->format);
if (d->format == alphaFormat)
detach(); detach();
else else
*this = convertToFormat(QImage::Format_ARGB32_Premultiplied); convertTo(alphaFormat);
if (isNull()) if (isNull())
return; return;
// Slight optimization since alphachannels are returned as 8-bit grays. QImage sourceImage;
if (alphaChannel.format() == QImage::Format_Alpha8 ||( alphaChannel.d->depth == 8 && alphaChannel.isGrayscale())) { if (alphaChannel.format() == QImage::Format_Alpha8 || (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()))
const uchar *src_data = alphaChannel.d->data; sourceImage = alphaChannel;
uchar *dest_data = d->data; else
for (int y=0; y<h; ++y) { sourceImage = alphaChannel.convertToFormat(QImage::Format_Grayscale8);
const uchar *src = src_data; if (!sourceImage.reinterpretAsFormat(QImage::Format_Alpha8))
QRgb *dest = (QRgb *)dest_data; return;
for (int x=0; x<w; ++x) {
int alpha = *src;
int destAlpha = qt_div_255(alpha * qAlpha(*dest));
*dest = ((destAlpha << 24)
| (qt_div_255(qRed(*dest) * alpha) << 16)
| (qt_div_255(qGreen(*dest) * alpha) << 8)
| (qt_div_255(qBlue(*dest) * alpha)));
++dest;
++src;
}
src_data += alphaChannel.d->bytes_per_line;
dest_data += d->bytes_per_line;
}
} else { QPainter painter(this);
const QImage sourceImage = alphaChannel.convertToFormat(QImage::Format_RGB32); if (sourceImage.size() != size())
if (sourceImage.isNull()) painter.setRenderHint(QPainter::SmoothPixmapTransform);
return; painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
const uchar *src_data = sourceImage.d->data; painter.drawImage(rect(), sourceImage);
uchar *dest_data = d->data;
for (int y=0; y<h; ++y) {
const QRgb *src = (const QRgb *) src_data;
QRgb *dest = (QRgb *) dest_data;
for (int x=0; x<w; ++x) {
int alpha = qGray(*src);
int destAlpha = qt_div_255(alpha * qAlpha(*dest));
*dest = ((destAlpha << 24)
| (qt_div_255(qRed(*dest) * alpha) << 16)
| (qt_div_255(qGreen(*dest) * alpha) << 8)
| (qt_div_255(qBlue(*dest) * alpha)));
++dest;
++src;
}
src_data += sourceImage.d->bytes_per_line;
dest_data += d->bytes_per_line;
}
}
} }
#if QT_DEPRECATED_SINCE(5, 15)
/*! /*!
\obsolete \obsolete
@ -4592,6 +4554,7 @@ QImage QImage::alphaChannel() const
return image; return image;
} }
#endif
/*! /*!
Returns \c true if the image has a format that respects the alpha Returns \c true if the image has a format that respects the alpha

View File

@ -266,7 +266,9 @@ public:
bool hasAlphaChannel() const; bool hasAlphaChannel() const;
void setAlphaChannel(const QImage &alphaChannel); void setAlphaChannel(const QImage &alphaChannel);
QImage alphaChannel() const; #if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED QImage alphaChannel() const;
#endif
QImage createAlphaMask(Qt::ImageConversionFlags flags = Qt::AutoColor) const; QImage createAlphaMask(Qt::ImageConversionFlags flags = Qt::AutoColor) const;
#ifndef QT_NO_IMAGE_HEURISTIC_MASK #ifndef QT_NO_IMAGE_HEURISTIC_MASK
QImage createHeuristicMask(bool clipTight = true) const; QImage createHeuristicMask(bool clipTight = true) const;

View File

@ -535,8 +535,6 @@ QImage ICOReader::iconAt(int index)
if (!mask.isNull()) { if (!mask.isNull()) {
img = image; img = image;
img.setAlphaChannel(mask); img.setAlphaChannel(mask);
// (Luckily, it seems that setAlphaChannel() does not ruin the alpha values
// of partially transparent pixels in those icons that have that)
} }
} }
} }