[英]MonoTouch: Doubling Appearance Image size when Hue adjusted on Retina display
我使用此代碼設置NavBar的背景,該代碼在Retina和非Retina顯示器上都很好用。 有一個@ 2x和正常圖像。 因此,一切都很好:
UINavigationBar.Appearance.SetBackgroundImage(
GetImage(ImageTheme.menubar), UIBarMetrics.Default);
現在,當我將ChangeHue()
轉換應用於圖像以調整其色調時,在Retina上顯示圖像的大小是其兩倍。 非視網膜顯示器很好:
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;
}
應用色相后,這是“非視網膜”和“視網膜”顯示的結果:
忽略這些HACK,然后在ChangeHue
方法中編輯以下行:
var i = UIImage.FromImage(cgimage);
改為這樣做:
float scale = 1f;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector ("scale"))) {
scale = UIScreen.MainScreen.Scale; // will be 2.0 for Retina
}
var i = new UIImage(cgimage, scale, UIImageOrientation.Up);
這應該返回一個UIImage
對象, UIImage
對象具有正確的“比例”信息,可以正確顯示在UINavigationBar
。
我從未嘗試過使用CoreImage,但是對於CoreGraphics,您需要使用UIGraphics.BeginImageContextWithOptions
並指定0
進行縮放(因此它將自動對Retina和非Retina顯示器進行處理)。
因此,我要嘗試的第一件事是替換您的:
var context = CIContext.FromOptions(null);
具有以下塊:
UIGraphics.BeginImageContextWithOptions (new SizeF (size, size), false, 0);
using (var c = UIGraphics.GetCurrentContext ()) {
var context = CIContext.FromContext (c);
...
}
UIGraphics.EndImageContext ();
更新 : FromContext
在iOS中不可用(特定於OSX),因此上面的代碼不起作用。
向MonoTouch團隊提交了錯誤。 將很快發布解決方案。
我現在建議三個“技巧”:
通過替換此行來強制范圍修剪圖像:
var cgimage = context.CreateCGImage(output, output.Extent);
有了這個:
var extent = output.Extent;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector("scale"))) {
if (UIScreen.MainScreen.Scale == 2f) {
extent = new System.Drawing.RectangleF(extent.X, extent.Y, extent.Width / 2f, extent.Height / 2f);
}
}
var cgimage = context.CreateCGImage(output, extent);
但是,如何在調整后的圖像上“降低”視網膜分辨率(它使用@ 2x圖像作為源,但由於應用了濾鏡,所以圖像的左下象限僅顯示在左下象限,這要歸功於圖像的左下角) 。
同樣,可以縮放從ChangeHue
方法返回的圖像,以使其不會超出導航欄:
var hued = ChangeHue (navBarImage);
if (hued.RespondsToSelector(new MonoTouch.ObjCRuntime.Selector("scale")))
hued = hued.Scale (new System.Drawing.SizeF(320, 47));
UINavigationBar.Appearance.SetBackgroundImage (hued, UIBarMetrics.Default);
不幸的是,您再次“降低”了視網膜分辨率,但至少圖像顯示正確(只是向下采樣到320寬)。
您可以將過濾后的圖像保存到磁盤,然后使用“磁盤”上的圖像文件設置UIAppearance
。 代碼如下所示:
bool retina = false;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector ("scale"))) {
if (UIScreen.MainScreen.Scale == 2f) {
retina = true;
}
}
if (retina) {
NSError err; // unitialized
UIImage img = ChangeHue (navBarImage);
img.AsPNG ().Save ("tempNavBar@2x.png", true, out err);
if (err != null && err.Code != 0) {
// error handling
}
UINavigationBar.Appearance.SetBackgroundImage (UIImage.FromFile ("tempNavBar.png"), UIBarMetrics.Default);
} else {
UINavigationBar.Appearance.SetBackgroundImage (ChangeHue (navBarImage), UIBarMetrics.Default);
}
最終破解的好處是圖像看起來正確(即,保留了視網膜分辨率)。
我仍在尋找“完美”的解決方案,但至少這些想法可以“單向”或“另一種”解決您的問題...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.