I am setting the NavBar's background with this code which works great in Retina and non-Retina displays. There is a @2x and normal image. So, all good:
UINavigationBar.Appearance.SetBackgroundImage(
GetImage(ImageTheme.menubar), UIBarMetrics.Default);
Now, when I apply this ChangeHue()
transformation to the image to adjust its hue, on Retina displays the image is twice the size. Non-Retina displays are fine:
UINavigationBar.Appearance.SetBackgroundImage(
ChangeHue(GetImage(ImageTheme.menubar)), UIBarMetrics.Default);
...
UIImage ChangeHue(UIImage originalImage){
var hueAdjust = new CIHueAdjust() {
Image = CIImage.FromCGImage(originalImage.CGImage),
Angle = hue * (float)Math.PI / 180f // angles to radians
};
var output = hueAdjust.OutputImage;
var context = CIContext.FromOptions(null);
var cgimage = context.CreateCGImage(output, output.Extent);
var i = UIImage.FromImage(cgimage);
return i;
}
Here is the result in Non-Retina and Retina displays after the Hue is applied:
I never tried for CoreImage but, for CoreGraphics, you need to use
UIGraphics.BeginImageContextWithOptions
and specify0
for scaling (so it will be done automagically for both Retina and non-Retina displays).So the first thing I would try is to replace your:
with the following block:
UPDATE:
FromContext
is not available in iOS (it's OSX specific) so the above code won't work.Filed a bug with the MonoTouch team. Will post solution shortly.
Ignore those HACKs, and edit this line in your
ChangeHue
method:to do this instead:
This should return a
UIImage
object that is has the correct 'scale' information to be properly displayed in theUINavigationBar
.I've got three 'hacks' to suggest for now:
Hack #1
To force the extent to trim the image by replacing this line:
with this:
HOWEVER you 'lose' the Retina resolution on the adjusted image (it uses the @2x image as the source, but only displays the bottom-left quadrant of it after applying the filter, thanks to the image origin starting at the bottom-left).
Hack #2
Along the same lines, you can scale the image returned from the
ChangeHue
method so that it doesn't expand beyond the navigation bar:UNFORTUNATELY you 'lose' the Retina resolution again, but at least the image is displayed correctly (just downsampled to 320 wide).
Hack #3
You could save the filtered image to disk and then set the
UIAppearance
using the image file on 'disk'. The code would look like this:The benefit of this final hack is that the image looks correct (ie. Retina resolution is preserved).
I'm still looking for the "perfect" solution, but at least these ideas 'fix' your problem one-way-or-another...