Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise operations with CGBitmapInfo and CGImageAlphaInfo

I'm having trouble performing bitwise operations with CGImageAlphaInfo and CGBitmapInfo in Swift.

In particular, I don't know how to port this Objective-C code:

bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaNoneSkipFirst;

The following straightforward Swift port produces the somewhat cryptic compiler error 'CGBitmapInfo' is not identical to 'Bool' on the last line:

bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGImageAlphaInfo.NoneSkipFirst

Looking at the source code I noticed that CGBitmapInfo is declared as a RawOptionSetType while CGImageAlphaInfo isn't. Maybe this has something to do with it?

It doesn't help that the official documentation on bitwise operators doesn't cover enums.

like image 494
hpique Avatar asked Sep 10 '14 19:09

hpique


3 Answers

You have the right equivalent Swift code:

bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(CGImageAlphaInfo.NoneSkipFirst.rawValue)

It's a little strange because CGImageAlphaInfo isn't actually a bitmask -- it's just a UInt32 enum (or a CF_ENUM/NS_ENUM with type uint32_t, in C parlance), with values for 0 through 7.

What's actually happening is that your first line clears the first five bits of bitmapInfo, which is a bitmask (aka RawOptionSetType in Swift), since CGBitmapInfo.AlphaInfoMask is 31, or 0b11111. Then your second line sticks the raw value of the CGImageAlphaInfo enum into those cleared bits.

I haven't seen enums and bitmasks combined like this anywhere else, if that explains why there isn't really documentation. Since CGImageAlphaInfo is an enum, its values are mutually exclusive. This wouldn't make any sense:

bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(CGImageAlphaInfo.NoneSkipFirst.rawValue)
bitmapInfo |= CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue)
like image 58
Nate Cook Avatar answered Nov 02 '22 00:11

Nate Cook


As of Swift 3, Xcode 8 Beta 5, the syntax (as JackPearse pointed out, it conforms to OptionSetType protocol) is changed again and we no longer need ~CGBitmapInfo.AlphaInfoMask.rawValue, instead we just use

let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.last.rawValue)

You can add other bitmap info settings via the | operator, e.g.

let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.first.rawValue)
like image 40
CodeBrew Avatar answered Nov 02 '22 02:11

CodeBrew


Turns out that CGImageAlphaInfo values need to be converted to CGBitmapInfo in order to perform bitwise operations. This can be done like this:

bitmapInfo &= ~CGBitmapInfo.AlphaInfoMask
bitmapInfo |= CGBitmapInfo(CGImageAlphaInfo.NoneSkipFirst.rawValue)
like image 1
hpique Avatar answered Nov 02 '22 02:11

hpique