arrays - Swift:代码由于某种原因崩溃
问题描述
我是 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()
}
}
上面的代码注释中有一些问题(“<--”)。当我运行访问者时,当我尝试修改索引 == 8 处的像素时出现崩溃。
let image = UIImage(named: "sample")
var filter_man = ImageProcessor(img: image!)
filter_man.visitPixels({ (p, args) in
//p.red += 30
}, nil)
我究竟做错了什么?
解决方案
避免这种溢出的最简单方法是让 swift 做到这一点
let res = pixel.value.addingReportingOverflow(0x202020)
pixel.value = res.partialValue
而不是你的崩溃线。
如果你想处理溢出并且在这种情况下使像素为白色/黑色/红色/其他任何东西——你可以在我的示例中通过 res 上的溢出属性来检查它。
推荐阅读
- postgresql - postgresql:如何添加显示两行之间时间差的列
- audio - 将频谱图图像转换回音频
- timeserieschart - 在 Shiny 中,如何模拟和绘制随时间变化的时间序列
- html - 带有 RStudio 和 xaringan 的垂直可滚动代码
- python - Instabot 不使用烧瓶网络应用程序
- java - 如何通过 OkHttp 和 Retrofit 为 Spring 应用程序提供凭据
- c++ - ShellExecuteA - 可执行文件不会从 %appdata% 运行
- python - X 每个样本有 19257 个特征;期待 19234,同时使用 Logistic 回归 Pickle 模型进行预测
- .net - NullReferenceException:对象引用未设置为对象 .NET Core 的实例
- javascript - 达到某个值时禁用向左滚动