Applying transformed image layer to renderInContext:

WrightsCS picture WrightsCS · Sep 7, 2011 · Viewed 7.5k times · Source

Background

I am using Erica Saduns Cookbook example from Chapter 8, Example 14 — Resize and Rotate to obviously resize and rotate a UIImageView.

VIew hierarchy

1.) striped background view.

2.) the interactive view which can be resize and rotate.

3.) an overlay image with a transparent portion. this view starts its y axis at 128 and is 768x768.

4.) above and below 3, are 2 views 128 in height.

******See Photo example below****

Issue

Currently, I can save the entire view's layer to the photo library using [[[self view] layer] renderInContext:, and #2's transformations are correct. However, I need a way to save a 768x768 (lime green in photo example) frame that only includes #2 and #3, including #2's transformations. If I use [[#2 layer] renderInContext:, I get the original image, and no transformations. (see screenshot below for # reference.

Code

CGSize deviceSpec;
if ( IDIOM == IPAD ) { deviceSpec =CGSizeMake(768,768); } else { deviceSpec =CGSizeMake(320,480); }
if (  scale > 1.5  ) {
    UIGraphicsBeginImageContextWithOptions(deviceSpec, NO, scale);
} else {
    UIGraphicsBeginImageContext( deviceSpec );
}        

    CGContextRef ctx = UIGraphicsGetCurrentContext();      

    [[stripedBg layer] renderInContext:ctx];  //#1    

        CGContextSaveGState(ctx);

            CGContextConcatCTM(ctx, [[interactiveImage layer] affineTransform]);

            //CGContextTranslateCTM(ctx, interactiveImage.frame.origin.x,interactiveImage.frame.origin.y-128);

            [[interactiveImage layer] renderInContext:ctx]; // #2

        CGContextRestoreGState(ctx);

    [[overlayImage layer] renderInContext:ctx]; // #3

    UIImage * draft = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

Photo Example

I only need the portion of the image that is outlined in LIME GREEN, while preserving the transformations by the user.

enter image description here

Answer

Lily Ballard picture Lily Ballard · Sep 8, 2011

If I understand you correctly, the issue is that you want to render just layer #2, but layer #2 has transforms that aren't preserved when rendering just that layer? You can apply those transforms to the graphics context's CTM (current transformation matrix) before you render the layer into that context. Something like this should work:

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextConcatCTM(ctx, [layer2 affineTransform]);
[layer2 renderInContext:ctx];
CGContextRestoreGState(ctx);

Note, the calls to CGContextSaveGState() and CGContextRestoreGState() are only necessary if you want to draw more stuff into the context after you draw the layer. You can omit them if the layer is all you want.