How do I autocrop a UIImage?

后端 未结 6 493
南方客
南方客 2020-12-23 15:04

I have a UIImage which contains a shape; the rest is transparent. I\'d like to get another UIImage by cropping out as much of the transparent part as possible, still retain

6条回答
  •  再見小時候
    2020-12-23 15:58

    Swift Version:

    extension UIImage {
    func cropRect() -> CGRect {
        let cgImage = self.CGImage!
        let context = createARGBBitmapContextFromImage(cgImage)
        if context == nil {
            return CGRectZero
        }
    
        let height = CGFloat(CGImageGetHeight(cgImage))
        let width = CGFloat(CGImageGetWidth(cgImage))
    
        let rect = CGRectMake(0, 0, width, height)
        CGContextDrawImage(context, rect, cgImage)
    
        let data = UnsafePointer(CGBitmapContextGetData(context))
    
        if data == nil {
            return CGRectZero
        }
    
        var lowX = width
        var lowY = height
        var highX: CGFloat = 0
        var highY: CGFloat = 0
    
        //Filter through data and look for non-transparent pixels.
        for (var y: CGFloat = 0 ; y < height ; y++) {
            for (var x: CGFloat = 0; x < width ; x++) {
                let pixelIndex = (width * y + x) * 4 /* 4 for A, R, G, B */
    
                if data[Int(pixelIndex)] != 0 { //Alpha value is not zero pixel is not transparent.
                    if (x < lowX) {
                        lowX = x
                    }
                    if (x > highX) {
                        highX = x
                    }
                    if (y < lowY) {
                        lowY = y
                    }
                    if (y > highY) {
                        highY = y
                    }
                }
            }
        }
    
    
        return CGRectMake(lowX, lowY, highX-lowX, highY-lowY)
    }
    }
    

    The method to create the Bitmap Context:

    func createARGBBitmapContextFromImage(inImage: CGImageRef) -> CGContextRef? {
    
        let width = CGImageGetWidth(inImage)
        let height = CGImageGetHeight(inImage)
    
        let bitmapBytesPerRow = width * 4
        let bitmapByteCount = bitmapBytesPerRow * height
    
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        if colorSpace == nil {
            return nil
        }
    
        let bitmapData = malloc(bitmapByteCount)
        if bitmapData == nil {
            return nil
        }
    
        let context = CGBitmapContextCreate (bitmapData,
            width,
            height,
            8,      // bits per component
            bitmapBytesPerRow,
            colorSpace,
            CGImageAlphaInfo.PremultipliedFirst.rawValue)
    
        return context
    }
    

    And finally, get your new cropped UIImage from the returned CGRect:

    let image = // UIImage Source
    let newRect = image.cropRect()
    if let imageRef = CGImageCreateWithImageInRect(image.CGImage!, newRect) {
        let newImage = UIImage(CGImage: imageRef)
        // Use this new Image
    }
    

提交回复
热议问题