Swift从图像文件获取像素数组时索引超1000后值为0问题求助
问题原因分析
核心错误是像素坐标转一维数组索引的计算公式错误:
你当前代码中给红、绿、蓝、alpha数组赋值时使用的索引是x + y,对于512×512的图像来说,x和y的取值范围都是0~511,二者相加的最大值仅为 511 + 511 = 1022,也就是说你只给数组前1023个索引的位置赋了有效值,索引≥1023的位置一直保留初始化时的默认值0,这就是你看到索引超过1000后数值全为0的直接原因。
修复方案
- 替换为正确的一维索引计算公式:对于宽度为
width的图像,坐标(x,y)对应的一维数组索引应为y * width + x - 补充手动分配的像素指针内存释放逻辑,避免内存泄漏
- 调整循环顺序为外层遍历行y、内层遍历列x,更符合常规图像存储的顺序逻辑
修复后的代码如下:
func forLoopWay() -> [[UInt8]] { let startTime = CFAbsoluteTimeGetCurrent() print("for loop way") let Image = UIImage(named: imageName) let image: CGImage = Image!.cgImage! let width = image.width let height = image.height let colorspace = CGColorSpaceCreateDeviceRGB() let bytesPerRow = (4 * width); let bitsPerComponent = 8 // 保存初始指针地址,后续用于释放内存 let pixelsStart = UnsafeMutablePointer<UInt8>.allocate(capacity: width * height * 4 ) var pixels = pixelsStart let context = CGContext.init(data: pixels, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorspace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) context?.draw(image, in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))) var alpha = [UInt8].init(repeating: 0, count: width * height) var red = [UInt8].init(repeating: 0, count: width * height) var green = [UInt8].init(repeating: 0, count: width * height) var blue = [UInt8].init(repeating: 0, count: width * height) let test_val = pixels.pointee print(test_val) print(pixels.pointee) // 调整循环顺序,外层遍历行y,内层遍历列x for y in 0..<height { for x in 0..<width { // 使用正确的索引计算公式 let index = y * width + x red[index] = pixels.pointee pixels += 1 green[index] = pixels.pointee pixels += 1 blue[index] = pixels.pointee pixels += 1 alpha[index] = pixels.pointee pixels += 1 } } // 释放手动分配的内存 pixelsStart.deallocate() let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime print("Time elapsed \(String(format : "%0.5f", timeElapsed)) seconds") print() return [red, green, blue, alpha] }
内容的提问来源于stack exchange,提问作者KleinerWarden
相关产品推荐
相关产品推荐

