iOS Image Rotation problem

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Hi Guys,
I got an image rotation function working a while back,
and recently put it to the test in an app, and have an interesting problem.

The image I'm testing is this:


Well not really, but it might as well be.
The image is stretched to be larger than the screen, and the origin I'm
rotating about will always be inside the blue box,
so I can rotate the image at any angle, and don't have to worry about
what part of the black surrounding gets chopped off since the background
is also plain black.

Every time the image is rotated, it appears there is some skew in the angle
the result can appear to be about 5 degrees off at worst,
depending on the angle of rotation. Also, depending on the angle, the result
image can be distorted into a slight rhombus, and not end up perfectly square.

I am printing the image with the exact same bounds that I started with 1024x1024.
Here is the code (image rotation) :

Code:
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bmContext = CGBitmapContextCreate(NULL,1024,1024,8,0,colorSpace,kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    CGContextTranslateCTM(bmContext,+originx,+originy);
    CGContextRotateCTM(bmContext, angle);
    CGContextTranslateCTM(bmContext,-originx,-originy);
    CGContextDrawImage(bmContext, CGRectMake(0,0,1024,1024),imgRef);
    
    rotatedImage = CGBitmapContextCreateImage(bmContext);
    CFRelease(bmContext);
    
    return rotatedImage;
}
and the part that deals with finding the origin, and drawing to screen:

Code:
   	// these floats are already loaded with the values I was
	// already using to print the image without rotation
        // they are current screen coordinates
    tscreenx // top left of image
    tscreeny // 
    bscreenx // and bottom right of image
    bscreeny //
    screenx  // screen coords for image centre
    screeny  //
        
    pixelvalx = 1024.0 / (bscreenx-tscreenx); // calc how many screen pixels (coordinate value) that one pixel
    pixelvaly = 1024.0 / (bscreeny-tscreeny); // of the image is currently worth while printed stretched
        
    originx = 512.0 + ((160-screenx) * pixelvalx); // find origin using image centre
    originy = 512.0 + ((screeny-centery) * pixelvaly);
        
    //originx = (160-tscreenx) * pixelvalx; // or find origin using image corners
    //originy = (bscreeny-centery) * pixelvaly;
        
    CGImageRef imageRef = [self CGImageRotatedByAngle:[boxImage CGImage] angle:(360-rotation)/57.295791];
    rotImage = [UIImage imageWithCGImage: imageRef];
        
    CGRect boximageRect = CGRectMake(tscreenx, tscreeny, bscreenx-tscreenx, bscreeny-tscreeny);
    [rotImage drawInRect:boximageRect];
    CGImageRelease(imageRef);
Everything is fine (even if I needlessly use the image rotation function)
if the angle I'm rotating is zero. It also appears the origin always lines up correctly.

Any ideas on what's happening?
Thanks, Art.
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Hi Guys,
I got an image rotation function working a while back,
and recently put it to the test in an app, and have an interesting problem.

