Fastest way to check if NSImage is a template image

Viewed 39

Let's say you have a NSImage with NSBitmapImageRep (raster image) of 16x16 pixels. It can be a color image or contain only black pixels with alpha channel.

When it only has black pixels, I can set .isTemplate for the NSImage and handle it correspondingly.

The question is - how do you quickly detect it has black pixels only?

What is the fastest way to check if provided image is a template?

Here is how I do it. It works, but requires moving through all the pixels and check them one-by-one. Even with 16x16 size it takes about a second for 10-20 images to process. So I am looking for a more optimized approach:

+ (BOOL)detectImageIsTemplate:(NSImage *)image
{
    BOOL result = NO;
    
    if (image)
    {
        // If we have a valid image, assume it's a template until we face any non-black pixel
        result = YES;
        
        NSSize imageSize = image.size;
        NSRect imageRect = NSMakeRect(0, 0, imageSize.width, imageSize.height);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
        
        CGContextRef ctx = CGBitmapContextCreate(NULL,
                                                 imageSize.width,
                                                 imageSize.height,
                                                 8,
                                                 0,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast);
        
        NSGraphicsContext* gctx = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:NO];
        [NSGraphicsContext setCurrentContext:gctx];
        [image drawInRect:imageRect];
        
        // ......................................................
        
        size_t width = CGBitmapContextGetWidth(ctx);
        size_t height = CGBitmapContextGetHeight(ctx);

        uint32_t* pixel = (uint32_t*)CGBitmapContextGetData(ctx);

        for (unsigned y = 0; y < height; y++)
        {
            for (unsigned x = 0; x < width; x++)
            {
                uint32_t rgba = *pixel;

                uint8_t red   = (rgba & 0x000000ff) >> 0;
                uint8_t green = (rgba & 0x0000ff00) >> 8;
                uint8_t blue  = (rgba & 0x00ff0000) >> 16;
                
                if (red != 0 || green != 0 || blue != 0)
                {
                    result = NO;
                    break;
                }

                pixel++; // Next pixel
            }
            
            if (result == NO) break;
        }
        
        // ......................................................
        
        [NSGraphicsContext setCurrentContext:nil];
        CGContextRelease(ctx);
        CGColorSpaceRelease(colorSpace);
    }
    
    return result;
}
1 Answers

Pure black images are in your category, is color image or only pixels with alpha channel? Why not judge the image type by the number of channels? RGBX or only A.

Related