픽셀 단위로 이미지를 처리하는 데 유용한 도우미를 만들었습니다. 기본적으로 RGBA 이미지 컨텍스트를 생성하고 이미지를 이미지에 복사합니다 (이미지 데이터를 jpeg 또는 무언가로 작업 할 수 있도록). 그리고 원시 데이터 버퍼를 가져옵니다. 이것은 내가 만든 클래스입니다 :
public final class RGBAPixels {
static let bitmapInfo = CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedLast.rawValue
static let colorSpace = CGColorSpaceCreateDeviceRGB()
public typealias Pixel = (r: UInt8, g: UInt8, b: UInt8, a: UInt8)
let context : CGContext
let pointer : UnsafeMutablePointer<Pixel>
public let width : Int
public let height : Int
public let range : (x: Range<Int>, y: Range<Int>)
/// Generates an image from the current pixels
public var CGImage : CGImageRef? {
return CGBitmapContextCreateImage(context)
}
public init?(CGImage: CGImageRef) {
width = CGImageGetWidth(CGImage)
height = CGImageGetHeight(CGImage)
range = (0..<width, 0..<height)
guard let context = CGBitmapContextCreate(
nil, width, height, 8, sizeof(Pixel) * width,
RGBAPixels.colorSpace, RGBAPixels.bitmapInfo)
else { return nil }
self.context = context
let rect = CGRect(origin: .zero, size: CGSize(width: width, height: height))
CGContextDrawImage(context, rect, CGImage)
pointer = UnsafeMutablePointer(CGBitmapContextGetData(context))
}
public subscript (x: Int, y: Int) -> Pixel {
get {
assert(range.x ~= x && range.y ~= y, "Pixel position (\(x), \(y)) is out of the bounds \(range))")
return pointer[y * width + x]
}
set {
assert(range.x ~= x && range.y ~= y, "Pixel position (\(x), \(y)) is out of the bounds \(range))")
pointer[y * width + x] = newValue
}
}
}
그것은 은 그 자체로 사용 가능한,하지만 당신은 좀 더 편리하도록 할 수 있습니다 :
public protocol Image {
var CGImage : CGImageRef? { get }
}
public extension Image {
public var pixels : RGBAPixels? {
return CGImage.flatMap(RGBAPixels.init)
}
public func copy(@noescape modifying : (pixels: RGBAPixels) -> Void) -> CGImageRef? {
return pixels.flatMap{ pixels in
modifying(pixels: pixels)
return pixels.CGImage
}
}
}
extension CGImage : Image {
public var CGImage: CGImageRef? { return self }
}
#if os(iOS)
import class UIKit.UIImage
extension UIImage : Image {}
extension RGBAPixels {
public var image : UIImage? {
return CGImage.map(UIImage.init)
}
}
#elseif os(OSX)
import class AppKit.NSImage
extension NSImage : Image {
public var CGImage : CGImageRef? {
var rect = CGRect(origin: .zero, size: size)
return CGImageForProposedRect(&rect, context: nil, hints: nil)
}
}
extension RGBAPixels {
public var image : NSImage? {
return cgImage.flatMap{ img in
NSImage(CGImage: img, size: CGSize(width: width, height: height))
}
}
}
#endif
그것은이 같은 사용 가능한입니다 :
let image = UIImage(named: "image")!
let pixels = image.pixels!
// Add a red square
for x in 10..<15 {
for y in 10..<15 {
pixels[x, y] = (255, 0, 0, 255)
}
}
let modifiedImage = pixels.image
// Copy the image, while changing the pixel at (10, 10) to be blue
let otherImage = UIImage(named: "image")!.copy{ $0[10, 10] = (0, 255, 0, 255) }
let a = UIImage(named: "image")!.pixels!
let b = UIImage(named: "image")!.pixels!
// Set the pixel at (10, 10) of a to the pixel at (20, 20) of b
a[10, 10] = b[20, 20]
let result = a.image!
을
데모 용으로 풀지 않은 상태에서 실제로 앱을 실행하지 마십시오.
구현은 CPU에서 얻을 수있는 것만큼 빠릅니다. 그냥 복사하는 것보다 더 복잡한 방법으로 많은 이미지를 수정해야하는 경우 CoreImage를 대신 사용할 수 있습니다.
OSX의 NSImage
s 과 iOS의 UIImage
모두로이 작업을 만들었습니다.
Simon from the rescue! 그나저나 책을 사랑해! –
빠른 질문 - 실제로 이미지에서 사용하고있는 색상을 참조하고 싶습니다. 'vec4 targetColor'를하는 대신 색상을 얻을 다른 __sample이 있으면 어떻게 될까요? vec4 targetColor = sample (pixel2, targetCoord)'를 사용하여 참조 할 색상을 알려줄 수 있습니다. –
두 이미지를 커널에 전달하고'vec2 imageSpaceCoord = samplerTransform (xyzImage, destCoord());로 소스 픽셀 색상을 얻을 수 있습니다. vec4 targetColor = sample (image, imageSpaceCoord);'- 여기서'xyzImage'는 샘플링중인 이미지입니다. 책에 대한 친절한 단어를 주셔서 감사합니다 :) –