Skip to content

Commit 09faa3a

Browse files
committed
fix: sd_colorAtPoint should early return when pixel format is not supported
1 parent c085d53 commit 09faa3a

File tree

4 files changed

+38
-13
lines changed

4 files changed

+38
-13
lines changed

SDWebImage/Core/SDImageCoder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeUseLazyDec
8989
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeScaleDownLimitBytes;
9090

9191
/**
92-
A Boolean value to provide converting to HDR during decoding.
92+
A Boolean value (NSNumber) to provide converting to HDR during decoding. Currently if number is 0, use SDR, else use HDR. But we may extend this option to use `NSUInteger` in the future (means, think this options as int number, but not actual boolean)
9393
@note Supported by iOS 17 and above when using ImageIO coder (third-party coder can support lower firmware)
94-
Defaults to NO, decoder will automatically convert SDR.
94+
Defaults to @(NO), decoder will automatically convert SDR.
9595
@note works for `SDImageCoder`
9696
*/
9797
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeToHDR;

SDWebImage/Core/SDWebImageDefine.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,9 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageT
338338
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageScaleDownLimitBytes;
339339

340340
/**
341-
A Boolean value to provide converting to HDR during decoding.
341+
A Boolean value (NSNumber) to provide converting to HDR during decoding. Currently if number is 0, use SDR, else use HDR. But we may extend this option to use `NSUInteger` in the future (means, think this options as int number, but not actual boolean)
342342
@note Supported by iOS 17 and above when using ImageIO coder (third-party coder can support lower firmware)
343-
Defaults to NO, decoder will automatically convert SDR.
343+
Defaults to @(NO), decoder will automatically convert SDR.
344344
*/
345345
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageDecodeToHDR;
346346

SDWebImage/Core/UIImage+Transform.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) {
123123
@note The overhead of object creation means this method is best suited for infrequent color sampling. For heavy image processing, grab the raw bitmap data and process yourself.
124124
125125
@param point The position of pixel
126+
@warning This API currently support 8 bits per component only (RGBA8888 etc), not RGBA16U/RGBA10
126127
@return The color for specify pixel, or nil if any error occur
127128
*/
128129
- (nullable UIColor *)sd_colorAtPoint:(CGPoint)point;

SDWebImage/Core/UIImage+Transform.m

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static inline CGRect SDCGRectFitWithScaleMode(CGRect rect, CGSize size, SDImageS
149149
#endif
150150
}
151151

152-
static inline UIColor * SDGetColorFromRGBA(Pixel_8888 pixel, CGBitmapInfo bitmapInfo, CGColorSpaceRef cgColorSpace) {
152+
static inline UIColor * SDGetColorFromRGBA8(Pixel_8888 pixel, CGBitmapInfo bitmapInfo, CGColorSpaceRef cgColorSpace) {
153153
// Get alpha info, byteOrder info
154154
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
155155
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
@@ -752,6 +752,19 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
752752
return nil;
753753
}
754754

755+
// Check pixel format
756+
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
757+
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
758+
if (@available(iOS 12.0, tvOS 12.0, macOS 10.14, watchOS 5.0, *)) {
759+
CGImagePixelFormatInfo pixelFormat = (bitmapInfo & kCGImagePixelFormatMask);
760+
if (pixelFormat != kCGImagePixelFormatPacked || bitsPerComponent > 8) {
761+
// like RGBA1010102, need bitwise to extract pixel from single uint32_t, we don't support currently
762+
SD_LOG("Unsupported pixel format: %u, bpc: %zu for CGImage: %@", pixelFormat, bitsPerComponent, imageRef);
763+
CGImageRelease(imageRef);
764+
return nil;
765+
}
766+
}
767+
755768
// Get pixels
756769
CGDataProviderRef provider = CGImageGetDataProvider(imageRef);
757770
if (!provider) {
@@ -766,8 +779,7 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
766779

767780
// Get pixel at point
768781
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
769-
size_t components = CGImageGetBitsPerPixel(imageRef) / CGImageGetBitsPerComponent(imageRef);
770-
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
782+
size_t components = CGImageGetBitsPerPixel(imageRef) / bitsPerComponent;
771783

772784
CFRange range = CFRangeMake(bytesPerRow * y + components * x, components);
773785
if (CFDataGetLength(data) < range.location + range.length) {
@@ -793,7 +805,7 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
793805
CFRelease(data);
794806
CGImageRelease(imageRef);
795807
// Convert to color
796-
return SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
808+
return SDGetColorFromRGBA8(pixel, bitmapInfo, colorSpace);
797809
} else {
798810
SD_LOG("Unsupported components: %zu", components);
799811
CFRelease(data);
@@ -826,6 +838,19 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
826838
return nil;
827839
}
828840

841+
// Check pixel format
842+
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
843+
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
844+
if (@available(iOS 12.0, tvOS 12.0, macOS 10.14, watchOS 5.0, *)) {
845+
CGImagePixelFormatInfo pixelFormat = (bitmapInfo & kCGImagePixelFormatMask);
846+
if (pixelFormat != kCGImagePixelFormatPacked || bitsPerComponent > 8) {
847+
// like RGBA1010102, need bitwise to extract pixel from single uint32_t, we don't support currently
848+
SD_LOG("Unsupported pixel format: %u, bpc: %zu for CGImage: %@", pixelFormat, bitsPerComponent, imageRef);
849+
CGImageRelease(imageRef);
850+
return nil;
851+
}
852+
}
853+
829854
// Get pixels
830855
CGDataProviderRef provider = CGImageGetDataProvider(imageRef);
831856
if (!provider) {
@@ -840,7 +865,7 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
840865

841866
// Get pixels with rect
842867
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
843-
size_t components = CGImageGetBitsPerPixel(imageRef) / CGImageGetBitsPerComponent(imageRef);
868+
size_t components = CGImageGetBitsPerPixel(imageRef) / bitsPerComponent;
844869

845870
size_t start = bytesPerRow * CGRectGetMinY(rect) + components * CGRectGetMinX(rect);
846871
size_t end = bytesPerRow * (CGRectGetMaxY(rect) - 1) + components * CGRectGetMaxX(rect);
@@ -855,7 +880,6 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
855880
size_t col = CGRectGetMaxX(rect);
856881

857882
// Convert to color
858-
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
859883
NSMutableArray<UIColor *> *colors = [NSMutableArray arrayWithCapacity:CGRectGetWidth(rect) * CGRectGetHeight(rect)];
860884
// ColorSpace
861885
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
@@ -874,12 +898,12 @@ - (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
874898
} else {
875899
if (components == 3) {
876900
Pixel_8888 pixel = {pixels[index], pixels[index+1], pixels[index+2], 0};
877-
color = SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
901+
color = SDGetColorFromRGBA8(pixel, bitmapInfo, colorSpace);
878902
} else if (components == 4) {
879903
Pixel_8888 pixel = {pixels[index], pixels[index+1], pixels[index+2], pixels[index+3]};
880-
color = SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
904+
color = SDGetColorFromRGBA8(pixel, bitmapInfo, colorSpace);
881905
} else {
882-
SD_LOG("Unsupported components: %zu", components);
906+
SD_LOG("Unsupported components: %zu for CGImage: %@", components, imageRef);
883907
}
884908
}
885909
if (color) {

0 commit comments

Comments
 (0)