Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 02-18-2009, 08:31 PM   #1 (permalink)
Registered Member
 
Join Date: Jan 2009
Posts: 21
Default Quartz: Transforming and cropping a UImage

It seems simple enough. I have a UIImageView which I apply an arbitrary CGAffineTransform to, but now I want to get a cropped portion of the transformed image.

Here is the code I'm currently using:
Code:
// Begin the drawing
UIGraphicsBeginImageContext(cropRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();

// Clear whole thing
CGContextClearRect(ctx, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));

// Transform the image (as the image view has been transformed)
CGContextConcatCTM(ctx, imageView.transform);

// Translate to compensate for the different positions of the image
CGContextTranslateCTM(ctx, -((imageView.bounds.size.width*0.5)-(cropRect.size.width*0.5)),
                             (imageView.bounds.size.height*0.5)-(cropRect.size.height*0.5));

// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, maskRect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

// Draw view into context
CGContextDrawImage(ctx, imageViewbounds, imageView.image.CGImage);

// Create the new UIImage from the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the drawing
UIGraphicsEndImageContext();
So far this works great, as long as my transform is limited to translations. If the transform involves any scaling or rotating, then the image resulting from the crop is at a different location than I intended. I've been struggling to get my head around this problem for ages now, so I would really appreciate any kind of input on the matter.

Thanks.
death_au is offline   Reply With Quote
Old 02-19-2009, 07:16 PM   #2 (permalink)
Registered Member
 
Join Date: Jan 2009
Posts: 21
Default

For anyone who is interested, I solved my problem. There were two main issues involved:
Firstly the fact that I was applying a transform from a large image to a much smaller image, meaning the scale values screwed up everything. I got around this by first transforming my original image and then cropping the result.
Secondly, transforms were all being applied from the top-left corner of the image, whereas the imageView's transform was applying from the center. So to work around that I just had to translate by (width/2, height/2), apply the transformation and then translate back.

Here's the new code:

Code:
CGRect rect = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);
// Begin the drawing
UIGraphicsBeginImageContext(imageView.image.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();

// Clear whole thing
CGContextClearRect(ctx, rect);

// Transform the image (as the image view has been transformed)
CGContextTranslateCTM(ctx, rect.size.width*0.5, rect.size.height*0.5);
CGContextConcatCTM(ctx, imageView.transform);
CGContextTranslateCTM(ctx, -rect.size.width*0.5, -rect.size.height*0.5);

// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

// Draw view into context
CGContextDrawImage(ctx, rect, imageView.image.CGImage);

// Create the new UIImage from the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the drawing
UIGraphicsEndImageContext();

// Begin the drawing (again)
UIGraphicsBeginImageContext(cropRect.size);
ctx = UIGraphicsGetCurrentContext();

// Clear whole thing
CGContextClearRect(ctx, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));

// Translate to compensate for the different positions of the image
CGContextTranslateCTM(ctx, -((newImage.size.width*0.5)-(cropRect.size.width*0.5)),
                             (newImage.size.height*0.5)-(cropRect.size.height*0.5));

// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, cropRect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

// Draw view into context
CGContextDrawImage(ctx, CGRectMake(0,0,newImage.size.width,newImage.size.height), newImage.CGImage);

// Create the new UIImage from the context
newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the drawing
UIGraphicsEndImageContext();
death_au is offline   Reply With Quote
Old 05-20-2009, 01:37 PM   #3 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 9
Send a message via Yahoo to nujohn
Default Thanks for the snippet...I made one minor adjustment

It was giving me problems (image ended up in the wrong location)when I move the image around i.e. translation. My image size was different from the view size and in my case that's the screen size (320X480) I noticed that if my image were exactly the same size as the view size then the existing code works perfectly otherwise there's the problem I described. Also I wasn't sure why it was doing a draw twice so I cut that out. Here are the results of my changes:

-(UIImage*) getCroppedImageFromViewUIView *)view imageUIImage *)image {
// Begin the drawing
CGRect rect = view.bounds;
UIGraphicsBeginImageContext(CGSizeMake(rect.size.w idth,rect.size.height));
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Clear whole thing
CGContextClearRect(ctx, rect);

// Transform the image (as the image view has been transformed)
CGContextTranslateCTM(ctx, rect.size.width*0.5, rect.size.height*0.5);
CGContextConcatCTM(ctx, view.transform);
CGContextTranslateCTM(ctx, -rect.size.width*0.5, -rect.size.height*0.5);

// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

// Draw view into context
CGContextDrawImage(ctx, rect, image.CGImage);

// Create the new UIImage from the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the drawing
UIGraphicsEndImageContext();
return newImage;
}


Again thanks for sharing.
nujohn is offline   Reply With Quote
Reply

Bookmarks

Tags
cgaffinetransform, crop, quartz, scale, transform

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 245
17 members and 228 guests
ADY, Alsahir, Dani77, Desert Diva, Duncan C, F_Bryant, Grinarn, HemiMG, Herbie, jansan, linkmx, M@realobjects, macquitzon216, prchn4christ, smethorst, spiderguy84
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,882
Threads: 89,228
Posts: 380,761
Top Poster: BrianSlick (7,129)
Welcome to our newest member, jansan
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 01:43 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0