ピクセル単位で画像を扱うための有用なヘルパーを作成しました。基本的には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'を実行する代わりに、色を取得するために別の__サンプルがあるとどうなりますか? 'vec4 targetColor = sample(pixel2、targetCoord)'を使って、参照する色を教えてください。 –
カーネルに両方のイメージを渡し、 'vec2 imageSpaceCoord = samplerTransform(xyzImage、destCoord());でソースピクセルの色を取得することができます。 vec4 targetColor = sample(image、imageSpaceCoord); ' - ここで' xyzImage'はサンプリング元の画像です。この本のおかげで、ありがとうございました:) –