iOS

Binary operator '+=' cannot be applied to operands of type 'Int' and 'UInt8'

Could some please tell me what I'm supposed to write at these error points. Just the errors in the for loop. Thanks in advance.

    // this is the image buffer
    var cvimgRef:CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)
    // Lock the image buffer
    CVPixelBufferLockBaseAddress(cvimgRef, 0)
    // access the data
    var width: size_t = CVPixelBufferGetWidth(cvimgRef)
    var height:size_t = CVPixelBufferGetHeight(cvimgRef)
    // get the raw image bytes
    let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
    var bprow: size_t = CVPixelBufferGetBytesPerRow(cvimgRef)


    var r = 0
    var g = 0
    var b = 0

        for var y = 0; y < height; y++ {
            for var x = 0; x < width * 4; x += 4 {
                b += buf[x]       // error
                g += buf[x + 1]  // error
                r += buf[x + 2]  // error
            }
            buf += bprow()    // error
        }
        r /= 255 * (width*height)
        g /= 255 * (width*height)
        b /= 255 * (width*height)

1 Answer

Jayden Spring
Jayden Spring
7,881 Points

Have a look at this: https://developer.apple.com/library/ios/documentation/General/Reference/SwiftStandardLibraryReference/NumericTypes.html

If you are going to start comparing and mutating different types of numbers you need to know the difference about how they are stored and since you are working here based of a memory address knowing how a number is formed will also be useful.

You are setting width & height to a size_t which is a unsigned data type that represents a size of an object. but thats not the problem as the compiler can handle that. However what is causing a problem is when you are comparing a a UInt64 (x) to a UInt8. By default 64 bit platforms will use a UInt64 for identifier int and 32 bit use UInt32. Therefore what you need to do is set X in your for loop to type UInt8 as you know that is what the buffer conforms to.

I would suggest doing a few basic C courses online which will introduce you to the concept of buffers and integers etc.

Thanks. How did you know x was the issue and not r,g,b? So how would I do that? Like this? I'm still getting an error though with var x:UInt8 I was also getting an error with buf +=bprow so I added (UnsafeMutablePointer(UInt8)) but still no luck.

  // this is the image buffer
    var cvimgRef:CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)
    // Lock the image buffer
    CVPixelBufferLockBaseAddress(cvimgRef, 0)
    // access the data
    var width: size_t = CVPixelBufferGetWidth(cvimgRef)
    var height:size_t = CVPixelBufferGetHeight(cvimgRef)
    // get the raw image bytes
    let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
    var bprow: size_t = CVPixelBufferGetBytesPerRow(cvimgRef)


    var r = 0
    var g = 0
    var b = 0

        for var y = 0; y < height; y++ {
            for var x:UInt8 = 0; x < width * 4; x += 4 {  // error: '<' cannot be applied to operands of type 'UInt8' and 'Int'
                b += buf[x]
                g += buf[x + 1]
                r += buf[x + 2]
            }
            buf += bprow(UnsafeMutablePointer(UInt8))  // error: '(_) -> _' cannot be applied to operands of type 'UnsafeMutablePointer<UInt8>' and 'size_t'
        }
        r /= 255 * (width*height)
        g /= 255 * (width*height)
        b /= 255 * (width*height)
Jayden Spring
Jayden Spring
7,881 Points

The buffer is an UnsafeMutablePointer to a type UInt8. An unsafe pointer is one that points to a C type UInt8 hence it is marked as unsafe (you need to delcare in effect you acknowledge there are safer ways to do it). Using buffers is one of the most basic aspects of C, I could write about it for hours but Im pressed for time so I found a PPT that explains it realtivley well.

At the moment when you evaluate your for conditions you are initialising X as a UInt8 and then comparing it to an Int64 which will not evaluate. What you need to do is cast the sum and the += 4 to UInt8 (eg UInt8(width * 4))

Again the problem you have with buf and bpropw is that the CVPixelBufferGetBytesPerRow(cvimgRef) actually returns an Int64 (see here) unlike CVPixelBufferGetBaseAddress which returns an unsafemutablepointer.

So what you are essentially doing if you read your code is you have initialised R,G,B to type Int (Int64) and then when you are inside your for loop you are evaluating;

  • b which is type Int64 plus UInt8 value of location at buf position X

As you can see logically that wont evaluate as you are comparing two different data types, it is a bit like tying to do 3028 * "223" - just wouldn't work. If you set rgb to UInt8 it should get rid of these compiler errors.

As for youre last error, you have initialized bprow as a size_t which is basically an unsigned integer at C level. have a look here. In this case you dont need to case it as an UnsafeMutablePointer since the method has returned something already you simply just want to cast it.

Hope this helps.

Thanks.