Some favorite site feeds aggregated locally: iPhone Development RSS   Adobe Labs RSS   Macrumors RSS

Wednesday, August 5, 2009

iPhone: Image interpolation on the hack

Wednesday, August 5, 2009    1 Comments

I am currently making an analog clock for the iPhone just to play with some things that come second nature to me in Actionscript 3. For the most part it's been straightforward. I ran into a snag and needed a solution.

I have three hands for this analog clock: hour, minute and second hands. They of course need to rotate to their appropriate values. However, I am using UIImageView with PNGs with transparency to do this. There are better ways to do this I'm sure, but I wanted to get this to work.

Setting it up in IB is a nightmare, so I'll be changing the way I do this for sure, but I learned a little something along the way. Using an NSTimer firing every second, I update my clock. Tick, tick, tick motions (no animation). The hands look terrible and blocky because by default no interpolation (aliasing) is happening. In trying to get rid of that, I managed to introduce some animation as well for free.

The original method called from my timer:
#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)
- (void) showActivity {
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit| NSMinuteCalendarUnit |NSSecondCalendarUnit;
NSDate *date = [NSDate date];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];
int h = [comps hour];
int m = [comps minute];
int s = [comps second];

CGAffineTransform cgaRotateHr = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(h * 30));
CGAffineTransform cgaRotateMin = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(m * 6));
CGAffineTransform cgaRotateSec = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(s * 6));

[hrHand setTransform:cgaRotateHr];
[minHand setTransform:cgaRotateMin];
[secondHand setTransform:cgaRotateSec];

NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setTimeStyle:NSDateFormatterMediumStyle];
[clockLabel setText:[formatter stringFromDate:date]];
}
Okay, that works, but I get horrid edges on my PNGs for the hands. Introducing these few lines before the setTransforms on the hands forces interpolation (default) and animation:
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath: @"transform"];
[[secondHand layer]addAnimation:animation forKey:@"transform"];
[[hrHand layer]addAnimation:animation forKey:@"transform"];
[[minHand layer]addAnimation:animation forKey:@"transform"];
Now the edges are prettier and I get animation of the hands when they change positions. It's on to looking at OpenGL and other things for something like this.

Labels: , ,