Fix the encoding leak when input CGImage is not RGBA8888 or RGB888
This commit is contained in:
parent
7d68eded0c
commit
44b1aae3c9
|
@ -762,20 +762,21 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
if (!dataProvider) {
|
if (!dataProvider) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
CFDataRef dataRef = CGDataProviderCopyData(dataProvider);
|
|
||||||
if (!dataRef) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
// Check colorSpace is RGB/RGBA
|
// Check colorSpace is RGB/RGBA
|
||||||
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
|
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
|
||||||
BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB;
|
BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB;
|
||||||
|
|
||||||
|
CFDataRef dataRef;
|
||||||
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
|
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
|
||||||
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
|
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
|
||||||
BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3;
|
BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3;
|
||||||
BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
|
BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
|
||||||
if (isRGB888 || isRGBA8888) {
|
if (isRGB888 || isRGBA8888) {
|
||||||
// If the input CGImage is already RGB888/RGBA8888
|
// If the input CGImage is already RGB888/RGBA8888
|
||||||
|
dataRef = CGDataProviderCopyData(dataProvider);
|
||||||
|
if (!dataRef) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
|
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
|
||||||
} else {
|
} else {
|
||||||
// Convert all other cases to target color mode using vImage
|
// Convert all other cases to target color mode using vImage
|
||||||
|
@ -798,7 +799,6 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
|
|
||||||
convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error);
|
convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error);
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
CFRelease(dataRef);
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,7 +806,6 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
|
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
vImageConverter_Release(convertor);
|
vImageConverter_Release(convertor);
|
||||||
CFRelease(dataRef);
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,21 +813,23 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
|
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
vImageConverter_Release(convertor);
|
vImageConverter_Release(convertor);
|
||||||
CFRelease(dataRef);
|
free(src.data);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert input color mode to RGB888/RGBA8888
|
// Convert input color mode to RGB888/RGBA8888
|
||||||
error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags);
|
error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags);
|
||||||
|
|
||||||
|
// Free the buffer
|
||||||
|
free(src.data);
|
||||||
vImageConverter_Release(convertor);
|
vImageConverter_Release(convertor);
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
CFRelease(dataRef);
|
free(dest.data);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
rgba = dest.data; // Converted buffer
|
rgba = dest.data; // Converted buffer
|
||||||
bytesPerRow = dest.rowBytes; // Converted bytePerRow
|
bytesPerRow = dest.rowBytes; // Converted bytePerRow
|
||||||
CFRelease(dataRef); // Use CFData to manage bytes for free, the same code path for error handling
|
|
||||||
dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault);
|
dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue