一對夫婦的想法:
你去寫你自己的圖像處理程序之前,你可能會考慮應用Core Image filters之一。它可能會讓你的生活變得更加輕鬆,並且可能會給你更精緻的結果。只是將每個通道縮小一些固定的數字會導致您不期待的失真(例如,色彩偏移,飽和度變化等)。
如果你打算這樣做,我會警惕只抓住數據提供者並按原樣操縱它。您可能想要爲圖像提供者的性質介紹各種條件邏輯(每個通道的位數,ARGB與RGBA等)。如果您查看Apple's example in Q&A #1509,則可以取而代之檢索預定格式的像素緩衝區(在其示例ARGB中,每個組件8位,每個像素4個字節)
此示例已過期,但它顯示瞭如何創建上下文然後將圖像繪製到該上下文中,然後您可以操作該數據,並使用此預定格式使用您自己的提供程序而不是JPEG數據提供程序創建新圖像
最重要的問題你的代碼示例是你試圖使用CGImageCreateWithJPEGDataProvider
,它需要一個「提供JPEG編碼數據的數據提供者」。但是你的提供者可能不是JPEG編碼的,所以它會失敗。如果你打算使用f中的數據ormat),那麼你必須使用CGImageCreate
(手動提供寬度,高度,bitsPerComponent,bitsPerPixel,bytesPerRow,colorSpace,bitmapInfo等)創建一個新圖像。
還有一些不太嚴重的問題,你的日常:
你注意,你所看到的每一個第四個字節是0xff
。在你的代碼評論中回答你的問題,這無疑是alpha通道。 (您可以通過檢查原始CGImageRef
的CGBitmapInfo
來確認。)您可能沒有使用Alpha通道,但顯然存在。
如果通道的值小於0x0a
,則您的例程將其設置爲0xff
。這顯然不是你的意圖(例如,如果像素是黑色的,你會使它變白!)。你應該檢查這個邏輯。
在我的測試中,這種迭代/操作Byte
數組的方法非常慢。我不完全確定這是爲什麼,但如果你直接操縱字節緩衝區,速度會更快。
所以,下面,請找創建預定格式的情況下(RGBA,每個組件8位等)例程,操作它(我轉換到B &W¯¯雖然你可以做任何你想要的),並從中創建新的圖像。因此,在斯威夫特2:
func blackAndWhiteImage(image: UIImage) -> UIImage? {
// get information about image
let imageref = image.CGImage
let width = CGImageGetWidth(imageref)
let height = CGImageGetHeight(imageref)
// create new bitmap context
let bitsPerComponent = 8
let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = Pixel.bitmapInfo
let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo)
// draw image to context
let rect = CGRectMake(0, 0, CGFloat(width), CGFloat(height))
CGContextDrawImage(context, rect, imageref)
// manipulate binary data
let pixels = UnsafeMutablePointer<Pixel>(CGBitmapContextGetData(context))
for row in 0 ..< height {
for col in 0 ..< width {
let offset = Int(row * width + col)
let red = Float(pixels[offset].red)
let green = Float(pixels[offset].green)
let blue = Float(pixels[offset].blue)
let alpha = pixels[offset].alpha
let luminance = UInt8(0.2126 * red + 0.7152 * green + 0.0722 * blue)
pixels[offset] = Pixel(red: luminance, green: luminance, blue: luminance, alpha: alpha)
}
}
// return the image
let outputImage = CGBitmapContextCreateImage(context)!
return UIImage(CGImage: outputImage, scale: image.scale, orientation: image.imageOrientation)
}
凡
struct Pixel: Equatable {
private var rgba: UInt32
var red: UInt8 {
return UInt8((rgba >> 24) & 255)
}
var green: UInt8 {
return UInt8((rgba >> 16) & 255)
}
var blue: UInt8 {
return UInt8((rgba >> 8) & 255)
}
var alpha: UInt8 {
return UInt8((rgba >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
rgba = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
static let bitmapInfo = CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue
}
func ==(lhs: Pixel, rhs: Pixel) -> Bool {
return lhs.rgba == rhs.rgba
}
或者,斯威夫特3:
func blackAndWhite(image: UIImage) -> UIImage? {
// get information about image
let imageref = image.cgImage!
let width = imageref.width
let height = imageref.height
// create new bitmap context
let bitsPerComponent = 8
let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = Pixel.bitmapInfo
let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)!
// draw image to context
let rect = CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))
context.draw(imageref, in: rect)
// manipulate binary data
guard let buffer = context.data else {
print("unable to get context data")
return nil
}
let pixels = buffer.bindMemory(to: Pixel.self, capacity: width * height)
for row in 0 ..< height {
for col in 0 ..< width {
let offset = Int(row * width + col)
let red = Float(pixels[offset].red)
let green = Float(pixels[offset].green)
let blue = Float(pixels[offset].blue)
let alpha = pixels[offset].alpha
let luminance = UInt8(0.2126 * red + 0.7152 * green + 0.0722 * blue)
pixels[offset] = Pixel(red: luminance, green: luminance, blue: luminance, alpha: alpha)
}
}
// return the image
let outputImage = context.makeImage()!
return UIImage(cgImage: outputImage, scale: image.scale, orientation: image.imageOrientation)
}
struct Pixel: Equatable {
private var rgba: UInt32
var red: UInt8 {
return UInt8((rgba >> 24) & 255)
}
var green: UInt8 {
return UInt8((rgba >> 16) & 255)
}
var blue: UInt8 {
return UInt8((rgba >> 8) & 255)
}
var alpha: UInt8 {
return UInt8((rgba >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
rgba = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: Pixel, rhs: Pixel) -> Bool {
return lhs.rgba == rhs.rgba
}
}
而不是由像素打算像素,創建充滿色彩的圖像(是0xA) ,並從你的原始圖像中減去它。您可以使用UIRectFill使用顏色填充圖像。在UIColor上使用setFill()設置填充顏色。然後,減去 - http://stackoverflow.com/questions/9690576/subtract-one-image-from-another-ios – 2014-11-01 03:48:09