├── demo.playground ├── Resources │ └── image.jpg ├── Contents.swift ├── contents.xcplayground ├── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── marius.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── timeline.xctimeline └── Sources │ └── RGBA.swift └── README.md /demo.playground/Resources/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhorga/ImageProcessing/HEAD/demo.playground/Resources/image.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImageProcessing 2 | 3 | Repository to accompany the blog post at http://mhorga.org/2015/10/19/image-processing-in-ios-part-3.html 4 | -------------------------------------------------------------------------------- /demo.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | let image = UIImage(named: "image.jpg")! 5 | let newImage = contrast(image: image).toUIImage() 6 | image 7 | 8 | newImage 9 | -------------------------------------------------------------------------------- /demo.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /demo.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /demo.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhorga/ImageProcessing/HEAD/demo.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /demo.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demo.playground/Sources/RGBA.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | struct Pixel { 5 | var value: UInt32 6 | var red: UInt8 { 7 | get { return UInt8(value & 0xFF) } 8 | set { value = UInt32(newValue) | (value & 0xFFFFFF00) } 9 | } 10 | var green: UInt8 { 11 | get { return UInt8((value >> 8) & 0xFF) } 12 | set { value = (UInt32(newValue) << 8) | (value & 0xFFFF00FF) } 13 | } 14 | var blue: UInt8 { 15 | get { return UInt8((value >> 16) & 0xFF) } 16 | set { value = (UInt32(newValue) << 16) | (value & 0xFF00FFFF) } 17 | } 18 | var alpha: UInt8 { 19 | get { return UInt8((value >> 24) & 0xFF) } 20 | set { value = (UInt32(newValue) << 24) | (value & 0x00FFFFFF) } 21 | } 22 | } 23 | 24 | public struct RGBA { 25 | var pixels: UnsafeMutableBufferPointer 26 | var width: Int 27 | var height: Int 28 | 29 | init?(image: UIImage) { 30 | guard let cgImage = image.cgImage else { return nil } 31 | width = Int(image.size.width) 32 | height = Int(image.size.height) 33 | let bitsPerComponent = 8 34 | let bytesPerPixel = 4 35 | let bytesPerRow = width * bytesPerPixel 36 | let imageData = UnsafeMutablePointer.allocate(capacity: width * height) 37 | let colorSpace = CGColorSpaceCreateDeviceRGB() 38 | var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue 39 | bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue 40 | guard let imageContext = CGContext(data: imageData, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { return nil } 41 | imageContext.draw(cgImage, in: CGRect(origin: CGPoint(x: 0,y :0), size: image.size)) 42 | pixels = UnsafeMutableBufferPointer(start: imageData, count: width * height) 43 | } 44 | 45 | public func toUIImage() -> UIImage? { 46 | let bitsPerComponent = 8 47 | let bytesPerPixel = 4 48 | let bytesPerRow = width * bytesPerPixel 49 | let colorSpace = CGColorSpaceCreateDeviceRGB() 50 | var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue 51 | bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue 52 | let imageContext = CGContext(data: pixels.baseAddress, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo, releaseCallback: nil, releaseInfo: nil) 53 | guard let cgImage = imageContext!.makeImage() else {return nil} 54 | let image = UIImage(cgImage: cgImage) 55 | return image 56 | } 57 | } 58 | 59 | public func contrast(image: UIImage) -> RGBA { 60 | let rgba = RGBA(image: image)! 61 | var totalRed = 0 62 | var totalGreen = 0 63 | var totalBlue = 0 64 | 65 | for y in 0..