picture rotation by angle

Hi,

I’ve been looking for simple method to rotate a picture object by angle without using 3rd party plugins.
Since I am developing only under Mac OS X I checked the MacOS Lib first & the Mac Developer page for examples and made up
a method to rotate a picture object with a given angle which I want to share in case somebody else may need it too.

I currently know 3 ways to rotate a picture:
1.) MacOS - make a canvas and set your picture as backdrop and use:
declare sub rotateByAngle lib Cocoa selector “rotateByAngle:” (obj_id as Ptr, angle as Single)
2.) MacOS - see my method below
3.) ALL - use Xojo built in PixmapShape class

I checked+compared the performance for Option 2 & 3, resulting in an overall performance of 0.27ms for 2 and about 4.5ms for 3
with 100 iterations.

Function Rotate( picObj as Picture, angle as single) as Picture
  const M_PI = 3.14159265
  const kCGImageAlphaPremultipliedFirst = 2
  
  soft declare sub CFRelease lib CarbonLib ( obj as ptr )
  soft declare sub CGContextTranslateCTM lib CarbonLib (context as Ptr, tx as Single, ty as Single)
  soft declare sub CGContextRotateCTM lib CarbonLib (context as Ptr, angle as Single)
  soft Declare Sub CGContextDrawImage Lib CarbonLib (context As Ptr, rect As CGRect, image As Ptr)
  soft declare function CGBitmapContextCreateImage lib CarbonLib (context as Ptr) as Ptr
  soft declare function CGBitmapContextCreate lib CarbonLib (data as Ptr, width as Integer, height as Integer, bitsPerComponent as Integer, bytesPerRow as Integer, colorspace as Ptr, bitmap as UInt32) as Ptr
  soft declare function CGColorSpaceCreateWithName lib CarbonLib (name as CFStringRef) as Ptr
  soft declare sub CGContextClearRect lib CarbonLib (context as Ptr, rect as CGRect)
  
  dim w as integer = picObj.Width
  dim h as integer = picObj.Height
  
  dim p as Picture
  // pass nil & 0 to have OS calculate the buffer itself
  dim cntx as Ptr = CGBitmapContextCreate( nil, w, h, 8, 0, CGColorspaceCreateWithName("kCGColorSpaceGenericRGB"), kCGImageAlphaPremultipliedFirst )
  if cntx <> nil then
    CGContextTranslateCTM cntx, w/2.0, h/2.0
    CGContextRotateCTM cntx, angle /180.0 * M_PI
    CGContextTranslateCTM cntx, -(w/2.0), -(h/2.0)
    
    dim cgImageRef as Ptr = picObj.CopyOSHandle(Picture.HandleType.MacCGImage)
    if cgImageRef <> nil then
      dim r as CGRect
      r.width = w
      r.height = h
      
      CGContextDrawImage( cntx, r, cgImageRef )
      CFRelease( cgImageRef )
      
      p = New Picture ( w, h )
      dim newCntxRef as Ptr = CGBitmapContextCreateImage( cntx )
      CGContextDrawImage(  Ptr( p.Graphics.Handle( Graphics.HandleTypeCGContextRef ) ), r, newCntxRef )
      CFRelease ( newCntxRef )
    end if
    CFRelease( cntx )
  end if
  return p

Please comment/discuss or let me know your thoughts. Maybe someone else has a different solution with less overhead or so.
If you need more comments what the code, please let me know.

Pixmapshape would have been my recommendation.
Is your criteria ‘how do I rotate a picture’ or ‘how do I rotate it really fast’?
How fast is fast enough?

Of course the speed is negligible in real world/office app unless you got some more animation running
so you can go for Pixmapshape for sure as it ensures being cross platform.

I’ve written a little project under MacOS with a bouncing, rotating 2D shape and compared both methods.
The animation gets updated every 25ms so in this case in matters a bit but I assume, if you’re really want to make animation under MacOS you’d probably use openGL stuff.

Well, I am just so excited that it works and yes maybe it’s a bit fooling around.

May actual goal was to have a fast and memory friendly routine but the latter one I couldn’t I archieve
since CopyOSHandle and new picture object. I am wondering if you can manage it with the context of the picObj Handle
you pass and return it again so that you actually use only one object and a buffer.

PS: You don’t know what pixmapshape does internally. Less code or 1-2 lines of code doesn’t means less overhead in compiled code.

I think the native graphics routines of Xojo can be pushed to respectable levels, but OpenGL definitely provides ways to reach very high frame-rates.

Maybe this Xojo tutorial on 2D sprites using OpenGL might help. I’ve been able to render hundreds of sprites simultaneously with good results.

www.xojo3d.com/tut015.php

OpenGL takes a bit more effort to begin with, but once your basic framework is set up in OpenGL, you reap the rewards of your efforts.

Thanks Alwyn. Will definitely looking into.

If you need smooth animations… you need to maintain at least 24frames per second… and this CAN be done without OpenGL for somethings…

I wrote a 3D maze runner with textured walls (ala Wolfenstien) and got between 16 and 48 fps depending on the visible content