7

So, I am taking a screenshot of a subclassed UIView that I save into the device's photo stream.

Problem:

The problem is that I use resizableImageWithCapInsets to add a stretched background to my UIView, but this background gets cut off on the right side and I have no idea why. If someone could help me out it would be highly appreciated.

This is what the image looks like in the app (left) and after saving it into the photo stream (right)

I add the stretched background to my UIView the following way:

[diagramBase addSubview:[self addTileBackgroundOfSize:diagramBase.frame 
andType:@"ipad_diagram_border.png"]];

Which calls this method:

- (UIImageView *) addTileBackgroundOfSize:(CGRect)frame 
andType:(NSString *)type
{
frame.origin.x = 0.0f;
frame.origin.y = 0.0f;

UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:frame];
UIImage *image = [UIImage imageNamed:type];
UIEdgeInsets insets = UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f);
UIImage *backgroundImage = [image resizableImageWithCapInsets:insets];
backgroundView.image = backgroundImage;

return backgroundView;
}

The actual printscreen is done with this method (RINDiagramView is the name of my subclassed UIView, which I am taking a screenshot of). The rotation is in there because I need the image rotated when I save it, but I commented out that part and that is not what does the background to act weird.

- (UIImage *) createSnapshotOfView:(RINDiagram *) view
{
CGRect rect = [view bounds];
rect.size.height = rect.size.height - 81.0f;
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
                                            scale: 1.0
                                      orientation: UIImageOrientationLeft];
return finalImage;
}

I use Xcode 5.1 and everything is done programmatically (no storyboard and such). The base SDK is iOS 7.1.

Community
  • 1
  • 1
Gergely Kovacs
  • 1,045
  • 2
  • 10
  • 28
  • 2
    Could you post the "ipad_diagram_border.png" here? I'd like to have a try for the code. – simalone Mar 27 '14 at 06:37
  • 1
    Hi, here is the non-retina version: https://lh4.googleusercontent.com/-C0H3fZ9KE_8/UzfBqifmGwI/AAAAAAAAFEs/1TFA_ayygns/s0/ipad_diagram_border.png – Gergely Kovacs Mar 30 '14 at 07:03

4 Answers4

3

If you're doing iOS 7+ you can use the new drawViewHierarchyInRect:afterScreenUpdates: and related methods which Apple says are really performant.

Even if you're targeting iOS 6 you should give it a try to see if you get the same problem.

Rivera
  • 10,792
  • 3
  • 58
  • 102
2

Try using the correct scale?

UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
                                        scale: [[UIScreen mainScreen] scale]
                                  orientation: UIImageOrientationLeft];

Use a different UIViewContentMode?

UIViewContentModeScaleToFill -> check if you can see the edges
UIViewContentModeScaleAspectFit -> check if you can see the edges, even if position is incorrect
UIViewContentModeScaleAspectFill -> check for edge right side
benzoid
  • 56
  • 1
  • 6
2

The reason you got a right-side cut image is caused by this line

UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
                                            scale: 1.0
                                      orientation: UIImageOrientationLeft];

You made the image orientation to left, the context will thought the left-side is your top-side.And your size has a minus to the height value, so the result turns to the right-side is cut.

About the rotation, I added some code into your code.Hopes it is helpful.

- (UIImage *) createSnapshotOfView:(UIView *) view
{
    CGRect rect = [view bounds];
    rect.size.height = rect.size.height - 81.0f;
    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f);
    CGContextRef context = UIGraphicsGetCurrentContext();

    view.transform = CGAffineTransformMakeRotation(M_PI_2);
    [view.layer renderInContext:context];

    UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
                                                     scale: 1.0
                                               orientation: UIImageOrientationLeft];

    view.transform = CGAffineTransformMakeRotation(0);
    return finalImage;
}
Steven Jiang
  • 1,006
  • 9
  • 21
  • Unfortunately, it is still being cut off, even with the added lines. – Gergely Kovacs Mar 31 '14 at 18:48
  • Also, I doubt that is the line that causes the problem because when I comment it out, I still get the same cut-off results, only with a different orientation. – Gergely Kovacs Mar 31 '14 at 19:36
  • 1
    @GergelyKovacs Yes, you are right.The cut is caused by the resizable image.And I found a interesting thing.If you change the resize edgeInset to UIEdgeInsetsMake(10.0f, 10.0f, 5.0f, 10.0f),the resized image will turn to a table of the original image. And compare the resized image with the captured image, you will found that the cut is caused by the position of last image in the table.Maybe it could be some hint. – Steven Jiang Apr 01 '14 at 05:20
2
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:@"foo.png" atomically:YES];

for retina display, change the first line into this:

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
else
    UIGraphicsBeginImageContext(self.window.bounds.size);

adjust your size, may you get help..

Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
  • 2
    This is almost exactly what I did except that I used the size of the view not the window (which is what I need). Unfortunately, it is of absolutely no help. – Gergely Kovacs Apr 02 '14 at 17:48