0

I've long since had a snippet of code in my iPhone app that attempts to mask the white background from some JPEG images. Today, this message still works well on iPhone, but does not mask whatsoever on Apple Watch. The code runs on the expected successful (non-NULL) path, but no masking is performed. Even if I change the maskingColors array to the range 0.0, 255.0 for each component, no masking is performed (this same change on iPhone completely masks the image) when displayed in a WKInterfaceImage (with setImage:).

PNG images with an alpha channel stored in an asset catalog seem to display properly on Apple Watch in a WKInterfaceImage.

Is CGImageCreateWithMaskingColors not safe for Apple Watch?

- (UIImage *)imageWithBackgroundRemovedWithImageData:(NSData *)imageData
{
    CGImageRef originalImage = [UIImage imageWithData:imageData].CGImage;

    /* Only attempt for RGB images */
    if (CGColorSpaceGetModel(CGImageGetColorSpace(originalImage)) != kCGColorSpaceModelRGB)
        return ([UIImage imageWithData:imageData]);

    /* Mask 10 shades of "white" */
    static const CGFloat maskingColors[] = {245.0, 255.0, 245.0, 255.0, 245.0, 255.0};
    CGImageRef transparentImageRef = CGImageCreateWithMaskingColors(originalImage, maskingColors);
    if (transparentImageRef == NULL)
        return ([UIImage imageWithData:imageData]);

    UIImage *transparentImage = [UIImage imageWithCGImage:transparentImageRef];
    CGImageRelease(transparentImageRef);
    return (transparentImage);
}
greg
  • 4,843
  • 32
  • 47
  • Can you add the Watch code (i.e. how you're encoding and setting the image)? – Mike Swanson Apr 25 '15 at 00:35
  • @MikeSwanson I am simply calling `setData` with the return of the posted code on a `WKInterfaceImage` in a row of a `WKInterfaceTable`. The `NSData` I am sending it is downloaded from a website as a JPEG from the iPhone app and transferred to the watch in the `reply` block from `openParentApplication`. I've also tried performing the masking step on the phone and sending the resulting `UIImagePNGRepresentation()` to the watch with the same results. – greg Apr 25 '15 at 02:52
  • Correction: setImage, not setData obviously. – greg Apr 25 '15 at 02:59
  • Aha. `setImage`...that's why I was confused. – Mike Swanson Apr 25 '15 at 06:06
  • I moved this code into a shared framework, and linked to the framework from an iPhone and Apple Watch app so I could be 100% sure that the code was identical. It performs as expected on iPhone but not on Apple Watch. Assuming it's a bug, and filed as radr://20702557. – greg Apr 26 '15 at 20:51
  • It doesn't make sense that it wouldn't work on the Watch, as you're simply passing a UIImage. This could be a situation where the UIImage creation is somehow being deferred, causing the issue. For testing, try converting the UIImage to PNG, then immediately creating another UIImage based on that data. You wouldn't want to keep that code, but it might help determine where the problem lies. – Mike Swanson Apr 26 '15 at 21:59
  • @MikeSwanson I just tried this, and it does not work :( – FlavienSi Apr 29 '15 at 13:04
  • @greg hi greg ! I just answered you on your topic in apple forums. I have exactly the same problem. Do you have any improvements on this ? thnks. – FlavienSi Apr 29 '15 at 13:05
  • @FlavienSi nothing new. Identical code works on iPhone but not on Apple Watch. Must be a bug, please duplicate my radar (20702557). I might use a TSI, but I think I should wait until after seeing what's new at WWDC. – greg Apr 29 '15 at 16:23

1 Answers1

1

This appears to be an issue that has existed since iOS 7. See this post for more details: CGImageCreateWithMaskingColors Doesn't Work with iOS7

Using that logic, I've modified your code as follows to produce the intended result:

UIGraphicsBeginImageContextWithOptions(transparentImage.size, NO, 1.0);
[transparentImage drawInRect:CGRectMake(0, 0, transparentImage.size.width, transparentImage.size.height)];
UIImage *anotherRendition = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return (anotherRendition);
Community
  • 1
  • 1
Mike Swanson
  • 3,337
  • 1
  • 17
  • 15
  • I'll be setting the `scale` parameter of `UIGraphicsBeginImageContextWithOptions` to 0 instead of 1, but this does work. Really does seem to be a bug though. – greg Apr 30 '15 at 01:04