How to do comparisons of bitmaps in iOS?

2020-04-16 18:07发布

问题:

I have three CGLayers who's data I'd like to compare.

void *a = CGBitmapContextGetData(CGLayerGetContext(layerA));
void *b = CGBitmapContextGetData(CGLayerGetContext(layerB));
void *c = CGBitmapContextGetData(CGLayerGetContext(layerC));

I'd like to get a result like ((a OR b) AND c) where only bits that are on in layerA or layerB and also on in layerC end up in the result. These layers are kCGImageAlphaOnly so they are only 8 bits "deep", and I've only drawn into them with 1.0 alpha. I also don't need to know where the overlap lies, I just need to know whether there are any bits on in the result.

I'm really missing QuickDraw today, it had plenty of bit-oriented operations that were very speedy. Any thoughts on how to accomplish something like this?

回答1:

Here's a naive implementation, assuming all three are the same size:

unsigned char *a = CGBitmapContextGetData(CGLayerGetContext(layerA));
unsigned char *b = CGBitmapContextGetData(CGLayerGetContext(layerB));
CGContextRef context = CGLayerGetContext(layerC);
unsigned char *c = CGBitmapContextGetData(context);
size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);
size_t height = CGBitmapContextGetHeight(context);
size_t len = bytesPerRow * height;
BOOL bitsFound = NO;
for (int i = 0; i < len; i++) {
    if ((a[i] | b[i]) & c[i]) { bitsFound = YES; break; }
}

Since you're hankering for QuickDraw, I assume you could have written that yourself, and you know that will probably be slow.

If you can guarantee the bitmap sizes, you could use int instead of char and operate on four bytes at a time.

For more serious optimization, you should check out the Accelerate framework.



回答2:

What about the CGBlendModes? kCGBlendModeDestinationOver acts as OR for A and B, and then you can use kCGBlendModeDestinationIn to AND that result with C.