title: Fastest way to calculate average RGB pixel value for AVCaptureVideoDataOutput feed - CPU/GPU
body: <p>I want the average pixel value for the entire image in the feed from AVCaptureVideoDataOutput, and I'm currently catching the image and looping through pixels to sum them.</p>
  
  <p>I was wondering if there's a more efficient way to do this with the GPU/openGL, given that this is a parallelisable image processing task. (perhaps a heavy gaussian blur, and read the central pixel value?)</p>
  
  <p>One specific requirement is for a high precision result, making use of the high level of averaging. Note the CGFloat result below.</p>
  
  <h2>Current swift 2 code:</h2>
  
  <p>Edit: Added an implementation with CIAreaAverage, as suggested below by Simon. It's separated by the <code>useGPU</code> bool.</p>
  
  <pre><code>func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
  
      var redmean:CGFloat = 0.0;
      var greenmean:CGFloat = 0.0;
      var bluemean:CGFloat = 0.0;
  
      if (useGPU) {
              let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
              let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)
              let filter = CIFilter(name: "CIAreaAverage")
              filter!.setValue(cameraImage, forKey: kCIInputImageKey)
              let outputImage = filter!.valueForKey(kCIOutputImageKey) as! CIImage!
  
              let ctx = CIContext(options:nil)
              let cgImage = ctx.createCGImage(outputImage, fromRect:outputImage.extent)
  
              let rawData:NSData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage))!
              let pixels = UnsafePointer&lt;UInt8&gt;(rawData.bytes)
              let bytes = UnsafeBufferPointer&lt;UInt8&gt;(start:pixels, count:rawData.length)
              var BGRA_index = 0
              for pixel in UnsafeBufferPointer(start: bytes.baseAddress, count: bytes.count) {
                  switch BGRA_index {
                  case 0:
                      bluemean = CGFloat (pixel)
                  case 1:
                      greenmean = CGFloat (pixel)
                  case 2:
                      redmean = CGFloat (pixel)
                  case 3:
                      break
                  default:
                      break
                  }
                  BGRA_index++
  
              }
       } else {
              let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
              CVPixelBufferLockBaseAddress(imageBuffer!, 0)
  
              let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer!, 0)
              let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
              let width = CVPixelBufferGetWidth(imageBuffer!)
              let height = CVPixelBufferGetHeight(imageBuffer!)
              let colorSpace = CGColorSpaceCreateDeviceRGB()
  
              let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue).rawValue | CGBitmapInfo.ByteOrder32Little.rawValue
  
              let context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo)
              let imageRef = CGBitmapContextCreateImage(context)
              CVPixelBufferUnlockBaseAddress(imageBuffer!, 0)
              let data:NSData = CGDataProviderCopyData(CGImageGetDataProvider(imageRef))!
              let pixels = UnsafePointer&lt;UInt8&gt;(data.bytes)
              let bytes = UnsafeBufferPointer&lt;UInt8&gt;(start:pixels, count:data.length)
              var redsum:CGFloat = 0
              var greensum:CGFloat  = 0
              var bluesum:CGFloat  = 0
              var BGRA_index = 0
              for pixel in UnsafeBufferPointer(start: bytes.baseAddress, count: bytes.count) {
              switch BGRA_index {
              case 0:
                  bluesum += CGFloat (pixel)
              case 1:
                  greensum += CGFloat (pixel)
              case 2:
                  redsum += CGFloat (pixel)
              case 3:
                  //alphasum += UInt64(pixel)
                  break
              default:
                  break
              }
  
              BGRA_index += 1
              if BGRA_index == 4 { BGRA_index = 0 }
          }
          redmean = redsum / CGFloat(bytes.count)
          greenmean = greensum / CGFloat(bytes.count)
          bluemean = bluesum / CGFloat(bytes.count)            
          }
  
  print("R:\(redmean) G:\(greenmean) B:\(bluemean)")
  </code></pre>