The image I'm testing is this:
[url=http://img.photobucket.com/albums/v186/ArtArt/box_zpsd3d58c37.png]Image[/URL]

Well not really, but it might as well be.
The image is stretched to be larger than the screen, and the origin I'm
rotating about will always be inside the blue box,
so I can rotate the image at any angle, and don't have to worry about
what part of the black surrounding gets chopped off since the background
is also plain black.

Every time the image is rotated, it appears there is some skew in the angle
the result can appear to be about 5 degrees off at worst,
depending on the angle of rotation. Also, depending on the angle, the result
image can be distorted into a slight rhombus, and not end up perfectly square.

I am printing the image with the exact same bounds that I started with 1024x1024.
Here is the code (image rotation) :

Code:
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bmContext = CGBitmapContextCreate(NULL,1024,1024,8,0,colorSpace,kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    CGContextTranslateCTM(bmContext,+originx,+originy);
    CGContextRotateCTM(bmContext, angle);
    CGContextTranslateCTM(bmContext,-originx,-originy);
    CGContextDrawImage(bmContext, CGRectMake(0,0,1024,1024),imgRef);
    
    rotatedImage = CGBitmapContextCreateImage(bmContext);
    CFRelease(bmContext);
    
    return rotatedImage;
}
and the part that deals with finding the origin, and drawing to screen:

Code:
   	// these floats are already loaded with the values I was
	// already using to print the image without rotation
        // they are current screen coordinates
    tscreenx // top left of image
    tscreeny // 
    bscreenx // and bottom right of image
    bscreeny //
    screenx  // screen coords for image centre
    screeny  //
        
    pixelvalx = 1024.0 / (bscreenx-tscreenx); // calc how many screen pixels (coordinate value) that one pixel
    pixelvaly = 1024.0 / (bscreeny-tscreeny); // of the image is currently worth while printed stretched
        
    originx = 512.0 + ((160-screenx) * pixelvalx); // find origin using image centre
    originy = 512.0 + ((screeny-centery) * pixelvaly);
        
    //originx = (160-tscreenx) * pixelvalx; // or find origin using image corners
    //originy = (bscreeny-centery) * pixelvaly;
        
    CGImageRef imageRef = [self CGImageRotatedByAngle:[boxImage CGImage] angle:(360-rotation)/57.295791];
    rotImage = [UIImage imageWithCGImage: imageRef];
        
    CGRect boximageRect = CGRectMake(tscreenx, tscreeny, bscreenx-tscreenx, bscreeny-tscreeny);
    [rotImage drawInRect:boximageRect];
    CGImageRelease(imageRef);
Everything is fine (even if I needlessly use the image rotation function)
if the angle I'm rotating is zero. It also appears the origin always lines up correctly.

Any ideas on what's happening?
Thanks, Art.
Why are you doing this the hard way?

You should not be using Core Image to render a rotated image. You should set the transform on a UIView or CALayer and let the graphics hardware render it for you. It's at least an order of magnitude faster, cleaner, and easier to support.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Why are you doing this the hard way?

You should not be using Core Image to render a rotated image. You should set the transform on a UIView or CALayer and let the graphics hardware render it for you. It's at least an order of magnitude faster, cleaner, and easier to support.
I'm open to ideas, but does that necessarily solve the problem?

The rotation is a sample I found on the net,
I just had to set the origin.
It also contained code to rotate and resize a rectangle,
but I assume that calculated the size for a new rectangle only
if you care about the corners being clipped.

Then it was going crazy until I found out the point of origin is bottom left.
https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_affine/dq_affine.html#//apple_ref/doc/uid/TP30001066-CH204-TPXREF101
It is the same thing they are showing me on their site.

Not it's close to correct, even if there's a better way,
the rotated box should always stay square, and doesn't.
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
I'm open to ideas, but does that necessarily solve the problem?

The rotation is a sample I found on the net,
I just had to set the origin.
It also contained code to rotate and resize a rectangle,
but I assume that calculated the size for a new rectangle only
if you care about the corners being clipped.

Then it was going crazy until I found out the point of origin is bottom left.
https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_affine/dq_affine.html#//apple_ref/doc/uid/TP30001066-CH204-TPXREF101
It is the same thing they are showing me on their site.

Not it's close to correct, even if there's a better way,
the rotated box should always stay square, and doesn't.

What are you trying to do? Create a rotated version of an image that you can save, or create an animation of an image rotating?
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
What are you trying to do? Create a rotated version of an image that you can save, or create an animation of an image rotating?
For an animation, like rotating a single map tile image to see how it works.
This box is a program of it's own though, going crazy before I figured out the orientation was bottom left.

On another platform the rotation code was pretty much the same.
I made a screen full of cogs of relative speeds and sizes with alpha around
them so they could all engage each other (wasted a lot of time on it).
If I were doing this now, the circular cogs would become slightly oblique,
predictably at it's worst at 90 degree increments beginning at 45 degrees.