通过图片像素循环 [英] Looping through pixels in pictures

查看:131
本文介绍了通过图片像素循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了下面的功能:

    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.

这篇关于通过图片像素循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