Bug 11969 - Missing bindings for UIImage initWithCGImage:scale:orientation: and initWithCIImage
Summary: Missing bindings for UIImage initWithCGImage:scale:orientation: and initWithC...
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 6.3.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
URL:
Depends on:
Blocks:
 
Reported: 2013-04-25 14:44 UTC by Mikkel
Modified: 2013-04-26 06:01 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test case (142.44 KB, application/zip)
2013-04-26 06:01 UTC, Mikkel
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Mikkel 2013-04-25 14:44:33 UTC
The bindings for UIImage's initWithCGImage:scale:orientation: and initWithCIImage seems to be missing.

See Apple's documentation: http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIImage_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006890-CH3-SW37

The binding for initWithCIImage:scale:orientation: (UIImage.FromImage(ciimage, scale, orientation), added in iOS 6) is there, though, but I currently need iOS 5 support in an app I'm developing.

It turns out that the CIImage property of an UIImage can sometimes be null (in this case when an image is returned from an UIImagePickerController using the front camera where I want to "keep" it mirrored - AFAIK this is expected?*), which confused me a bit.
At first I tried using UIImage.FromImage(mypicture.CGImage, scale, orientation) - the missing binding, actually - which did compile (?) and gave me the UIImage I wanted IIRC, but when using the CGImage of the new UIImage, the properties weren't initialized (width and height were 0 for example). This took me down a dark path before looking at the bindings and class libraries.
As I found that the needed bindings were missing, I ended up creating a CIImage from mypicture.CGImage before using it, like this:

mypicture = UIImage.FromImage(CIImage.FromCGImage(mypicture.CGImage), scale, orientation);

But this isn't iOS 5 compatible, and could skip a step. The discovery also led me to the other missing binding (initWithCIImage).

Is there an easy way to extend the default bindings if something like this is missing?

Let me know if you need more information :)

Thanks,
Mikkel

* http://stackoverflow.com/questions/15651228/could-anyone-tell-me-why-uiimage-ciimage-is-null#15651358

System:

Xamarin Studio
Version 4.1.0 (build 45)
Installation UUID: 3b3e4592-bc84-4261-aace-85db6c7c9444
Runtime:
	Mono 3.0.10 ((no/eff4cb5)
	GTK 2.24.18
	GTK# (2.12.0.0)
	Package version: 300100000

Apple Developer Tools
Xcode 4.6.1 (2067)
Build 4H512

Xamarin.iOS
Version: 6.3.4.36 (Business Edition)
Hash: 9eb42f8
Branch: 
Build date: 2013-11-04 10:49:08-0400
Comment 1 Sebastien Pouliot 2013-04-25 15:12:25 UTC
You're right, `initWithCGImage:scale:orientation:` seems to be missing, I'll add it and give you a workaround.

OTOH `initWithCIImage:` is already part of UIImage and mapped to:

    public UIImage (CIImage ciImage)
Comment 2 Sebastien Pouliot 2013-04-25 15:14:49 UTC
hmm... wrong `initWithCGImage:scale:orientation:` is mapped to:

   public UIImage (CGImage cgImage, float scale, UIImageOrientation orientation)
Comment 3 Sebastien Pouliot 2013-04-25 15:21:36 UTC
> At first I tried using UIImage.FromImage(mypicture.CGImage, scale, orientation)

I think the confusion is that `init*` selectors are map to C# constructors while `image*` (static) selectors are mapped to static methods, e.g. From*
Comment 4 Mikkel 2013-04-25 16:13:38 UTC
Hmm, oh right!

But it was actually the `image*` (static) selectors I meant (the link is correct), which are missing, right?

Using the constructor is perfectly fine for me – I think I accidentally hid the constructors when I tried to add my own binding. Obviously, I had no idea what I was doing.

Should the compiler not have picked up the error in my first attempt?
Comment 5 Sebastien Pouliot 2013-04-25 16:27:05 UTC
yep, the link is correct - it why I saw it as missing the first time :-) then I looked at the source and used the `init*` from your description.

