簡體   English   中英

MonoTouch:在視網膜顯示屏上調整色相時,外觀圖像大小加倍

[英]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;
}

應用色相后,這是“非視網膜”和“視網膜”顯示的結果:

非Retina

視網膜

忽略這些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團隊提交了錯誤。 將很快發布解決方案。

我現在建議三個“技巧”:

哈克#1

通過替換此行來強制范圍修剪圖像:

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圖像作為源,但由於應用了濾鏡,所以圖像的左下象限僅顯示在左下象限,這要歸功於圖像的左下角) 。

哈克2

同樣,可以縮放從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寬)。

哈克#3

您可以將過濾后的圖像保存到磁盤,然后使用“磁盤”上的圖像文件設置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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM