剪辑的UIImage到UIBezierPath(未掩蔽)

问题描述:

我试图剪辑基于给定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

感谢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我真的很感激它。 –

我使用按照客观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