diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 944dd04b8c..d6037fb2d6 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4424,6 +4424,8 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla InPlace_Image_Converter converter = *converterPtr; if (converter) return converter(this, flags); + else if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8) + return convert_generic_inplace(this, newFormat, flags); else return false; } diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 193ef59fcd..f53eed1c43 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -138,6 +138,40 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio } } +// Cannot be used with indexed formats or between formats with different pixel depths. +bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags) +{ + Q_ASSERT(dst_format > QImage::Format_Indexed8); + Q_ASSERT(data->format > QImage::Format_Indexed8); + if (data->depth != qt_depthForFormat(dst_format)) + return false; + + const int buffer_size = 2048; + uint buffer[buffer_size]; + const QPixelLayout *srcLayout = &qPixelLayouts[data->format]; + const QPixelLayout *destLayout = &qPixelLayouts[dst_format]; + + uchar *srcData = data->data; + + FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; + StorePixelsFunc store = qStorePixels[destLayout->bpp]; + + for (int y = 0; y < data->height; ++y) { + int x = 0; + while (x < data->width) { + int l = qMin(data->width - x, buffer_size); + const uint *ptr = fetch(buffer, srcData, x, l); + ptr = srcLayout->convertToARGB32PM(buffer, ptr, l, srcLayout, 0); + ptr = destLayout->convertFromARGB32PM(buffer, ptr, l, destLayout, 0); + store(srcData, ptr, x, l); + x += l; + } + srcData += data->bytes_per_line; + } + data->format = dst_format; + return true; +} + static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 2a280a2b18..81730b92f2 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -115,6 +115,7 @@ extern Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImag extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats]; void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); +bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags); void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);