剪辑到UIBezierPath的UIImage(不屏蔽)
我正在尝试基于给定的UIBezierPath
剪辑UIImage
,但生成的图像保留原始形状和大小。 我希望形状和大小类似于路径,即新图像的可见内容。
看看下面这个例子:
以下是我用来屏蔽给定路径的图像的代码:
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 }
一种解决方案是在屏蔽后对图像进行裁剪,但理想情况下,我希望一次完成尽可能简单有效的图像。
任何解决方案/提示将不胜感激。
感谢Rob,我能够使用CGImage
的cropping(to:)
方法实现解决方案。
这是一个两步过程,首先我使用给定的路径屏蔽图像,然后使用路径的边界裁剪结果。
以下是我实现剪辑 UIBezierPath
UIImage
扩展的最终工作源代码:
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 } }
我在目标C中使用以下内容,用于将任何图像裁剪为非透明矩形。 检查它是否有用
@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 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 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