2015-11-30 19 views
0

在查看從我們的某臺服務器獲取的嵌入式圖像的功能時,其中一個要求是製作概覽頁面,其中顯示所有圖像,像iOS Native Photos App這樣的一種方式(正方形瓷磚,在4/5的行中,並且被點擊時,在整個屏幕上顯示圖像將圖像裁剪爲像本機一樣的「完美」廣場照片應用程序

除了圖像變形之外,這已被成功實現因此,他們要求我設計一種方法來裁剪圖像,所以原始方面保持不變。

爲了做到這一點,我想先調整圖像的大小,直到寬度達到我想要的最大寬度((screenwidth - 10)/ 4-5)。

  • 如果圖像的高度小於寬度,我將高度設置爲等於寬度,然後相應地裁剪寬度(不改變方向)。
  • 如果圖像的高度大於寬度,我只想裁剪高度。

這是我目前使用的方法:

//Images is an array/List with base64 strings 
foreach (var image in Images) 
{ 
    UIImage imageToAdd = UIImage.LoadFromData(NSData.FromArray(Convert.FromBase64String(image.Content))); 

    var width = imageToAdd.Size.Width; 
    var height = imageToAdd.Size.Height; 

    //GlobalSupport.ScreenWidth is a static variable that contains the actual screensize 
    var newWidth = (GlobalSupport.ScreenWidth - 10)/4 - 5; 

    var newHeight = height * newWidth/width; 

    var widthToCrop = 0.0f; 
    var heightToCrop = 0.0f; 

    //If the new height is smaller than the new width, make the new height equal to the new width, and modify the new width accordingly. 
    if (newHeight < newWidth) 
    { 
     newHeight = newWidth; 
     newWidth = width * newHeight/height; 

     widthToCrop = newWidth - newHeight; 
    } 
    //Or, if the new height is greater than the new width, just crop the height. 
    else if (newHeight > newWidth) 
    { 
     heightToCrop = newHeight - newWidth; 
    } 

    UIGraphics.BeginImageContext(new SizeF(newWidth, newHeight)); 
    var cropRectangle = new RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight); 
    imageToAdd.Draw(cropRectangle); 
    imageToAdd = UIGraphics.GetImageFromCurrentImageContext(); 
    UIGraphics.EndImageContext(); 

    UIButton btnToAdd = new UIButton(new RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight)); 

    btnToAdd.SetBackgroundImage(imageToAdd, UIControlState.Normal); 

    btnToAdd.TouchUpInside += (sender, e) => 
    { 
     Task.Factory.StartNew(() => 
      { 
       //Displays a loading spinner 
       GlobalSupport.EnableLoadingOverlay(true, NSBundle.MainBundle.LocalizedString("txtOneMoment", "", "")); 
      }).ContinueWith(task => InvokeOnMainThread(() => 
       { 
        //Navigate to the full-screen image viewer 
        this.NavigationController.PushViewController(
         new VCDCMPhotoDetails(
          UIImage.LoadFromData(
           NSData.FromArray(
            Convert.FromBase64String(image.Content)))), true); 

        GlobalSupport.EnableLoadingOverlay(false, ""); 
       })); 
    }; 

    //Add btn to the scrollable view's children 
    scrollView.AddSubview(btnToAdd); 
} 

這種方法效果很好,除了一兩件事:如果new heightnew width,在new heightnew width順利拿到修改,但小在ImageToAdd.Draw(RectangleF)之後,ImageToAddSize仍然具有new width的值,而不是裁剪的寬度(即,如果我可以假設,如果使用-20作爲其x值繪製圖像,寬度會被修改爲-20以及)。

我不知道這是否是正確的做法。如果不是,那麼歡迎所有幫助!如果這是正確的做法,但我錯過了一些東西,請告訴我!提前致謝!

當裁剪圖像,x座標等於所述圖像的寬度減去一個縮略圖的最大寬度:http://i.stack.imgur.com/uNm7k.png

裁剪之後,圖像仍具有原來的新的寬度,而不是裁切寬度:http://i.stack.imgur.com/rabeY.png

圖像生成的網格:http://i.stack.imgur.com/opo2f.jpg

回答

2

讓我告訴你如何用FILL操作裁剪圖像的正確過程。該代碼是斯威夫特,但你應該沒有問題,將它移植:

public static func resampleImageToSize(image: UIImage!, size: CGSize) -> UIImage { 
     let originalWidth = image.size.width 
     let originalHeight = image.size.height 
     let originalRatio = originalWidth/originalHeight 

     let targetRatio = size.width/size.height 

     var targetFrame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height) 

     if originalRatio>targetRatio { 
      // crop width 
      let targetHeight = size.height 
      let targetWidth = targetHeight * originalRatio 
      targetFrame = CGRect(x: (size.width-targetWidth)*0.5, y: (size.height-targetHeight)*0.5, width: targetWidth, height: targetHeight) 

     } else if originalRatio<targetRatio { 
      // crop height 
      let targetWidth = size.width 
      let targetHeight = targetWidth/originalRatio 
      targetFrame = CGRect(x: (size.width-targetWidth)*0.5, y: (size.height-targetHeight)*0.5, width: targetWidth, height: targetHeight) 
     } 

     UIGraphicsBeginImageContext(size) 
     image.drawInRect(targetFrame) 
     let outputImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     return outputImage 
    } 

所以這是發生在原始圖像,並用大小您所選擇的返回圖像的一般方法。在你的情況下,這是你想要顯示的圖標的大小。此處的操作是填充,如果您需要合適您需要做的全部圖像是在if語句中交換<>

2

你在做什麼是最容易實現與創建與您的目標圖像尺寸的大小的形象圖。然後將圖像設置爲它並設置內容模式以縮放方面填充,並簡單地創建視圖的屏幕截圖(您可以在網絡上找到非常簡單的解決方案)。

從你的問題,我看不出你是否有問題或它是什麼。但有一件事是困擾我。該行

RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight) 

將裁剪的方式,你將永遠得到圖像的右下角部分。你應該最有可能的中心是:

RectangleF(-widthToCrop*0.5, -heightToCrop*0.5, newWidth, newHeight) 

好吧,我想我找到了你的問題。您計算的框架是您應該在其上繪製圖像以將其放在正方形上的框架。但是當你開始圖像上下文時,你應該將大小設置爲一個正方形。所以如果寬度較大,尺寸應爲(newHeight, newHeight),否則爲(newWidth, newWidth)。按鈕框架對我來說也沒有意義。爲什麼使用只應用於重繪圖像的矩形?

+0

問題是,當我將圖像放入另一個控件(如UIButton)時,圖像右側有一個透明空間(這是「裁剪」空間)。 例如:如果我有300x200的圖像,並希望它爲50x50,我調整它的大小以填充最大高度,並相應地修改寬度。使用OP中描述的方法,我得到的圖像不是Size 50x30,而是更像75x30(在它的屬性中,當查看圖像時,它完全是正方形,只是透明空間在那裏)。這樣,即使我裁剪了它,圖像也會在控件中變形。 –

+0

檢查編輯我製作 –

+0

我修改了按鈕框架作爲實驗,看它是否有任何效果。我已經把它改回來了。我會嘗試按照您的建議修改圖像上下文框架,然後讓您知道結果!謝謝! –