Awalz / SwiftyDraw

A simple, lightweight drawing framework written in Swift
MIT License
341 stars 66 forks source link

how to getCropped Image only without the background #25

Closed X901 closed 5 years ago

X901 commented 5 years ago

Hi , I did see this it worked to get an image with the background space

for example, if the UIView is 200X200 and I did draw in the corner when I get the image will be 200X200 with all the empty space and with the drawing I did in the corner

I want the get only the draw without the empty spaces

before I use this library I was using YPDrawSignatureView

and it did it like this

 // Save the Signature (cropped of outside white space) as a UIImage
    public func getCroppedSignature(scale:CGFloat = 1) -> UIImage? {
        guard let fullRender = getSignature(scale:scale) else { return nil }
        let bounds = self.scale(path.bounds.insetBy(dx: -strokeWidth/2, dy: -strokeWidth/2), byFactor: scale)
        guard let imageRef = fullRender.cgImage?.cropping(to: bounds) else { return nil }
        return UIImage(cgImage: imageRef)
    }

I did try to do a similar thing with this library but with no luck

X901 commented 5 years ago

I found a solution here

I use the same function to get the image from the draw view

extension UIView {
    func screenshot() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
        defer { UIGraphicsEndImageContext() }
        drawHierarchy(in: bounds, afterScreenUpdates: true)
        return UIGraphicsGetImageFromCurrentImageContext()
    }   
}

then I use this extension

extension UIImage {
    func cropAlpha() -> UIImage {

        let cgImage = self.cgImage!;

        let width = cgImage.width
        let height = cgImage.height

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bytesPerPixel:Int = 4
        let bytesPerRow = bytesPerPixel * width
        let bitsPerComponent = 8
        let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

        guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
            let ptr = context.data?.assumingMemoryBound(to: UInt8.self) else {
                return self
        }

        context.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: width, height: height))

        var minX = width
        var minY = height
        var maxX: Int = 0
        var maxY: Int = 0

        for x in 1 ..< width {
            for y in 1 ..< height {

                let i = bytesPerRow * Int(y) + bytesPerPixel * Int(x)
                let a = CGFloat(ptr[i + 3]) / 255.0

                if(a>0.5) {
                    if (x < minX) { minX = x }
                    if (x > maxX) { maxX = x }
                    if (y < minY) { minY = y}
                    if (y > maxY) { maxY = y}
                }
            }
        }

        let rect = CGRect(x: CGFloat(minX),y: CGFloat(minY), width: CGFloat(maxX-minX), height: CGFloat(maxY-minY))
        let imageScale:CGFloat = self.scale
        let croppedImage =  self.cgImage!.cropping(to: rect)!
        let ret = UIImage(cgImage: croppedImage, scale: imageScale, orientation: self.imageOrientation)

        return ret
    }
}

after that to use it

let imageCroppedBg = touchDrawView.screenshot()?.cropAlpha()

LinusGeffarth commented 5 years ago

@X901 I'll close this issue for now as you seem to have solved it yourself. Feel free to reopen it if you need any additional help.