I'll add the missing selectors (below) for the next release
* imageWithCGImage:scale:orientation:
* imageWithCIImage:
* imageWithCIImage:scale:orientation:

As for the workaround you can use (the already existing) constructors.

> Should the compiler not have picked up the error in my first attempt?

No, the static method and the constructor are different and the C# compiler does not know anything about the selectors.
Comment 6 Sebastien Pouliot 2013-04-25 16:52:38 UTC
`imageWithCIImage:scale:orientation:` was already present but the 2 others are now added in master de8fe8ae1cf5a9d9e0e9ac71d8f0f2d80570d36f
Comment 7 Mikkel 2013-04-25 17:01:33 UTC
That was quick! :)

What I meant about the compiler picking up the error, was that a CGImage was used where a CIImage should've been used, i.e. UIImage.FromImage(someCGImage, scale, orientation) but only UIImage.FromImage(someCIImage, scale, orientation) is actually supported. Should it not tell me "Stop with the CGImage already!" as the object types are different? I guess the answer is that they both implement INativeObject (only *.Handle is used as far as I can tell)?
Comment 8 Sebastien Pouliot 2013-04-25 17:07:19 UTC
Not sure I understand. The compiler should have reported an error - but it might not be able to suggest the best alternative.

If it did not report an error can you show us the code you used ?
Comment 9 Mikkel 2013-04-25 17:19:35 UTC
This is what I have in my UIImagePickerControllerDelegate:

public override async void FinishedPickingImage(UIImagePickerController picker, UIImage image, NSDictionary editingInfo) {

	if (picker.SourceType == UIImagePickerControllerSourceType.Camera && picker.CameraDevice == UIImagePickerControllerCameraDevice.Front) {
		image = UIImage.FromImage(image.CGImage, image.CurrentScale, UIImageOrientation.LeftMirrored); // <-- Here. CGImage used, method signature says CIImage.
		//new UIImage(image.CGImage, image.CurrentScale, UIImageOrientation.LeftMirrored);
	}

	// Dismiss controller and display/process image
}

Let me know if you want a complete test case.
Comment 10 Sebastien Pouliot 2013-04-25 17:24:17 UTC
Did that compile ? if not what was the error message ?

note that `FromImage (CIImage ciImage, float scale, UIImageOrientation orientation)` already exists, so it's normal if the compiler reported an error between `CGImage` and `CIImage` (i.e. it tried to be helpful).
Comment 11 Mikkel 2013-04-25 17:34:41 UTC
It compiles, no error. It even runs, and you get a displaying UIImage (when added to UIImageView; luck?), but when you access CGImage of that, it just gets weird (I'm processing the raw image before saving it to the camera roll and width, height etc. are 0/null).
Comment 12 Sebastien Pouliot 2013-04-25 17:44:50 UTC
I'll check, there might be some implicit type conversion.
Comment 13 Sebastien Pouliot 2013-04-25 19:18:47 UTC
Yes, that was it.

		public static implicit operator CIImage (CGImage image)
		{
			return FromCGImage (image);
		}

Sadly "implicit" means it's not very visible (and harder to debug).
Comment 14 Mikkel 2013-04-25 19:36:33 UTC
Hmm. If I understand correctly, that is the same as explicitly calling CIImage.FromCGImage(image.CGImage)?

If yes, then how come UIImage.FromImage(CIImage.FromCGImage(image.CGImage), image.CurrentScale, UIImageOrientation.LeftMirrored) worked as my workaround, but UIImage.FromImage(image.CGImage, image.CurrentScale, UIImageOrientation.LeftMirrored) did not? Well, it partially did, but the resulting CGImage was "empty".
Comment 15 Sebastien Pouliot 2013-04-25 19:55:07 UTC
Not sure. It looks like it should have been identical.

Can you attach a self-contained test case ? I'll examine it with the (unfixed) 6.3.x version.
Comment 16 Mikkel 2013-04-26 06:01:10 UTC
Created attachment 3879 [details]
Test case

Actually, they do behave identically. Not sure there's anything to else report then, other than they both behave faulty (resulting CGImage isn't initialized correctly).

Anyway, here's the test case.