Есть ли более быстрый способ сравнить объекты NSBitmapImageRep попиксельно?

Я пытаюсь ускорить некоторый код, который я написал некоторое время назад.

Используя инструменты в Xcode, я обнаружил, что основным узким местом является этот метод, в частности, вызов getPixel.

- (BOOL)fasterCompareImage:(NSBitmapImageRep *)imageRepA IdenticalTo:(NSBitmapImageRep *)imageRepB {

    // look for obvious differences ie: width and height differences...
    NSSize imageASize = [imageRepA size];
    NSSize imageBSize = [imageRepB size];
    if( (imageASize.width != imageBSize.width) || (imageASize.height != imageBSize.height) ) {
        return NO;
    }

    // now start looking at each point
    NSUInteger pixelOfA[3];  
    NSUInteger pixelOfB[3];  

    for (int row = 0; row < (imageASize.height); row = row +1) { 
        for(int col = 0; col < (imageASize.width); col = col +1) { 
            [imageRepA getPixel:pixelOfA atX:row y:col];
            [imageRepB getPixel:pixelOfB atX:row y:col];

            if(pixelOfA[1] != pixelOfB[1]) {  
                return NO;
            }
        }
    }

    return YES;
}

По сути, мой метод берет два объекта NSBitmapImageRep и сравнивает их попиксельно, чтобы найти различия.

Есть ли у кого-нибудь какие-либо советы по коду или, возможно, другой подход?


person Monty    schedule 23.10.2013    source источник


Ответы (1)


Монти, когда вы используете интенсивные циклы, как вы, вы не должны использовать много вызовов obj-c.

NSBitmapImageRep содержит ссылку на CGImage. И вы можете использовать CFEqual для сравнения двух CFStruct, которыми является CGImage. После этого вам просто нужно скрестить пальцы, что равенство в CGImage касается пикселя, канала, растровой информации и многого другого ... Я не знаю, что концептуально два одинаковых изображения идентичны. Но у вас есть много инструментов, чтобы делать то, что вы хотите.

Извините, если это на самом деле не ответ, но я даю вам большие подсказки о том, как вы должны достичь того, чего хотите.

person Mr Bonjour    schedule 23.10.2013
comment
Спасибо, мистер Бонжур. Я рассмотрю некоторые из ваших предложений в ближайшие несколько дней и доложу. Цените указатели :) - person Monty; 24.10.2013
comment
Привет, мистер Бонжур, я исследовал использование CGImageRef, как было предложено, и скорость удвоилась :) Я не смог заставить работать CFEqual, поэтому вместо этого сравнивал байты в каждом CGImageRef, который фактически хранится в CFDataRef (внутри CGImageRef). Получение CFDataRef для сравнения байтов — очень дорогая операция. Для этого я использую функцию CGDataProviderCopyData(...). Можете ли вы предложить другой способ или объяснить, как я могу использовать CFEqual для сравнения CGImages? - person Monty; 01.11.2013
comment
Хорошо, теперь я понимаю, почему CFEqual не работает. Это связано с тем, что существуют другие атрибуты, отличные от данных пикселей, хранящихся в CGImageRef (например, bitsPerPixel), и CFEqual сравнивает их все. Для тех, кто ищет действительно быстрый способ сравнения изображений, используйте «объекты» CFImageRef, а не их аналоги NS... и вызовите CFEqual для их сравнения. Убедитесь, что вы понимаете, что CFEqual будет сравнивать все атрибуты, а не только данные пикселей. Спасибо, мистер Бонжур, вы направили меня в правильном направлении :) - person Monty; 01.11.2013