Capture Image Orientation

Hi

I’m trying to take a photo on the iPhone. The problem I’m having with this is the orientation of the photo will only be upright if you hold the phone only one of the landscape angles.

Does anyone know how I can keep the image in the correct orientation no matter which way the phone is positioned?

Secondly, when using the Edit option, does anyone know if changing the crop shape from square to 3:2, etc?

Thanks very much for any help

Chris

If you have iOSKit in your project, navigate to iOSKit > Extensions.

Paste this method:

Public Function ScalePicture(extends pic as Picture, scaleFactor as Double, mode as InterpolationQuality = InterpolationQuality.Default) As Picture
  
  
  dim UIImageRef as ptr = pic.CopyOSHandle(Picture.HandleType.iOSUIImage)
  
  declare function size lib UIKitLib selector "size" (obj_id as ptr) as CGSize64
  dim sz as CGSize64 = size(UIImageRef)
  dim newSize as CGSize64
  
  
  newSize.w = sz.w * scaleFactor
  newSize.h = sz.h * scaleFactor
  
  dim r as CGRect64
  
  
  r.origin.x = 0
  r.origin.y = 0
  r.rsize.w = newSize.w
  r.rsize.h = newSize.h
  
  
  declare sub UIGraphicsBeginImageContext lib UIKitLib (mSize as CGSize64)
  
  UIGraphicsBeginImageContext(newSize)
  
  'declare sub UIGraphicsBeginImageContextWithOptions lib UIKitLib (mSize as CGSize64, opaque as boolean, scale as double)
  'UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0) //0.0 uses current screen scale
  
  declare function UIGraphicsGetCurrentContext lib UIKitLib () as ptr
  dim CGContextRef as ptr = UIGraphicsGetCurrentContext
  
  declare sub CGContextSetInterpolationQuality lib CoreGraphicsLib (context as ptr, quality as InterpolationQuality)
  CGContextSetInterpolationQuality(CGContextRef, mode)
  
  
  declare sub drawInRect lib UIKitLib selector "drawInRect:" (obj_id as ptr, rect as CGRect64)
  
  
  drawInRect(UIImageRef,r)
  
  declare function UIGraphicsGetImageFromCurrentImageContext lib UIKitLib () as ptr
  dim newUIImage as Ptr = UIGraphicsGetImageFromCurrentImageContext
  
  declare sub UIGraphicsEndImageContext lib UIKitLib ()
  UIGraphicsEndImageContext
  
  Return Picture.FromHandle(newUIImage)
End Function

In the MobileImagePicker.Selected event call this code:

pic = pic.ScalePicture(1.0) //Magically keeps the orientation of the photo

Thanks very much Jeremie :smiley: I was looking forward to the magic, but, alas I’m still crooked :smiley:

I’ll simplify the project first 'cause I’m sure it’s something I’m doing wrong! … and update the thread

No it isn’t you doing anything wrong.
There are various stackoverflow posts about this issue.

Now you know how to fix it :slight_smile:

I think what Chris needs is a way to force the camera to always open in Portrait mode, not something that modifies the image after the fact.

It doesn’t really modify the image, it just makes it appear in the correct orientation.

Thanks Tim - Not necessarily actually. I want to modify anyway to reduce the size…

Also, I’d like the option of the photo being landscape or portrait

Then I have no idea what you need, sorry to confuse!

No at all Tim and thanks for taking the time

Hi Jeremie,

Same problem with the image not following the orientation of the camera when I tried it on a “clean” version of iOS_Kit. I will say though, I’m using the ImagePicker rather than Jason’s Extension.Camera as it’s API2.0 savvy.

I can’t imagine this isn’t something a lot of people would be doing so I must be doing something wrong still :roll_eyes:

Though it’s not ideal, is anyone aware of a method of rotating the photo afterwards?

Thanks

I use Einhugur plugins to rotate Pictures.

Cheers David. I’ll check it out. Thanks for taking the time to reply

I am not sure that will work
-sometimes the pictures won’t be rotated
-sometimes they will
-sometimes they will be rotated by keeping the original pixel size but not orientation (pixels will appear wider on the height and narrower on the width)

There’s an issue with the built-in control in that the Xojo Picture class knows nothing about orientation but the underlying NSImage kinda requires it. So when the event fires, the NSImage is converted to a Picture and all of the metadata is stripped away. Unfortunately the ptr to the original data is also deleted.

I won’t say that it’s trivial for Xojo to fix, lord knows I tried on several occasions, but a feature request could be made to add orientation info to the Picture class as I suspect this will also be a problem when Android finally ships.

Thanks Greg. I actually logged it as a bug yesterday ( #68933) Should I raise/change this to a feature request? It seems a bug to me.

Thanks again

There’s already a bug report (what I worked on when I was there) but I do think a feature request is more appropriate. As I said, having the orientation available on Picture and a ptr to the underlying image would be very helpful.

:ok_hand: Thanks Greg

@Chris_O_Brien this has been an issue for a number of years with the Xojo Picture not containing any orientation data. As a workaround, for some time I have used the UIKit.UIImagePickerController from iOSKit. To use it, first create a MobileScreen property of this type, eg I’ve called it PicturePickerController, and then launch it like this:

// Remove current handler
If PicturePickerController <> Nil Then
  RemoveHandler PicturePickerController.PictureTaken, AddressOf HandlePictureTaken
End If

// Create a new controller with handler
PicturePickerController = New UIKit.UIImagePickerController
PicturePickerController.sourceType = UIKit.UIImagePickerController.Source.Camera
AddHandler PicturePickerController.PictureTaken, AddressOf HandlePictureTaken

// Show
Try
  PicturePickerController.PresentInView(Self)
Catch e As UnsupportedOperationException
  // Camera not available so handle this your way
End Try

The HandlePictureTaken method looks like this in its simplest form:

Private Sub HandlePictureTaken(sender as UIKit.UIImagePickerController)
  // Remove the handler
  RemoveHandler PicturePickerController.PictureTaken, WeakAddressOf HandlePictureTaken
  
  If sender.originalImage <> Nil Then
    // Copy into a new Picture so we can do something with it
    Var pic As New Picture(sender.originalImage.Width, sender.originalImage.Height)
    pic.Graphics.DrawPicture(sender.originalImage, 0, 0)
    
    // Remove the controller
    PicturePickerController = Nil
  End If
End Sub

I did modify parts of iOSKit to return Pictures instead of the original iOSImage so you might have to change a couple of lines in iOSKit for this to run if iOSKit hasn’t been updated. It looks as though this just involved changing iOSImage.FromHandle to Picture.FromHandle in the HandleDidFinishPicking method and the originalImage and editedImage properties from iOSImage to Picture.