Pages

Saturday, July 18, 2009

iPhone OS - drawing image and stupid thing from Apple

Just because of a piece of code, a team in Singapore gave up an iPhone project. Actually, they do not know how to play tricks with Apple. ... and I also faced to a similar situation when I play as a technical consultant to fix this stupid bug.

The need of client is: drawing some effects on an image and save it as a photo in Photo library. So, if anyone has experience with graphic programming may think this is a very simple task. However, that's not true.

Many forums and online articles just shows us a real problem on iPhone graphics programming: the root position (0,0) of the image to draw is on the bottom left and the root position of the graphic context is on the top-left corner. So, we must do some transformation to keep the image in the correct position.

And the simple code to fix this issue is as below:
int width = image.size.width;
int height = image.size.height;
CGSize size = CGSizeMake(width, height);
//create the rect zone that we draw from the image
CGRect imageRect = CGRectMake(0, 0, width, height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
//Save current status of graphics context
CGContextSaveGState(context);
//Do stupid stuff to draw the image correctly
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, imageRect, image.CGImage);
//After drawing the image, roll back all transformation by restoring the 
//old context
CGContextRestoreGState(context);
DO OTHER EFFECTS HERE
//get the image from the graphic context
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
//commit all drawing effects
UIGraphicsEndImageContext();
Above piece of code is thing that you see in all online technical articles related to iPhone graphic programming. Anyway, that's not enough. If you deploy that piece of code into iPhone OS 3.0 on real device, it does not run correctly: saved images are always scaled in horizontal and inverse. However, there is a very strange thing: this code is run perfectly on simulator for iPhone OS 3.0.

After 1 day to detect the problem, I found that: when an image is shown on iPhone, it has a direction. Direction is included: UP, DOWN, LEFT, RIGHT. So, we must to fix the code to satisfy when they're in those cases. The above code is run correctly in case image direction is UP.

Here is the fixed version:
int width = image.size.width;
int height = image.size.height;
CGSize size = CGSizeMake(width, height);
//create the rect zone that we draw from the image
CGRect imageRect;

if(image.imageOrientation==UIImageOrientationUp 
|| image.imageOrientation==UIImageOrientationDown) 
{
    imageRect = CGRectMake(0, 0, width, height); 
}
else 
{
    imageRect = CGRectMake(0, 0, height, width); 
}

UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
//Save current status of graphics context
CGContextSaveGState(context);

//Do stupid stuff to draw the image correctly
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);

if(image.imageOrientation==UIImageOrientationLeft) 
{
    CGContextRotateCTM(context, M_PI / 2);
    CGContextTranslateCTM(context, 0, -width);
}
else if(image.imageOrientation==UIImageOrientationRight) 
{
    CGContextRotateCTM(context, - M_PI / 2);
    CGContextTranslateCTM(context, -height, 0);
} 
else if(image.imageOrientation==UIImageOrientationUp) 
{

//DO NOTHING

}
else if(image.imageOrientation==UIImageOrientationDown) 
{
    CGContextTranslateCTM(context, width, height);
    CGContextRotateCTM(context, M_PI);
}

CGContextDrawImage(context, imageRect, image.CGImage);
//After drawing the image, roll back all transformation by restoring the 
//old context
CGContextRestoreGState(context);
DO OTHER EFFECTS HERE
//get the image from the graphic context
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
//commit all drawing effects
UIGraphicsEndImageContext();
After fixing this bug, I can say only one thing: why Apple always do something stupid and make developer do the stupid thing?

6 comments:

Anonymous said...

I just had this problem also. I can accept that someone at Apple like it like that and they want to make it easy to render to PDF and PostScript and whatever, but it would be nice if there were just a flag or a pair of functions like CGContextSetOriginToTopLeft and CGContextSetOriginToBottomLeft.

Usman Aleem said...

Thankz dude. really work for me.

Pannag said...

dude.. thanks a lot! Very impressive article.
What is the difference between UIGraphicsBeginImageContext() and CGBitmapContextCreate() ?? For some, the first one is used and for some, the second one is used. Like, can you get a B/W image or draw a text on top of the image by using the UIGraphicsContext?

Anonymous said...

it works. Thank you!

Anonymous said...

Thanks for this! Keep in mind that Apple is using technology invented in the eighties from NeXT (Google it). Although it gets the job done, it wastes much time for nothing. THE EIGHTIES ARE OVER, STEVE!!

Anonymous said...

Fantastic goods from you, man. I've understand your stuff previous to and you are just extremely great. I really like what you've
acquired here, certainly like what you're saying and the way in which you say it. You make it enjoyable and you still take care of to keep it sensible. I cant wait to read far more from you. This is actually a tremendous site.

Feel free to surf to my web blog :: free p orn pictures