c - 遍历图片中的像素

标签 c arrays swift

我写了下面的函数:

    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 以在屏幕上显示它。因此,我在另一个函数中创建了这段代码:

    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 是我现在想要显示的数据。我预计“ConvertImageToBlackAndWhite”中的 for 循环所做的更改会得到反射(reflect),但根本没有发生任何更改。

感谢 Rob,我之前获得了一些有值(value)的见解。但这张图片仍然没有任何变化。

我的问题是:

1) 创建这个输出数据变量作为返回值是否正确?这有意义吗?

2)我使用这个已经返回的outputData变量来创建一个Context并绘制上下文。但这没有效果。我需要先创建一个新图像吗? processusingPixels 的返回值是一个 UIImage。但我认为 CGContextDrawImage 就足够了。错了吗?

最佳答案

您正在 for 循环中初始化 currentPixel。在开始循环之前执行此操作,例如:

var currentPixel = inputPixels

for row in 0 ..< inputHeight {
    for column in 0 ..< inputWidth {
        var color: UInt32 = currentPixel.memory
        print(String(format:"%X", color))
        currentPixel++
    }
}

完成后,您可以使用 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)
}

请注意,我从上面删除了 calloc。如果您将它保留在您的日常工作中,请确保释放它。


原始问题中隐含的函数是从 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)
}

就我个人而言,我不太喜欢玩这种位的移动,所以我自然倾向于使用 struct (就像我做的 in this answer ;它使用了 PremultipliedFirst 而不是此处问题中使用的 PremultipliedLast,但概念是相同的)。但是可以以任何你想要的方式访问/操作缓冲区。

关于c - 遍历图片中的像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28799701/

相关文章:

c - fscanf 和动态数组分配

java - 不同的按钮,相同的导航 Activity ,但导航 Activity 中 fragment 的结果不同

ios - 快速从数组中获取值?

ios - 如何在 swift 4 中使用对象映射器附加字典数组?

c - 3 位数字的缓冲区

c - 为什么在减去指向结构的指针时会得到奇怪的结果?

swift - 为什么核心数据不会在 swiftui 类中加载,但会在结构 View 中加载

swift - 数组修改时的执行闭包

c - 如何正确地字节移位一大块数据?

c - 分配类型不兼容,从 BSTNode* 到 BSTNode*