Arrays Swift:由于某种原因导致代码崩溃

Arrays Swift:由于某种原因导致代码崩溃,arrays,swift,uiimage,unsafemutablepointer,Arrays,Swift,Uiimage,Unsafemutablepointer,我是Swift的新手,我正在网上学习一门课程,但不幸的是他们没有回答我的问题。我相信答案很简单,但因为我是初学者,我希望这里的人能回答我 import UIKit public struct Pixel { public var value: UInt32 = 0 public init() { } public var red: UInt8 { get { return UInt8(value & 0xFF)

我是Swift的新手,我正在网上学习一门课程,但不幸的是他们没有回答我的问题。我相信答案很简单,但因为我是初学者,我希望这里的人能回答我

import UIKit

public struct Pixel {
    public var value: UInt32 = 0

    public init() { }
    public var red: UInt8 {
        get {
            return UInt8(value & 0xFF)
        }
        set {
            value = UInt32(newValue) | (value & 0xFFFFFF00)
        }
    }

    public var green: UInt8 {
        get {
            return UInt8((value >> 8) & 0xFF)
        }
        set {
            value = (UInt32(newValue) << 8) | (value & 0xFFFF00FF)
        }
    }

    public var blue: UInt8 {
        get {
            return UInt8((value >> 16) & 0xFF)
        }
        set {
            value = (UInt32(newValue) << 16) | (value & 0xFF00FFFF)
        }
    }

    public var alpha: UInt8 {
        get {
            return UInt8((value >> 24) & 0xFF)
        }
        set {
            value = (UInt32(newValue) << 24) | (value & 0x00FFFFFF)
        }
    }
}

public class RGBAImage
{
    public var pixels: [Pixel]

    public var width: Int
    public var height: Int
    private var imageData: UnsafeMutablePointer<Pixel>

    public init?(image: UIImage) {
        guard let cgImage = image.cgImage else { return nil }

        // Redraw image for correct pixel format
        let colorSpace = CGColorSpaceCreateDeviceRGB()

        var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue
        bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue

        width = Int(image.size.width)
        height = Int(image.size.height)
        let bytesPerRow = width * 4

        imageData = UnsafeMutablePointer<Pixel>.allocate(capacity: width * height)

        guard let imageContext = CGContext.init(data: imageData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { return nil }
        imageContext.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: image.size))

        let bufferPointer = UnsafeMutableBufferPointer<Pixel>(start: imageData, count: width * height)
        pixels = Array(bufferPointer) // <-- is this creating a copy of that bufferPointer contents or a reference?

        imageData.deinitialize(count: width * height) // <-- I tried commenting out this code, so not to free the memory but to no avail. I am not sure if the previous line copied the buffer or kept a reference to it
    }

    public func toUIImage() -> UIImage? {
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue
        bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue

        let bytesPerRow = width * 4

        let imageDataReference = UnsafeMutablePointer<Pixel>(mutating: pixels)
        defer {
            imageDataReference.deinitialize(count: width * height)
        }
        let imageContext = CGContext(data: imageDataReference, width: width, height: height, bitsPerComponent: 8, 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
    }
}

// Pixel visitor callback
public typealias PixelVisitor = (_ pixel: inout Pixel, _ args: AnyObject?) -> Void

public class ImageProcessor
{
    private var rgb_img: RGBAImage

    public init(img: UIImage) {
        rgb_img = RGBAImage(image: img)!
    }

    public func Pixels() -> [Pixel] {
        return rgb_img.pixels
    }

    public var width: Int {
        get {
            return rgb_img.width
        }
    }

    public var height: Int {
        get {
            return rgb_img.height
        }
    }

    public func visitPixels(_ callback: PixelVisitor, _ args: AnyObject?) {
        for y in 0..<self.rgb_img.height {
            let base = y * rgb_img.width
            for x in 0..<self.rgb_img.width {
                let index = base + x;
                var pixel = rgb_img.pixels[index]
                pixel.value += 0x202020 // <--- causing crash at index == 8?!
                //callback(&pixel, args)
            }
        }
    }

    public func toUIImage() -> UIImage? {
        return self.rgb_img.toUIImage()
    }
}

我做错了什么?

避免溢出的最简单方法是允许swift这么做

let res = pixel.value.addingReportingOverflow(0x202020)
pixel.value = res.partialValue
而不是你的崩溃线


如果您想处理溢出,并在这种情况下使像素为白色/黑色/红色/其他任何颜色-在我的示例中,您可以通过res上的溢出属性来检查它

它崩溃的错误消息是什么?可能是整数溢出。在添加
0x202020
并崩溃之前,什么是
pixel.value
?对我来说很好,有一张200x200的图像。@MartinR你会将
value
从a
UInt32
更改为
UInt64
?@Adrian:
pixel.value
是一个32位整数,每个颜色分量(r,g,b,a)有一个字节,并直接对应于位图的内存表示。更改类型没有帮助,必须以某种方式处理溢出。如果您不关心溢出标志值,为什么不使用运算符呢?它也短路了。
let res = pixel.value.addingReportingOverflow(0x202020)
pixel.value = res.partialValue