为什么 iPhone 7 和 iPhone 7 Plus 屏幕截图会发送不兼容的 alpha 与 RGB 色彩空间图像?

set*_*ite 3 iphone objective-c ios ios10

我正在尝试创建位图上下文以调整从相机胶卷导入的图像的大小。这是代码:

    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                            newRect.size.width,
                                            newRect.size.height,
                                            CGImageGetBitsPerComponent(imageRef),
                                            0,
                                            CGImageGetColorSpace(imageRef),
                                            CGImageGetBitmapInfo(imageRef));
Run Code Online (Sandbox Code Playgroud)

我在 iPhone 7 上截取了两个屏幕截图,当我尝试从相机胶卷加载它们时,一个失败,另一个成功。

第一个是失败的:

<CGImage 0x1701de3c0>
<<CGColorSpace 0x174a325c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Display P3)>
    width = 750, height = 1334, bpc = 16, bpp = 64, row bytes = 6000 
    kCGImageAlphaLast | kCGImageByteOrder16Little 
    is mask? No, has mask? No, has matte? No, should interpolate? Yes
Run Code Online (Sandbox Code Playgroud)

这是错误:

<Error>: CGBitmapContextCreate: unsupported parameter combination:
     16 integer bits/component;
     64 bits/pixel;
    RGB color space model; kCGImageAlphaLast;
    3840 bytes/row.
Valid parameters for RGB color space model are:
    16  bits per pixel,         5  bits per component,         kCGImageAlphaNoneSkipFirst
    32  bits per pixel,         8  bits per component,         kCGImageAlphaNoneSkipFirst
    32  bits per pixel,         8  bits per component,         kCGImageAlphaNoneSkipLast
    32  bits per pixel,         8  bits per component,         kCGImageAlphaPremultipliedFirst
    32  bits per pixel,         8  bits per component,         kCGImageAlphaPremultipliedLast
    64  bits per pixel,         16 bits per component,         kCGImageAlphaPremultipliedLast
    64  bits per pixel,         16 bits per component,         kCGImageAlphaNoneSkipLast
    64  bits per pixel,         16 bits per component,         kCGImageAlphaPremultipliedLast|kCGBitmapFloatComponents
    64  bits per pixel,         16 bits per component,         kCGImageAlphaNoneSkipLast|kCGBitmapFloatComponents
    128 bits per pixel,         32 bits per component,         kCGImageAlphaPremultipliedLast|kCGBitmapFloatComponents
    128 bits per pixel,         32 bits per component,         kCGImageAlphaNoneSkipLast|kCGBitmapFloatComponents
See Quartz 2D Programming Guide (available online) for more information.
Run Code Online (Sandbox Code Playgroud)

第二个是成功的:

<CGImage 0x1705c0a50>
<<CGColorSpace 0x17402b7c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)>
    width = 750, height = 1334, bpc = 8, bpp = 32, row bytes = 3000 
    kCGImageAlphaPremultipliedLast | 0 (default byte order) 
    is mask? No, has mask? No, has matte? No, should interpolate? Yes
Run Code Online (Sandbox Code Playgroud)

我找不到关于这种特殊情况的任何明确信息。所以,我想知道是否有人对此问题有任何见解以及可能的修复建议。我在这里完全不知所措。

我的崩溃日志表明此问题仅在我的 iPhone 7 和 iPhone 7 Plus 用户上发现。

提前致谢。

pin*_*nch 5

我希望有人找到更好的解决方案,因为这是一个 hack,但这是我的解决方法:

kCGImageAlphaLast参数是该位图信息中不受支持的部分。对于图像完全不透明的情况,您可以使用kCGImageAlphaPremultipliedLast并获得相同的结果,因为 alpha 预乘,在完全不透明的情况下,本质上是一个空操作(每个像素都乘以 1)。

但警告,如果图像有任何半透明像素,它们的颜色将是错误的。在我的情况下,我希望照片完全不透明,否则用户没有正确使用我的应用程序,所以我现在可以忍受。

CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

// first try
CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                        newRect.size.width,
                                        newRect.size.height,
                                        CGImageGetBitsPerComponent(imageRef),
                                        0,
                                        CGImageGetColorSpace(imageRef),
                                        bitmapInfo);

if (!bitmap && (bitmapInfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaLast) {

    // WARNING - only do this if you expect a fully opaque image

    // try again with pre-multiply alpha

    // clear alpha bits
    bitmapInfo &= ~kCGBitmapAlphaInfoMask;
    // set pre-multiply last
    bitmapInfo |= kCGImageAlphaPremultipliedLast & kCGBitmapAlphaInfoMask;

    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                        newRect.size.width,
                                        newRect.size.height,
                                        CGImageGetBitsPerComponent(imageRef),
                                        0,
                                        CGImageGetColorSpace(imageRef),
                                        bitmapInfo);

}

if (!bitmap) {
    // fail gracefully
}
Run Code Online (Sandbox Code Playgroud)