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?
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
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
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.
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.
@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.