Implement inplace image conversion for generic down conversions
If the destination image format is smaller than the source one, allow an inplace conversion followed by a shrinking realloc. Change-Id: I99b3e285e06fb37fd5fe7412749fa87f4cf2ee9a Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
587f1cbc5d
commit
b10e1209e1
@ -257,7 +257,8 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
// Cannot be used with indexed formats or between formats with different pixel depths.
|
||||
Q_ASSERT(dst_format > QImage::Format_Indexed8);
|
||||
Q_ASSERT(data->format > QImage::Format_Indexed8);
|
||||
if (data->depth != qt_depthForFormat(dst_format))
|
||||
const int destDepth = qt_depthForFormat(dst_format);
|
||||
if (data->depth < destDepth)
|
||||
return false;
|
||||
|
||||
const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
|
||||
@ -272,9 +273,16 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
uint buf[BufferSize];
|
||||
uint *buffer = buf;
|
||||
uchar *srcData = data->data;
|
||||
uchar *destData = data->data;
|
||||
|
||||
Q_ASSERT(srcLayout->bpp == destLayout->bpp);
|
||||
Q_ASSERT(srcLayout->bpp != QPixelLayout::BPP64);
|
||||
QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes };
|
||||
if (data->depth != destDepth) {
|
||||
params = QImageData::calculateImageParameters(data->width, data->height, destDepth);
|
||||
if (!params.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_ASSERT(destLayout->bpp != QPixelLayout::BPP64);
|
||||
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
@ -316,15 +324,26 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
while (x < data->width) {
|
||||
dither.x = x;
|
||||
int l = data->width - x;
|
||||
if (destLayout->bpp == QPixelLayout::BPP32)
|
||||
if (srcLayout->bpp == QPixelLayout::BPP32)
|
||||
buffer = reinterpret_cast<uint *>(srcData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr);
|
||||
store(srcData, ptr, x, l, nullptr, ditherPtr);
|
||||
store(destData, ptr, x, l, nullptr, ditherPtr);
|
||||
x += l;
|
||||
}
|
||||
srcData += data->bytes_per_line;
|
||||
destData += params.bytesPerLine;
|
||||
}
|
||||
if (params.totalSize != data->nbytes) {
|
||||
Q_ASSERT(params.totalSize < data->nbytes);
|
||||
void *newData = realloc(data->data, params.totalSize);
|
||||
if (newData) {
|
||||
data->data = (uchar *)newData;
|
||||
data->nbytes = params.totalSize;
|
||||
}
|
||||
data->bytes_per_line = params.bytesPerLine;
|
||||
data->depth = destDepth;
|
||||
}
|
||||
data->format = dst_format;
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user