2

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?

EFC
  • 1,890
  • 18
  • 39
  • Are these images? Or are you using the Core Graphics API to manipulate some other data? – benzado Jun 29 '11 at 04:54
  • These are images in that I've "stroked" the data in with CG calls. But I don't really care whether they are compared as images or not, I'm really just trying to discover whether their is overlap between the last "c" data and the combination of the first two "a" and "b" sets. – EFC Jun 29 '11 at 04:58

2 Answers2

2

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.

benzado
  • 82,288
  • 22
  • 110
  • 138
  • Yes, I know the size and I think I can use `int` in this case, but the example is still a big help. I hadn't thought of the Accelerate framework, I'll have to see if it is available to iOS. Thanks! – EFC Jun 29 '11 at 05:20
  • By the way, you can see how I've applied this answer in a sample app I left at http://stackoverflow.com/questions/6482362/hit-detection-when-drawing-lines-in-ios/6526850#6526850 – EFC Jun 29 '11 at 20:31
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.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • That's an interesting alternative, Josh, and I'll have to give it a try. Though it may well save time in the combining of the images, I think I'd still have to walk through the result with a loop to see if anything was left "on" in there. By the time I do that, the loop @benzado suggested might be just as quick. This is especially true because that loop can short circuit with the break as soon as it finds something. I also am uncertain how this blending would work on a `kCGImageAlphaOnly` bitmaps. – EFC Jun 29 '11 at 06:26
  • Yes, I really have no idea how well or fast it would work, but the idea struck me almost immediately on reading your question, so I thought I'd throw it out there. AFAIK, the fact that they are alpha-only shouldn't be an issue; I may be wrong, though. – jscs Jun 29 '11 at 06:28
  • If this works, it will almost certainly be faster than writing a loop, since the compositing can be done by graphics hardware. I didn't suggest it since I wasn't sure that they would be bitwise equivalents. But if you're collision testing, maybe that's not important... – benzado Jun 29 '11 at 17:29