CraftyCoder CraftyCoder - 3 months ago 27
Swift Question

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

In my swift project, I have two classes that work together to hold Pixel values of an image to be able to modify red, green, blue and alpha values. An

holds lots of bites that are comprised of the Pixel class objects.

I can interact with that the class that holds the
property. I can access all of the properties on that object and that all works fine. The only problem I'm having with the
is trying to loop through it with my Pixel object and it keeps crashing with the Thread 1:

init!(image: UIImage)
_width = Int(image.size.width)
_height = Int(image.size.height)

guard let cgImage = image.cgImage else { return nil }

_width = Int(image.size.width)
_height = Int(image.size.height)
let bitsPerComponent = 8

let bytesPerPixel = 4
let bytesPerRow = _width * bytesPerPixel
let imageData = UnsafeMutablePointer<Pixel>.allocate(capacity: _width * _height)
let colorSpace = CGColorSpaceCreateDeviceRGB()

var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue
bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
guard let imageContext = CGContext(data: imageData, width: _width, height: _height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { return nil }
imageContext.draw(cgImage, in: CGRect(origin:, size: image.size))

_pixels = UnsafeMutableBufferPointer<Pixel>(start: imageData, count: _width * _height)

This function is the part that is crashing the program. The exact part that is crashing is the for loop that is looping through the rgba.pixels. rgba.pixels is the UnsafeMutableBufferPointer.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
let image: UIImage = info[UIImagePickerControllerEditedImage] as! UIImage!

let rgba = RGBA(image: image)!

for pixel in rgba.pixels

self.dismiss(animated: true, completion: nil);

This is the constructor where I create the
. Is there an easier way to do this and still be able to get the RBGA values and change them easily.

The Pixel class is a
value this is split into four
UInt 8

Am I using the wrong construct to hold those values and if so, is there a safer or easier construct to use? Or am I doing something wrong when accessing the Pixel values?


This is how I got the pixels of an image -

// Grab and set up variables for the original image
    let inputCGImage = inputImage.CGImage
    let inputWidth: Int = CGImageGetWidth(inputCGImage)
    let inputHeight: Int = CGImageGetHeight(inputCGImage)

    // Get the colorspace that will be used for image processing (RGB/HSV)
    let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()!

    // Hardcode memory variables
    let bytesPerPixel = 4 // 32 bits = 4 bytes
    let bitsPerComponent = 8 // 32 bits div. by 4 components (RGBA) = 8 bits per component
    let inputBytesPerRow = bytesPerPixel * inputWidth

    // Get a pointer pointing to an allocated array to hold all the pixel data of the image
    let inputPixels = UnsafeMutablePointer<UInt32>(calloc(inputHeight * inputWidth, sizeof(UInt32)))

    // Create a context to draw the original image in (aka put the pixel data into the above array)
    let context: CGContextRef = CGBitmapContextCreate(inputPixels, inputWidth, inputHeight, bitsPerComponent, inputBytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Big.rawValue)!

    CGContextDrawImage(context, CGRect(x: 0, y: 0, width: inputWidth, height: inputHeight), inputCGImage)

Keep in mind this is not Swift 3 syntax incase that's what you're using, but that's the basic algorithm. Now to grab the individual color values of each pixel, you will have to implement these functions -

func Mask8(x: UInt32) -> UInt32
    return x & 0xFF

func R(x: UInt32) -> UInt32
    return Mask8(x)

func G(x: UInt32) -> UInt32
    return Mask8(x >> 8)

func B(x: UInt32) -> UInt32
    return Mask8(x >> 16)

func A(x: UInt32) -> UInt32
    return Mask8(x >> 24)

To create a completely new color after processing the RGBA values, you use this function -

func RGBAMake(r: UInt32, g: UInt32, b: UInt32, a: UInt32) -> UInt32
    return (Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24)

To iterate through the pixels array, you do it as so -

var currentPixel = inputPixels
for _ in 0..<height
        for i in 0..<width
            let color: UInt32 = currentPixel.memory
            if i < width - 1
                print(NSString(format: "%3.0f", R(x: color), terminator: " "))
                print(NSString(format: "%3.0f", R(x: color)))
            currentPixel += 1