├── 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..