Looping through pixels in pictures

I have written the following function:

    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
}

I want to return the outputData to display it on screen. Therefore I created within another function this code:

  • What does the question mark and the colon (?: ternary operator) mean in objective-c?
  • How to set include path in xcode project
  • Memory goes on Increasing each time the interstitial ad is display in unity 5
  • Swift: Appending to Dictionary
  • How is this form of scoping called?
  • Swift multidimensional array
  •     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
    }
    

    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.

    Thanks to Rob I got some valuable insights before. but still this picture does not change at all.

    my questions would be:

    1) is it correct to create this output data var as a return value? Does it make sense at all?

    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?

    Solutions Collect From Internet About “Looping through pixels in pictures”

    You are initializing currentPixel inside the for loops. Do that before you start the loops, e.g.:

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

    When you’re done, you can create new image using 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)
    }
    

    Note, I removed calloc from the above. If you keep that in your routine, make sure to free it.


    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)
    }
    

    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.