这个 Bug 是在将工程的 Deployment Target 从 8.0 升级到 9.0 后出现的, 错误代码如下:
NSDictionary *optionDict = @{GLKTextureLoaderOriginBottomLeft:@(YES)};
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:procImgRef options:optionDict error:&error];
错误信息:
ErrorDomain=GLKTextureLoaderErrorDomain errorCode=12
同样的代码在 Deployment Target = 8.0 时没有问题...
过程:
升级OpenGL ES 2.0 -> 3.0 遇到同样错误.
查看OpenGL ES 3.0 新功能和改动, 并无纹理加载的相关的改动.
尝试更换加载API:
// 失败
+ (nullable GLKTextureInfo *)textureWithContentsOfFile:(NSString *)path /* File path of image. */
options:(nullable NSDictionary<NSString*, NSNumber*> *)options /* Options that control how the image is loaded. */
error:(NSError * __nullable * __nullable)outError; /* Error description. */
// 通过 UIImagePNGRepresentation 转换成 Data 后加载成功, 但是 Alpha 通道数据异常
+ (nullable GLKTextureInfo *)textureWithContentsOfData:(NSData *)data /* NSData containing image contents. */
options:(nullable NSDictionary<NSString*, NSNumber*> *)options /* Options that control how the image is loaded. */
error:(NSError * __nullable * __nullable)outError; /* Error description. */
尝试转成JPEG后加载, 丢失透明通道, 但是加载成功.
以为是格式问题, 代码创建Bitmap上下文并重新渲染, 生成了各种格式的图片, 发现只有 CGImageAlphaInfo = kCGImageAlphaNone 的图片能加载成功.
大致判断错误应该是在Alpha通道上, 仔细查看 Texture Loading Options 参数, 发现一个选项:
/*
Dictionary keys for texture loader properties
*/
/*
GLKTextureLoaderApplyPremultiplication - A boolean NSNumber.
Non-alpha channels are premultiplied by corresponding alpha channel values.
For compressed formats, this option must be omitted, or false.
False by default.
*/
GLK_EXTERN NSString *const GLKTextureLoaderApplyPremultiplication NS_AVAILABLE(10_8, 5_0);
即应用自左乘.
添加参数 GLKTextureLoaderApplyPremultiplication 并设置成 YES, 加载成功!
CGImageAlphaInfo 有如下几种:
typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
kCGImageAlphaNone, /* For example, RGB. */
kCGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */
kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
kCGImageAlphaLast, /* For example, non-premultiplied RGBA */
kCGImageAlphaFirst, /* For example, non-premultiplied ARGB */
kCGImageAlphaNoneSkipLast, /* For example, RBGX. */
kCGImageAlphaNoneSkipFirst, /* For example, XRGB. */
kCGImageAlphaOnly /* No color data, alpha data only */
};
后来查了一下我的 CGImageAlphaInfo 是 kCGImageAlphaPremultipliedLast.
按理说这个参数一直都要设置成YES才行.
很奇怪的是 这个问题在 8.0 的时候没有问题, 怎么到 9.0 就崩溃了....
解决办法:
optionDict 添加配置参数 GLKTextureLoaderApplyPremultiplication 并设置为 YES 并更换 API
NSDictionary *optionDict = @{GLKTextureLoaderOriginBottomLeft:@(YES), GLKTextureLoaderApplyPremultiplication:@(YES)};
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfData:UIImagePNGRepresentation(procImg) options:optionDict error:&error];