Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bmp image With imageFromDiskCacheForKey can't load in iOS15.2 and later #3330

Closed
JzwOnly opened this issue Mar 1, 2022 · 14 comments
Closed

bmp image With imageFromDiskCacheForKey can't load in iOS15.2 and later #3330

JzwOnly opened this issue Mar 1, 2022 · 14 comments
Labels
apple bug ImageIO

Comments

@JzwOnly
Copy link

@JzwOnly JzwOnly commented Mar 1, 2022

test bmp url: https://raw.githubusercontent.com/JzwOnly/unMec/main/001.bmp
SDWebImage Version: 5.12.3
iPhone in iOS 14.8 is ok
when I update to iOS 15.3.1 this bmp url can't show but disk memory bmp image no error

@JzwOnly JzwOnly changed the title bmp image can't load in iOS15.2 and later bmp image With imageFromDiskCacheForKey can't load in iOS15.2 and later Mar 1, 2022
@JzwOnly
Copy link
Author

@JzwOnly JzwOnly commented Mar 1, 2022

This is Demo for test
BMPTest.zip

  1. image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
  2. NSString * filePath = [[SDImageCache sharedImageCache] cachePathForKey:key]; image = [UIImage imageWithContentsOfFile:filePath];
    1 don't work show image, but 2 is ok

@JzwOnly
Copy link
Author

@JzwOnly JzwOnly commented Mar 1, 2022

@kinarobin
Copy link
Member

@kinarobin kinarobin commented Mar 2, 2022

This is Demo for test BMPTest.zip

  1. image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
  2. NSString * filePath = [[SDImageCache sharedImageCache] cachePathForKey:key]; image = [UIImage imageWithContentsOfFile:filePath];
    1 don't work show image, but 2 is ok

I test with you demo. 1 and 2 work perfect in iPhone 12 && iOS 15.3.1

@JzwOnly
Copy link
Author

@JzwOnly JzwOnly commented Mar 2, 2022

This is Demo for test BMPTest.zip

  1. image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
  2. NSString * filePath = [[SDImageCache sharedImageCache] cachePathForKey:key]; image = [UIImage imageWithContentsOfFile:filePath];
    1 don't work show image, but 2 is ok

I test with you demo. 1 and 2 work perfect in iPhone 12 && iOS 15.3.1

Are you use Simulator or real machine?
I test this demo in real machine(IPhoneXS and iPad Pro) 1 not work, 2 is ok

@kinarobin
Copy link
Member

@kinarobin kinarobin commented Mar 2, 2022

iPhone 12 Device.

@JzwOnly
Copy link
Author

@JzwOnly JzwOnly commented Mar 2, 2022

This is Demo Video https://user-images.githubusercontent.com/21191349/156117005-87bf5218-3c9e-4983-8a76-4663bf1a5c85.MP4

@kinarobin This video demo was shot with an iPad Pro
use ImageData to create Image is not work such as 1, but use filePath to create is ok.
I had to setup image with filePath in completeBlock again to fix it.
have better solution?

@dreampiggy dreampiggy added apple bug ImageIO labels Mar 3, 2022
@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 3, 2022

I guess this may be Apple ImageIO bug. We didn't do anything special to BMP format. Which should be handled by ImageIO codec.

Any intersting logs or open radar related ?

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 3, 2022

Seems this API cause blank image:

[SDImageCoderHelper decodedImageWithImage:image]

->

[SDImageCoderHelper CGImageCreateDecoded:]

->

CGBitmapContextCreate
CGContextDrawImage

The CGImageRef returned from ImageIO is:

<CGImage 0x7f8e2510abd0> (IP)
	<<CGColorSpace 0x60000049c420> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
		width = 1080, height = 1080, bpc = 8, bpp = 32, row bytes = 4320 
		kCGImageAlphaNoneSkipLast | 0 (default byte order)  | kCGImagePixelFormatPacked 
		is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 3, 2022

Seems Apple's bug. CGContext's draw call, should convert the RGBX8888 to our BGRX8888, which is documented behavior. However it fails on iOS 15.

A quick hack is to check the fomat and use the input CGImage's bitmap info to create CGContext.

PR will available later. And this sample BMP image will added to unit test.

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 8, 2022

One small question:

What's the meaning of [DP] and [IP] when print CGImage in debugger (seems via image_copy_format_description)

  • The input CGImage
<CGImage 0x7f8e2510abd0> (IP)
	<<CGColorSpace 0x60000049c420> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
		width = 1080, height = 1080, bpc = 8, bpp = 32, row bytes = 4320 
		kCGImageAlphaNoneSkipLast | 0 (default byte order)  | kCGImagePixelFormatPacked 
		is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes		
  • This one before PR #3332
<CGImage 0x7fdf13f16d10> (DP)
	<<CGColorSpace 0x6000007ad2c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
		width = 1080, height = 1080, bpc = 8, bpp = 32, row bytes = 4320 
		kCGImageAlphaNoneSkipFirst | kCGImageByteOrder32Little  | kCGImagePixelFormatPacked 
		is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes
  • This one after PR #3332
<CGImage 0x7fee621073a0> (DP)
	<<CGColorSpace 0x600002315620> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
		width = 1080, height = 1080, bpc = 8, bpp = 32, row bytes = 4320 
		kCGImageAlphaNoneSkipLast | 0 (default byte order)  | kCGImagePixelFormatPacked 
		is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes

Seems after the reverse engineering, I found the [DP] represent Data Provider (CGDataProvider)
and [IP] represent Image Provider (CGImageProvider)

image

image

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 8, 2022

Released v5.12.4

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 8, 2022

One tip: For new user who don't want that Force Decode, you can disable that when initialize SDWebImage.

See:

SDWebImageManager.sharedManager.optionsProcessor = [SDWebImageOptionsProcessor optionsProcessorWithBlock:^SDWebImageOptionsResult * _Nullable(NSURL * _Nullable url, SDWebImageOptions options, SDWebImageContext * _Nullable context) {
     // Disable Force Decoding in global, may reduce the frame rate
     options |= SDWebImageAvoidDecodeImage;
     return [[SDWebImageOptionsResult alloc] initWithOptions:options context:context];
}];

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 15, 2022

Can anyone limit the effect iOS version for this bug ?

I have no extra iPhones, but tested with iPhone 15.2 simulator

I found the reproduce way:

If CGContext: BGRX8888,
input CGImage: RGBX8888
CGContextDrwaImage will always return black.

However, if CGContext is BGRA8888(alpha channel), everything works.

@dreampiggy
Copy link
Contributor

@dreampiggy dreampiggy commented Mar 15, 2022

Can anyone limit the effect iOS version for this bug ?

I have no extra iPhones, but tested with iPhone 15.2 simulator

I found the reproduce way:

If CGContext: BGRX8888, input CGImage: RGBX8888 CGContextDrwaImage will always return black.

However, if CGContext is BGRA8888(alpha channel), everything works.

Check result:

  • iOS 12.4: work
  • iOS 13.5: work
  • iOS 14.8: work
  • iOS 15.0: fail
  • iOS 15.2: fail
  • iOS 15.3.1: fail

I assume this is a iOS 15+ only bug.

Reproduce Demo: https://github.com/dreampiggy/CGContextDrawImageBug
Radar: FB9958017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
apple bug ImageIO
Projects
None yet
Development

No branches or pull requests

3 participants