UIImage Loop Through Pixel Highly Inefficient?

匿名 (未验证) 提交于 2019-12-03 08:39:56

问题:

Currently I am using this method to loop through every pixel, and insert a value into a 3D array based upon RGB values. I need this array for other parts of my program, however it is extraordinarily slow. When run on a 50 x 50 picture, it is almost instant, but as soon as you start getting into the hundreds x hundreds it takes a long time to the point where the app is useless. Anyone have any ideas on how to speed up my method?

@IBAction func convertImage(sender: AnyObject) {     if let image = myImageView.image {          var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))         var data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)          let height = Int(image.size.height)         let width = Int(image.size.width)         var zArry = [Int](count:3, repeatedValue: 0)         var yArry = [[Int]](count:width, repeatedValue: zArry)         var xArry = [[[Int]]](count:height, repeatedValue: yArry)          for (var h = 0; h < height; h++) {             for (var w = 0; w < width; w++) {                  var pixelInfo: Int = ((Int(image.size.width) * Int(h)) + Int(w)) * 4                 var rgb = 0                 xArry[h][w][rgb] = Int(data[pixelInfo])                 rgb++                 xArry[h][w][rgb] = Int(data[pixelInfo+1])                 rgb++                 xArry[h][w][rgb] = Int(data[pixelInfo+2])                 }         }         println(xArry[20][20][1])     } } 

Maybe there is a way to convert the UIImage to a different type of image and create an array of pixels. I am open to all suggestions. Thanks!

GOAL: The goal is to use the array to modify the RGB values of all pixels, and create a new image with the modified pixels. I tried simply looping through all of the pixels without storing them, and modifying them into a new array to create an image, but got the same performance issues.

回答1:

Update:

After countless tries I realized I was making my tests on debug configuration.

Switched to release, and now it's so much faster.

Swift seems to be many times slower on the debug configuration.

The difference now between your code and my optimized version is several times faster.

It seems as you have a big slowdown from using image.size.width instead of the local variable width.

Original

I tried to optimize it a bit and come up with this:

@IBAction func convertImage () {      if let image = UIImage(named: "test") {          let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))         let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)          let height = Int(image.size.height)         let width = Int(image.size.width)         let zArry = [Int](count:3, repeatedValue: 0)         let yArry = [[Int]](count:width, repeatedValue: zArry)         let xArry = [[[Int]]](count:height, repeatedValue: yArry)          for (index, value) in xArry.enumerate() {             for (index1, value1) in value.enumerate() {                 for (index2, var value2) in value1.enumerate() {                      let pixelInfo: Int = ((width * index) + index1) * 4 + index2                      value2 = Int(data[pixelInfo])                 }             }         }     } } 

However in my tests this is barely 15% faster. What you need is orders of magnitude faster.

Another ideea is use the data object directly when you need it without creating the array like this:

let image = UIImage(named: "test")!  let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage)) let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)  let width = Int(image.size.width)  // value for [x][y][z] let value = Int(data[((width * x) + y) * 4 + z]) 

You didn't say how you use this array in your app, but I feel that even if you find a way to get this array created much faster, you would get another problem when you try to use it, as it would take a long time too..



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!