iphoneioscore-animationtransitionpixelate

Pixelate transition in iOS


How do you implement a pixelate transition like this (animated gif) in iOS?

Is it possible to implement with Core Animation?


Solution

  • C4 - Travis' comment being correct, your best option is probably to render the animation live yourself. You'll want to take the code in QA1703 for screen capture, but adjust the size of the context you create at UIGraphicsBeginImageContextWithOptions and alter the Core Graphics current transform matrix (CTM) appropriately immediately after the call to UIGraphicsGetCurrentContext. So, just typing as I write this, your adjustments would be to result in something like:

    - (UIImage*)screenshotWithScale:(CGFloat)scale
    {
        // Create a graphics context with the target size
        // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
        // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
        CGSize imageSize = [[UIScreen mainScreen] bounds].size;
    
        /* YOU'VE ADDED: */
        imageSize.width *= scale;
        imageSize.height *= scale;
    
        if (NULL != UIGraphicsBeginImageContextWithOptions)
        /* ... then stuff as per the original, down to ... */
    
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSaveGState(context);
        CGContextScaleCTM(context, scale, scale);
    
        // Iterate over every window from back to front
        for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
            /* etc, etc, down to... */
    
         // Retrieve the screenshot image
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
        CGContextRestoreGState(context);
        UIGraphicsEndImageContext();
    
        return image;
    }
    

    With scale = 1.0, you'll get back a UIImage exactly equal to the screen. With scale = 0.5 you'll get one with half as many pixels across and down, with scale = 0.25 you'll get a quarter as many pixels across and down, etc.

    You can then put that UIImage into a UIImageView, and set its layer's magnification filter to kCAFilterNearest. Showing that image view should give you a deliberatedly pixellated version of the original. You can then either be lazy and just keep performing a half-size render of what's already on screen (so the live view the first time, the image view subsequently) or adapt the code not to render from the main window but rather from a nominated view and re-render from the original view hierarchy as required (which would work if you wanted to do something other than keep dividing the scale by an integer).