Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save silvinaroldan/94d5cace5acc858654bc0e28dc033a83 to your computer and use it in GitHub Desktop.
Save silvinaroldan/94d5cace5acc858654bc0e28dc033a83 to your computer and use it in GitHub Desktop.
Swift Image Crop Out Transparent Pixels (Swift 2.0)
/*
Swift 3.2 update for Image Crop Out Transparent Pixels
Original gist https://gist.github.com/gregpardo/b69c6cdbec8276df19b9
*/
extension UIImage {
func imageByCroppingTransparentPixels() -> UIImage? {
let rect = cropOpaqueRectForImage()
guard let cgImage = self.cgImage, let cgImageCrop = cgImage.cropping(to: rect) else {
return nil
}
return UIImage(cgImage: cgImageCrop, scale: self.scale, orientation: self.imageOrientation)
}
func cropOpaqueRectForImage() -> CGRect {
guard let imageAsCGImage = self.cgImage, let context = createARGBBitmapContext(inImage: imageAsCGImage) else {
return .zero
}
let width = Int(imageAsCGImage.width)
let height = Int(imageAsCGImage.height)
let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height))
context.draw(imageAsCGImage, in: rect)
var lowX = width
var lowY = height
var highX = 0
var highY = 0
guard let data = context.data else {
return .zero
}
let dataType: UnsafeMutablePointer<UInt8> = data.assumingMemoryBound(to: UInt8.self)
for y in 0..<height {
for x in 0..<width {
let pixelIndex = (width * y + x) * 4 /* 4 for A, R, G, B */
if dataType[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 }
}
}
}
free(data)
return CGRect(x: CGFloat(lowX), y: CGFloat(lowY), width: CGFloat(highX - lowX), height: CGFloat(highY - lowY))
}
func createARGBBitmapContext(inImage: CGImage) -> CGContext? {
let pixelsWidth = inImage.width
let pixelsHeight = inImage.height
// Declare the number of bytes per row. Each pixel in the bitmap in this
// example is represented by 4 bytes; 8 bits each of red, green, blue, and
// alpha.
let bitmapBytesPerRow = Int(pixelsWidth) * 4
let bitmapByteCount = bitmapBytesPerRow * Int(pixelsHeight)
let colorSpace = CGColorSpaceCreateDeviceRGB()
// Allocate memory for image data. This is the destination in memory
// where any drawing to the bitmap context will be rendered.
let bitmapData = malloc(bitmapByteCount)
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
// Create the bitmap context. We want pre-multiplied ARGB, 8-bits
// per component. Regardless of what the source image format is
// (CMYK, Grayscale, and so on) it will be converted over to the format
// specified here by CGBitmapContextCreate.
return CGContext(data: bitmapData, width: pixelsWidth, height: pixelsHeight, bitsPerComponent: 8, bytesPerRow: bitmapBytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment