2016-11-26 39 views
2

我試圖剪輯基於給定UIBezierPath一個UIImage,但所得到的圖像保留原始形狀和尺寸。我希望形狀和大小類似於路徑,即新圖像的可見內容。剪輯的UIImage到UIBezierPath(未掩蔽)

看看下面的例子中:

Input image, input path, actual result, and desired result

以下是我使用來掩蓋給出的路徑圖像代碼:

func imageByApplyingClippingBezierPath(_ path: UIBezierPath) -> UIImage { 
    UIGraphicsBeginImageContextWithOptions(CGSize(
     width: size.width, 
     height: size.height 
    ), false, 0.0) 
    let context = UIGraphicsGetCurrentContext()! 
    context.saveGState() 

    path.addClip() 
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) 

    let newImage = UIGraphicsGetImageFromCurrentImageContext()! 

    context.restoreGState() 
    UIGraphicsEndImageContext() 

    return newImage 
} 

一個解決辦法是農作物在掩蓋它之後的圖像,但理想情況下,我希望這樣做盡可能簡單而有效。

任何溶液/提示,將不勝感激。

+1

不,請繼續前進並裁剪它。這很簡單,只需要調用一次'CGImageCreateWithImageInRect'。 – Rob

+0

感謝您對@Rob的評論,你會介意分享一個關於如何實現這個的快速代碼片段嗎? – Aleksander

+0

不需要編碼樣本Rob,我想通了。感謝指針! – Aleksander

回答

3

感謝Rob我能夠實施cropping(to:)方法CGImage的解決方案。

這是一個兩個步驟的過程,其中第一I使用給定的路徑遮蔽圖像,然後裁剪使用路徑的邊界的結果。

以下是用於實現剪裁UIBezierPathUIImage擴展我的最終工作的源代碼:

extension UIImage { 

    func imageByApplyingClippingBezierPath(_ path: UIBezierPath) -> UIImage { 
     // Mask image using path 
     let maskedImage = imageByApplyingMaskingBezierPath(path) 

     // Crop image to frame of path 
     let croppedImage = UIImage(cgImage: maskedImage.cgImage!.cropping(to: path.bounds)!) 
     return croppedImage 
    } 

    func imageByApplyingMaskingBezierPath(_ path: UIBezierPath) -> UIImage { 
     // Define graphic context (canvas) to paint on 
     UIGraphicsBeginImageContext(size) 
     let context = UIGraphicsGetCurrentContext()! 
     context.saveGState() 

     // Set the clipping mask 
     path.addClip() 
     draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) 

     let maskedImage = UIGraphicsGetImageFromCurrentImageContext()! 

     // Restore previous drawing context 
     context.restoreGState() 
     UIGraphicsEndImageContext() 

     return maskedImage 
    } 

} 
+0

偉大的工作! man〜 – Jerome

+0

下面的目標c版本僅顯示解決方案的裁剪部分,我們可能有任何機會可以獲得所有解決方案的完整客觀c版本? @Aleksander我真的很感激它。 –

0

我使用按照客觀C,對於任何圖像裁剪非transperant矩形。檢查它是否有幫助

@implementation UIImage (cropTransperant) 
- (UIImage *) CropimageByTrimmingTransparentPixels { 
    int rows = self.size.height; 
    int cols = self.size.width; 
    int bytesPerRow = cols*sizeof(uint8_t); 

    if (rows < 2 || cols < 2) { 
     return self; 
    } 


    uint8_t *bitmapData = calloc(rows*cols, sizeof(uint8_t)); 


    CGContextRef contextRef = CGBitmapContextCreate(bitmapData, cols, rows, 8, bytesPerRow, NULL, kCGImageAlphaOnly); 


    CGImageRef cgImage = self.CGImage; 
    CGRect rect = CGRectMake(0, 0, cols, rows); 
    CGContextDrawImage(contextRef, rect, cgImage); 

    //get all non-transparent pixels in every row and every column 
    uint16_t *rowSum = calloc(rows, sizeof(uint16_t)); 
    uint16_t *colSum = calloc(cols, sizeof(uint16_t)); 

    //loop through all pixels 
    for (int row = 0; row < rows; row++) { 
     for (int col = 0; col < cols; col++) 
     { 
      if (bitmapData[row*bytesPerRow + col]) { //when you get non transperant pixel 
       rowSum[row]++; 
       colSum[col]++; 
      } 
     } 
    } 

     UIEdgeInsets crop = UIEdgeInsetsMake(0, 0, 0, 0); //croprect, initialize with 0,0,0, 

    for (int i = 0; i<rows; i++) {  //get top 
     if (rowSum[i] > 0) { 
      crop.top = i; break; 
     } 
    } 

    for (int i = rows; i >= 0; i--) {  //get bottom 
     if (rowSum[i] > 0) { 
      crop.bottom = MAX(0, rows-i-1); break; 
     } 
    } 

    for (int i = 0; i<cols; i++) {  //get left 
     if (colSum[i] > 0) { 
      crop.left = i; break; 
     } 
    } 

    for (int i = cols; i >= 0; i--) {  //get right 
     if (colSum[i] > 0) { 
      crop.right = MAX(0, cols-i-1); break; 
     } 
    } 

    free(bitmapData); 
    free(colSum); 
    free(rowSum); 

    if (crop.top == 0 && crop.bottom == 0 && crop.left == 0 && crop.right == 0) { 

     return self; 
    } 
    else { 

     rect.origin.x += crop.left; 
     rect.origin.y += crop.top; 
     rect.size.width -= crop.left + crop.right; 
     rect.size.height -= crop.top + crop.bottom; 

     //crop image to calcualted rect 
     CGImageRef newImage = CGImageCreateWithImageInRect(cgImage, rect); 


     return [UIImage imageWithCGImage:newImage]; 
    } 
} 

@end 
+0

我沒有機會測試您的代碼,但從邏輯上來說它似乎有意義。不過,理想情況下,我正在尋找更簡單,更高效的解決方案。我不知道爲什麼它被拒絕投票,任何人都在意解釋? – Aleksander