Add generic inplace converter

The generic converter can easily be modified to work inplace. Such
an inplace converter can ensure we can do direct conversion between
formats of similar pixel depth.

Inplace conversion is currently only used by QPixmaps, but will be used
by ref qualified versions of QImage::convertToFormat in a future patch.

Change-Id: Idbdaf087b53deecdee8258ba0b5d80edd37cfe79
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
This commit is contained in:
Allan Sandfeld Jensen 2014-01-10 13:31:32 +01:00 committed by The Qt Project
parent 0e65cec6b4
commit b157a57953
3 changed files with 37 additions and 0 deletions

View File

@ -4424,6 +4424,8 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
InPlace_Image_Converter converter = *converterPtr; InPlace_Image_Converter converter = *converterPtr;
if (converter) if (converter)
return converter(this, flags); return converter(this, flags);
else if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8)
return convert_generic_inplace(this, newFormat, flags);
else else
return false; return false;
} }

View File

@ -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) 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); Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);

View File

@ -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]; extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats];
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); 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); void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);