views:

62

answers:

1

I have a UIImageView within a UIScrollView which I have enabled the user to perform any number of flip and rotation operations on. I have this all working which allows the user to zoom, pan, flip and rotate. Now I want to be able to save the final image out to a png.

however it is doing my head in trying to work this out...

I have seen quite a few other posts similar to this but most only require applying a single transform such as a rotation eg http://stackoverflow.com/questions/2856556/creating-a-uiimage-from-a-rotated-uiimageview

I would like to apply any transform that the user has "created" which will be a series of flip and rotations concatenated togethers

As the user is applying various rotations, flips etc, I store the concatenated transform using CGAffineTransformConcat. For example when they rotate I do:

CGAffineTransform newTransform = CGAffineTransformMakeRotation(angle);
self.theFullTransform = CGAffineTransformConcat(self.theFullTransform, newTransform);
self.fullPhotoImageView.transform = self.theFullTransform;

The following method is the best I have gotten so far for creating a UIImage with the full transform however the image is always translated in the wrong place. Eg the image is "offset". Which my guess is either related to using the wrong bounds being set in in CGAffineTransformTranslate or CGContextDrawImage.

Does anyone have any ideas? This seems a lot harder that I thought it should be...

- (UIImage *) translateImageFromImageView: (UIImageView *) imageView withTransform:(CGAffineTransform) aTransform
{
    UIImage *rotatedImage;

    // Get image width, height of the bounding rectangle
    CGRect boundingRect = CGRectApplyAffineTransform(imageView.bounds, aTransform);

    // Create a graphics context the size of the bounding rectangle
    UIGraphicsBeginImageContext(boundingRect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGAffineTransform transform = CGAffineTransformIdentity;

    //I think this translaton is the problem?

    transform = CGAffineTransformTranslate(transform, boundingRect.size.width/2, boundingRect.size.height/2);
    transform = CGAffineTransformScale(transform, 1.0, -1.0);
    transform = CGAffineTransformConcat(transform, aTransform);

    CGContextConcatCTM(context, transform);

    // Draw the image into the context

    // or the boundingRect is incorrect here?

    CGContextDrawImage(context, boundingRect, imageView.image.CGImage);

    // Get an image from the context
    rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];

    // Clean up
    UIGraphicsEndImageContext();
    return rotatedImage;
}
A: 

Is the offset predictable, like always half the image, or does it depend on aTransform?

struct CGAffineTransform {
  CGFloat a, b, c, d;
  CGFloat tx, ty;
};

If the latter, set tx and ty to zero in aTransform before using it.

drawnonward
thanks but it depends on the transform. In the end I added an extra UIView enclosing the UIImageView and used the renderInContext:UIGraphicsGetCurrentContext(), then cropped it.
joneswah
Write up what you did as an answer and mark it as accepted.
drawnonward