线程 1:EXC_BAD_ACCESS(代码=EXC_I386_GPFLT)

Posted

技术标签:

【中文标题】线程 1:EXC_BAD_ACCESS(代码=EXC_I386_GPFLT)【英文标题】:Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 【发布时间】:2016-09-29 04:58:58 【问题描述】:

在我的 swift 项目中,我有两个类共同保存图像的像素值,以便能够修改红色、绿色、蓝色和 alpha 值。 UnsafeMutableBufferPointer 包含许多由 Pixel 类对象组成的位。

我可以与拥有UnsafeMutableBufferPointer<Pixel> 属性的类进行交互。我可以访问该对象的所有属性,并且一切正常。我在使用 UnsafeMutableBufferPoint<Pixel> 时遇到的唯一问题是尝试用我的 Pixel 对象循环遍历它,并且它不断因 Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 异常而崩溃。

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: CGPoint.zero, size: image.size))

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

这个函数是导致程序崩溃的部分。崩溃的确切部分是循环通过 rgba.pixels 的 for 循环。 rgba.pixels 是 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
    
        print(pixel.red)
    

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

这是我创建UnsafeMutableBufferPointer&lt;Pixel&gt; 的构造函数。有没有更简单的方法可以做到这一点,并且仍然能够获取 RBGA 值并轻松更改它们。

Pixel 类是一个UInt32 值,它分为四个UInt 8 值。

我是否使用了错误的构造来保存这些值,如果是,是否有更安全或更容易使用的构造?还是我在访问像素值时做错了什么?

【问题讨论】:

【参考方案1】:

这就是我获得图像像素的方式 -

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

请记住,这不是您使用的 Swift 3 语法,但这是基本算法。现在要获取每个像素的单独颜色值,您必须实现这些功能 -

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)

要在处理 RGBA 值后创建全新的颜色,请使用此函数 -

func RGBAMake(r: UInt32, g: UInt32, b: UInt32, a: UInt32) -> UInt32

    return (Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24)

要遍历像素数组,您可以这样做 -

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: " "))
            
            else
            
                print(NSString(format: "%3.0f", R(x: color)))
            
            currentPixel += 1
        
    

【讨论】:

以上是关于线程 1:EXC_BAD_ACCESS(代码=EXC_I386_GPFLT)的主要内容,如果未能解决你的问题,请参考以下文章

代码错误:线程 1:EXC_BAD_ACCESS(代码=1,地址=0x0)

线程1:EXC_BAD_ACCESS(代码=1,地址=0x48)avaudiofoundation

线程 1:EXC_BAD_ACCESS(代码=1,地址=0x200)

线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x30000008)

线程 1:EXC_BAD_ACCESS(代码=1,地址=0x48)

迷宫构造器问题 [线程 1:EXC_BAD_ACCESS(代码=1,地址=0x8)]