Skip to content

Commit

Permalink
Merge pull request #54 from SDWebImage/bugfix_encoding_leak
Browse files Browse the repository at this point in the history
Fix the encoding leak when input CGImage is not RGBA8888 or RGB888
  • Loading branch information
dreampiggy authored Feb 24, 2021
2 parents 7d68ede + 44b1aae commit 9d3c8fd
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions SDWebImageWebPCoder/Classes/SDImageWebPCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -762,20 +762,21 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef
if (!dataProvider) {
return nil;
}
CFDataRef dataRef = CGDataProviderCopyData(dataProvider);
if (!dataRef) {
return nil;
}
// Check colorSpace is RGB/RGBA
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
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`
// 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 isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
if (isRGB888 || isRGBA8888) {
// If the input CGImage is already RGB888/RGBA8888
dataRef = CGDataProviderCopyData(dataProvider);
if (!dataRef) {
return nil;
}
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
} else {
// Convert all other cases to target color mode using vImage
Expand All @@ -798,37 +799,37 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef

convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error);
if (error != kvImageNoError) {
CFRelease(dataRef);
return nil;
}

vImage_Buffer src;
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
if (error != kvImageNoError) {
vImageConverter_Release(convertor);
CFRelease(dataRef);
return nil;
}

vImage_Buffer dest;
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
if (error != kvImageNoError) {
vImageConverter_Release(convertor);
CFRelease(dataRef);
free(src.data);
return nil;
}

// Convert input color mode to RGB888/RGBA8888
error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags);

// Free the buffer
free(src.data);
vImageConverter_Release(convertor);
if (error != kvImageNoError) {
CFRelease(dataRef);
free(dest.data);
return nil;
}

rgba = dest.data; // Converted buffer
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);
}

Expand Down

0 comments on commit 9d3c8fd

Please sign in to comment.