通过图片像素循环
我写了下面的功能:
class func convertImageToBlackAndWhite(#data:UnsafeMutablePointer<UInt32>, inputWidth:UInt32, inputHeight:UInt32) -> UnsafeMutablePointer<UInt32> {
var currentPixel = UnsafeMutablePointer<UInt32>()
currentPixel = data
for (var i = 0; i < Int(inputHeight); i++) {
for (var j = 0; j < Int(inputWidth); j++) {
var color:UInt32 = currentPixel.memory
// Average of RGB = greyscale
var averageColor:UInt32 = (R(color) + G(color) + B(color)) / 3
var updatedColor:UInt32 = RGBAMake(averageColor, g: averageColor, b: averageColor, a: A(color))
currentPixel.memory = updatedColor
currentPixel++
}
}
var outputData = UnsafeMutablePointer<UInt32>((calloc(UInt(inputHeight*inputWidth), UInt(sizeof(UInt32)))))
outputData = currentPixel
return outputData
}
我要回的outputData显示在屏幕上。因此,我另一个函数中创建这个code:
I want to return the outputData to display it on screen. Therefore I created within another function this code:
class func processUsingPixels(#inputImage:UIImage) -> UIImage {
var inputCGImage:CGImageRef = inputImage.CGImage
var colorSpace:CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()
var inputWidth:UInt = CGImageGetWidth(inputCGImage)
var inputHeight:UInt = CGImageGetHeight(inputCGImage)
var bytesPerPixel:UInt = 4
var bitsPerComponent:UInt = 8
var inputBytesPerRow = bytesPerPixel * inputWidth
let bitmapInfo = CGBitmapInfo(CGBitmapInfo.ByteOrder32Big.rawValue | CGImageAlphaInfo.PremultipliedLast.rawValue)
let inputPixels = UnsafeMutablePointer<UInt32>(calloc(UInt(inputHeight*inputWidth), UInt(sizeof(UInt32))))
var outputData = UnsafeMutablePointer<UInt32>()
outputData = self.convertImageToBlackAndWhite(data: inputPixels, inputWidth: UInt32(inputWidth), inputHeight: UInt32(inputHeight))
let context:CGContextRef = CGBitmapContextCreate(outputData, inputWidth, inputHeight, bitsPerComponent, inputBytesPerRow, colorSpace, bitmapInfo)
CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(inputWidth), CGFloat(inputHeight)), inputCGImage)
return inputImage
}
该outputData是我现在就想来显示数据。我预计,在ConvertImageToBlackAndWhitefor循环的变化将反映,但根本没有发生变更。
The outputData was the data I wanted now to display. I expected that the changes by the for-loop in "ConvertImageToBlackAndWhite" would be reflected, but no change at all happens.
感谢Rob我之前得到了一些有价值的见解。但还是这幅画并没有改变。
Thanks to Rob I got some valuable insights before. but still this picture does not change at all.
我的问题是:
1)是它正确创建此输出数据变种作为返回值?是否在所有有意义吗?
1) is it correct to create this output data var as a return value? Does it make sense at all?
2)我使用已恢复到创建一个Context并绘制背景下,这个outputData变量。但是这并没有影响。我是否需要先创建一个新的图像? processusingPixels的返回值是一个UIImage的。但我以为CGContextDrawImage就足够了。是不是错了?
2) I use this outputData Variable that has been returned to create a Context and Draw the context. But this has no effect. Do I need to create a new Image first? The return value of processusingPixels is an UIImage. But I thought the CGContextDrawImage would be sufficient. Is that wrong?
正在初始化 currentPixel
中的为
循环。做到这一点,然后再开始的循环,例如:
You are initializing currentPixel
inside the for
loops. Do that before you start the loops, e.g.:
var currentPixel = inputPixels
for (var i = 0; i < Int(inputHeight); i++) {
for (var j = 0; j < Int(inputWidth); j++) {
var color:UInt32 = currentPixel.memory
println(String(format:"%X", color))
currentPixel++
}
}
当你完成,你可以创建一个使用新的图像 CGBitmapContextCreateImage
:
func processUsingPixels(#inputImage:UIImage) -> UIImage {
let inputCGImage = inputImage.CGImage
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = CGImageGetWidth(inputCGImage)
let height = CGImageGetHeight(inputCGImage)
let bytesPerPixel: UInt = 4
let bitsPerComponent: UInt = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = CGBitmapInfo(CGBitmapInfo.ByteOrder32Big.rawValue | CGImageAlphaInfo.PremultipliedLast.rawValue)
let context:CGContextRef = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo)
CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), inputCGImage)
let pixelBuffer = UnsafeMutablePointer<UInt32>(CGBitmapContextGetData(context))
var currentPixel = pixelBuffer
for (var i = 0; i < Int(height); i++) {
for (var j = 0; j < Int(width); j++) {
currentPixel.memory = grayScaleFromColor(currentPixel.memory)
currentPixel++
}
}
let ouputCGImage = CGBitmapContextCreateImage(context)
let outoutImage = UIImage(CGImage: ouputCGImage)
return outoutImage!
}
func grayScaleFromColor(color: UInt32) -> UInt32 {
let r = Double(red(color))
let g = Double(green(color))
let b = Double(blue(color))
let a = alpha(color)
let gray = UInt8(0.2126 * r + 0.7152 * g + 0.0722 * b)
return rgba(red: gray, green: gray, blue: gray, alpha: a)
}
请注意,我删除释放calloc
从上面。如果你一直在你的日常,请务必免费
了。
Note, I removed calloc
from the above. If you keep that in your routine, make sure to free
it.
隐函数分别从 UInt32的
颜色提取RGBA值,也可以创建自RGBA值的颜色。为了完整起见,我将包括一些示例引渡:
Implicit in the original question were functions to extract RGBA values from the UInt32
color, and also to create a color from the RGBA values. For the sake of completeness, I'll include some sample renditions:
func red(color: UInt32) -> UInt8 {
return UInt8(color & 255)
}
func green(color: UInt32) -> UInt8 {
return UInt8((color >> 8) & 255)
}
func blue(color: UInt32) -> UInt8 {
return UInt8((color >> 16) & 255)
}
func alpha(color: UInt32) -> UInt8 {
return UInt8((color >> 24) & 255)
}
func rgba(#red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -> UInt32 {
return UInt32(red) | (UInt32(green) << 8) | (UInt32(blue) << 16) | (UInt32(alpha) << 24)
}
就个人而言,我真的不喜欢这种换挡位的玩弄,所以我自然会倾向于使用结构
(像我一样的in这个答案;所使用 premultipliedFirst
,而不是用在问题 premultipliedLast
这里,但概念是相同)。但访问/操纵缓冲区你想要的任何方式。
Personally, I don't really like playing around with this shifting of bits, so I'd naturally be inclined to use a struct
(like I did in this answer; that used PremultipliedFirst
rather than the PremultipliedLast
used in the question here, but the concept would be the same). But access/manipulate the buffer any way you want.