简体   繁体   English

EXC_BAD_INSTRUCTION快速抖动功能

[英]EXC_BAD_INSTRUCTION Swift Dithering Function

I've been trying to create a dithering function in Swift but I keep running into issues. 我一直在尝试在Swift中创建抖动功能,但一直遇到问题。 I've noticed the code loops just fine for the first 9000 or so pixels of a random image I selected. 我注意到代码循环对于我选择的随机图像的前9000个左右像素都很好。 But then it gives me a runtime error, I've looked everywhere and I can't seem to solve the issue. 但是,这给了我一个运行时错误,我四处张望,似乎无法解决问题。 Please help. 请帮忙。

file:///Users/jeffn/Desktop/MyPlayground34.playground/: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0). 文件:///Users/jeffn/Desktop/MyPlayground34.playground/:错误:操场执行中止:错误:执行被中断,原因:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)。 The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation. 该进程已被中断,请使用“线程返回-x”返回到表达式求值之前的状态。

   import UIKit





 struct Pixel {
var value: UInt32
var red: UInt8 {
    get { return UInt8(value & 0xFF) }
    set { value = UInt32(newValue) | (value & 0xFFFFFF00) }
}
var green: UInt8 {
    get { return UInt8((value >> 8) & 0xFF) }
    set { value = (UInt32(newValue) << 8) | (value & 0xFFFF00FF) }
}
var blue: UInt8 {
    get { return UInt8((value >> 16) & 0xFF) }
    set { value = (UInt32(newValue) << 16) | (value & 0xFF00FFFF) }
}
var alpha: UInt8 {
    get { return UInt8((value >> 24) & 0xFF) }
    set { value = (UInt32(newValue) << 24) | (value & 0x00FFFFFF) }
}}

 public struct RGBA {
var pixels: UnsafeMutableBufferPointer<Pixel>
var width: Int
var height: Int

init?(image: UIImage) {
    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(x: 0,y :0), size: image.size))
    pixels = UnsafeMutableBufferPointer<Pixel>(start: imageData, count: width * height)
}

public func toUIImage() -> UIImage? {
    let bitsPerComponent = 8
    let bytesPerPixel = 4
    let bytesPerRow = width * bytesPerPixel
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue
    bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
    let imageContext = CGContext(data: pixels.baseAddress, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo, releaseCallback: nil, releaseInfo: nil)
    guard let cgImage = imageContext!.makeImage() else {return nil}
    let image = UIImage(cgImage: cgImage)
    return image
}
}

public func contrast(image: UIImage) -> RGBA {
let rgba = RGBA(image: image)!

var new_red: UInt8 = 0
var new_green = 0
var new_blue = 0
var new_alpha = 0

var error_red: UInt8 = 0
var error_green = 0
var error_blue = 0
var error_alpha = 0

var pixel_1_red: UInt8 = 0

var output_red: UInt8 = 0

let w1: Double = 7.00/16.00
let w2: Double = 3.00/16.00
let w3: Double = 5.00/16.00
let w4: Double = 1.00/16.00


for y in 0..<rgba.height-1{
    for x in 0..<rgba.width-1{
        var index = y * rgba.width + x
        var index_1 = y*rgba.width + x + 1

        var pixel = rgba.pixels[index]
        var pixel_1 = rgba.pixels[index_1]
        pixel_1_red = pixel_1.red



        if(pixel.red < 128){new_red = 0} else {new_red = 255}
        error_red = new_red - pixel.red


        var double_error_red = Double(error_red)*w1
        var int_error_red = UInt8(double_error_red)

        output_red = pixel_1_red + int_error_red


        pixel_1.red = output_red
        rgba.pixels[index_1] = pixel_1


    }
}

return rgba
}




 let image = UIImage(named: "newlowpassfilter.jpg")!
 let rgba = contrast(image: image)
 let newImage = rgba.toUIImage()
 image

 newImage

Maybe integer overflow is your issue. 也许整数溢出是您的问题。

With testing with one of my sample jpg-image, this line caused overflow: 通过对我的一个示例jpg图像进行测试,此行导致了溢出:

output_red = pixel_1_red + int_error_red

You may need to change the line to something like this: 您可能需要将行更改为以下内容:

let temp_red = Int(pixel_1_red) + Int(int_error_red)
output_red = temp_red > 255 ? 255 : UInt8(temp_red)

In Swift, + operator detects overflow and causes app crash, and overflow ignoring operator &+ does not suit for image processing. 在Swift中, +运算符检测到溢出并导致应用崩溃,而忽略运算符&+溢出不适用于图像处理。 You may need to care about the result range of each operation in your code. 您可能需要关心代码中每个操作的结果范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM