I wrote a multi-touch based photo tweak program. With UIImageView showing a photo, the transform value is set according to the user touch, to expand/shrink the image. Here's some code that handle the multi-touch.
-(void) viewPanned:(UIPanGestureRecognizer *)g
{
CGPoint translate = [g translationInView:imageView];
CGAffineTransform nt = CGAffineTransformMake(1.0, 0, 0, 1.0, translate.x, translate.y ) ;
imageView.transform = CGAffineTransformConcat( transform, nt ) ;
if( g.state == UIGestureRecognizerStateEnded ) {
transform = imageView.transform ;
}
}
-(void) viewPinched:(UIPinchGestureRecognizer *)g
{
switch (g.state) {
case UIGestureRecognizerStateBegan:
{
startScale = g.scale ;
}
break;
case UIGestureRecognizerStateChanged:
{
CGFloat change = g.scale ;
switch( currentMode ) {
case 0:
imageView.transform = CGAffineTransformScale( transform, change, change ) ;
break ;
case 1:
imageView.transform = CGAffineTransformScale( transform, change, 1.0 ) ;
break ;
case 2:
imageView.transform = CGAffineTransformScale( transform, 1.0, change ) ;
break ;
}
}
break ;
case UIGestureRecognizerStateEnded:
{
transform = imageView.transform ;
}
default:
break;
}
}
-(void) viewRotated:(UIRotationGestureRecognizer *)g
{
CGFloat rotation = g.rotation ;
imageView.transform = CGAffineTransformRotate(transform, rotation) ;
if( g.state == UIGestureRecognizerStateEnded ) {
transform = imageView.transform ;
}
}
So, the program maintains the original photo and change the transform value to show the tweak. At the end, I got the original image and the transform value as the result. As far as using UIImageView, I can reproduce the tweaked image, by setting .image as the original photo, and .transform as the result of tweak. Now, to redraw the tweaked image to a single image, I try to use CGContextConcatCTM to apply the transform to the drawing image.
-(UIImage *)shrinkImage:(UIImage *)img size:(CGSize)size transform:(CGAffineTransform)transform
{
UIImage *sImage ;
CGSize trSize = CGSizeApplyAffineTransform( size, transform ) ;
UIGraphicsBeginImageContext(trSize) ;
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform tr = CGAffineTransformIdentity;
//tr = CGAffineTransformTranslate(tr, trSize.width/2, trSize.height/2); // only works on rotate
tr = CGAffineTransformConcat(tr , transform);
//tr = CGAffineTransformScale(tr, 1.0, -1.0);
CGContextConcatCTM(context, tr);
CGRect rect ;
rect.origin = CGPointZero ;
rect.size = size ;
[img drawInRect:rect] ;
//CGContextDrawImage(context, rect, img.CGImage); // no difference
sImage = UIGraphicsGetImageFromCurrentImageContext() ;
UIGraphicsEndImageContext() ;
return sImage ;
}
Then I got a wrong image, most of the case the result is displaced from the image I expected. (What I could get with UIImageView with transform) I searched this suite and other, and found some solutions for rotation, but there's no generic solution for any type of transform. Some mechanism only works for rotation, some works for expansion, etc. It seems that the axis difference between UIImageView transform and CGContextConcatCTM is causing the problem. But I could not find any information about that. Logically Core graphics and UIView origin should be the same.
Can anyone tell me what is the generic solution?