diff --git a/Source/ASImageNode.mm b/Source/ASImageNode.mm index 063617b5a..27e8e05f2 100644 --- a/Source/ASImageNode.mm +++ b/Source/ASImageNode.mm @@ -473,9 +473,17 @@ + (UIImage *)createContentsForkey:(ASImageNodeContentsKey *)key drawParameters:( return nil; } + // If the image is opaque, and the draw rect contains the bounds rect, we can use an opaque context. + UIImage *image = key.image; + const CGRect imageDrawRect = key.imageDrawRect; + const CGRect contextBounds = { CGPointZero, key.backingSize }; + const BOOL imageIsOpaque = ASImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(image.CGImage)); + const BOOL imageFillsContext = CGRectContainsRect(imageDrawRect, contextBounds); + const BOOL contextIsOpaque = (imageIsOpaque && imageFillsContext) || key.isOpaque; + // Use contentsScale of 1.0 and do the contentsScale handling in boundsSizeInPixels so ASCroppedImageBackingSizeAndDrawRectInBounds // will do its rounding on pixel instead of point boundaries - ASGraphicsBeginImageContextWithOptions(key.backingSize, key.isOpaque, 1.0); + ASGraphicsBeginImageContextWithOptions(contextBounds.size, contextIsOpaque, 1.0); BOOL contextIsClean = YES; @@ -503,13 +511,12 @@ + (UIImage *)createContentsForkey:(ASImageNodeContentsKey *)key drawParameters:( // upon removal of the object from the set when the operation completes. // Another option is to have ASDisplayNode+AsyncDisplay coordinate these cases, and share the decoded buffer. // Details tracked in https://github.com/facebook/AsyncDisplayKit/issues/1068 - - UIImage *image = key.image; - BOOL canUseCopy = (contextIsClean || ASImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(image.CGImage))); + + BOOL canUseCopy = (contextIsClean || imageIsOpaque); CGBlendMode blendMode = canUseCopy ? kCGBlendModeCopy : kCGBlendModeNormal; @synchronized(image) { - [image drawInRect:key.imageDrawRect blendMode:blendMode alpha:1]; + [image drawInRect:imageDrawRect blendMode:blendMode alpha:1]; } if (context && key.didDisplayNodeContentWithRenderingContext) {