我写了以下函数:
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
}
Run Code Online (Sandbox Code Playgroud)
我想返回outputData以在屏幕上显示它.因此我在另一个函数中创建了这段代码:
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
}
Run Code Online (Sandbox Code Playgroud)
outputData是我现在想要显示的数据.我预计"ConvertImageToBlackAndWhite"中for循环的更改会被反映出来,但根本不会发生任何变化.
感谢Rob我以前得到了一些有价值的见解.但这张照片仍然没有变化.
我的问题是:
1)将此输出数据var创建为返回值是否正确?它有意义吗?
2)我使用这个返回的outputData变量来创建Context并绘制上下文.但这没有效果.我需要先创建一个新的图像吗?processusingPixels的返回值是UIImage.但我认为CGContextDrawImage就足够了.那是错的吗?
你正在循环currentPixel内初始化for.在开始循环之前执行此操作,例如:
var currentPixel = inputPixels
for row in 0 ..< inputHeight {
for column in 0 ..< inputWidth {
var color: UInt32 = currentPixel.memory
print(String(format:"%X", color))
currentPixel++
}
}
Run Code Online (Sandbox Code Playgroud)
完成后,您可以使用CGBitmapContextCreateImage以下方法创建新图像:
func processUsingPixels(inputImage 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.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 row in 0 ..< inputHeight {
for column in 0 ..< inputWidth {
currentPixel.memory = grayScaleFromColor(currentPixel.memory)
currentPixel++
}
}
let outputCGImage = CGBitmapContextCreateImage(context)
return UIImage(CGImage: outputCGImage)!
}
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)
}
Run Code Online (Sandbox Code Playgroud)
注意,我calloc从上面删除了.如果你把它保存在日常生活中,请确保free它.
原始问题中隐含的是从UInt32颜色中提取RGBA值的功能,以及从RGBA值创建颜色的功能.为了完整起见,我将包括一些示例再现:
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)
}
Run Code Online (Sandbox Code Playgroud)
就我个人而言,我真的不喜欢玩这种位移,所以我自然会倾向于使用a struct(就像我在这个答案中所做的那样;使用PremultipliedFirst而不是在PremultipliedLast这里使用的问题,但概念将是相同).但是以任何你想要的方式访问/操作缓冲区.
| 归档时间: |
|
| 查看次数: |
1894 次 |
| 最近记录: |