use generic fallback implementation to copy QImage to and from XImage in case of depth mismatch

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-12-29 08:22:23 +02:00
parent e0f38d149b
commit 429afda051

View file

@ -89,58 +89,58 @@ void QX11Data::copyQImageToXImage(const QImage &image, XImage *ximage)
ximage->data = static_cast<char*>(::malloc(size_t(ximage->bytes_per_line) * image.height())); ximage->data = static_cast<char*>(::malloc(size_t(ximage->bytes_per_line) * image.height()));
Q_CHECK_PTR(ximage->data); Q_CHECK_PTR(ximage->data);
bool checkbyteorder = true;
const int w = image.width(); const int w = image.width();
const int h = image.height(); const int h = image.height();
switch(image.format()) {
case QImage::Format_RGB32: { if (ximage->bits_per_pixel == image.depth()) {
uint *xidata = (uint *)ximage->data; switch(image.format()) {
for (int y = 0; y < h; ++y) { case QImage::Format_RGB32: {
const QRgb *p = (const QRgb *) image.constScanLine(y); uint *xidata = (uint *)ximage->data;
for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) {
*xidata++ = p[x] | 0xff000000; const QRgb *p = (const QRgb *) image.constScanLine(y);
} for (int x = 0; x < w; ++x) {
} *xidata++ = p[x] | 0xff000000;
break;
}
case QImage::Format_ARGB32: {
uint *xidata = (uint *)ximage->data;
for (int y = 0; y < h; ++y) {
const QRgb *p = (const QRgb *) image.constScanLine(y);
for (int x = 0; x < w; ++x) {
const QRgb rgb = p[x];
const int a = qAlpha(rgb);
if (a == 0xff) {
*xidata = rgb;
} else {
// RENDER expects premultiplied alpha
*xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
} }
++xidata;
} }
break;
} }
break; case QImage::Format_ARGB32: {
} uint *xidata = (uint *)ximage->data;
case QImage::Format_ARGB32_Premultiplied: { for (int y = 0; y < h; ++y) {
::memcpy(ximage->data, image.constBits(), image.byteCount()); const QRgb *p = (const QRgb *) image.constScanLine(y);
break; for (int x = 0; x < w; ++x) {
} const QRgb rgb = p[x];
default: { const int a = qAlpha(rgb);
checkbyteorder = false; if (a == 0xff) {
for (int h = 0; h < image.height(); h++) { *xidata = rgb;
for (int w = 0; w < image.width(); w++) { } else {
const QRgb pixel = image.pixel(w, h); // RENDER expects premultiplied alpha
XPutPixel(ximage, w, h, pixel); *xidata = qRgba(qt_div_255(qRed(rgb) * a),
qt_div_255(qGreen(rgb) * a),
qt_div_255(qBlue(rgb) * a),
a);
}
++xidata;
}
} }
break;
} }
break; case QImage::Format_ARGB32_Premultiplied: {
::memcpy(ximage->data, image.constBits(), image.byteCount());
break;
}
}
return;
}
for (int h = 0; h < image.height(); h++) {
for (int w = 0; w < image.width(); w++) {
const QRgb pixel = image.pixel(w, h);
XPutPixel(ximage, w, h, pixel);
} }
} }
if (checkbyteorder && (ximage->byte_order == MSBFirst) != (Q_BYTE_ORDER == Q_BIG_ENDIAN)) { if ((ximage->byte_order == MSBFirst) != (Q_BYTE_ORDER == Q_BIG_ENDIAN)) {
uint *xidata = (uint *)ximage->data; uint *xidata = (uint *)ximage->data;
uint *xiend = xidata + w*h; uint *xiend = xidata + w*h;
while (xidata < xiend) { while (xidata < xiend) {
@ -159,54 +159,55 @@ void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image)
Q_ASSERT(ximage->width == image.width()); Q_ASSERT(ximage->width == image.width());
Q_ASSERT(ximage->height == image.height()); Q_ASSERT(ximage->height == image.height());
switch (image.format()) { if (ximage->bits_per_pixel == image.depth()) {
case QImage::Format_RGB32: { switch (image.format()) {
uchar *imagedata = image.bits(); case QImage::Format_RGB32: {
const int imagebpl = image.bytesPerLine(); uchar *imagedata = image.bits();
for (int h = 0; h < ximage->height; h++) { const int imagebpl = image.bytesPerLine();
uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h); for (int h = 0; h < ximage->height; h++) {
for (int w = 0; w < ximage->width; w++) { uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h);
const uint xpixel = XGetPixel(ximage, w, h); for (int w = 0; w < ximage->width; w++) {
//make sure alpha is 255, we depend on it in qdrawhelper for cases const uint xpixel = XGetPixel(ximage, w, h);
// when image is set as a texture pattern on a qbrush //make sure alpha is 255, we depend on it in qdrawhelper for cases
((uint *)imageline)[w] = uint(255 << 24) | xpixel; // when image is set as a texture pattern on a qbrush
((uint *)imageline)[w] = uint(255 << 24) | xpixel;
}
} }
break;
}
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied: {
uchar *imagedata = image.bits();
const int imagebpl = image.bytesPerLine();
for (int h = 0; h < ximage->height; h++) {
uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h);
for (int w = 0; w < ximage->width; w++) {
const uint xpixel = XGetPixel(ximage, w, h);
((uint *)imageline)[w] = xpixel;
}
}
break;
}
case QImage::Format_RGB16: {
uchar *imagedata = image.bits();
const int imagebpl = image.bytesPerLine();
for (int h = 0; h < ximage->height; h++) {
uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h);
for (int w = 0; w < ximage->width; w++) {
const quint16 xpixel = XGetPixel(ximage, w, h);
((quint16 *)imageline)[w] = xpixel;
}
}
break;
} }
break;
} }
case QImage::Format_ARGB32: return;
case QImage::Format_ARGB32_Premultiplied: { }
uchar *imagedata = image.bits();
const int imagebpl = image.bytesPerLine(); for (int h = 0; h < ximage->height; h++) {
for (int h = 0; h < ximage->height; h++) { for (int w = 0; w < ximage->width; w++) {
uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h); const uint xpixel = XGetPixel(ximage, w, h);
for (int w = 0; w < ximage->width; w++) { image.setPixel(w, h, xpixel);
const uint xpixel = XGetPixel(ximage, w, h);
((uint *)imageline)[w] = xpixel;
}
}
break;
}
case QImage::Format_RGB16: {
uchar *imagedata = image.bits();
const int imagebpl = image.bytesPerLine();
for (int h = 0; h < ximage->height; h++) {
uchar* imageline = QFAST_SCAN_LINE(imagedata, imagebpl, h);
for (int w = 0; w < ximage->width; w++) {
const quint32 xpixel = XGetPixel(ximage, w, h);
((quint16 *)imageline)[w] = qt_colorConvert<quint16, quint32>(xpixel, 0);
}
}
break;
}
default: {
for (int h = 0; h < ximage->height; h++) {
for (int w = 0; w < ximage->width; w++) {
const uint xpixel = XGetPixel(ximage, w, h);
image.setPixel(w, h, xpixel);
}
}
break;
} }
} }
} }