NSBitmapImageRep:colorAtX:y返回NSColor在堆上不断增长

时间:2014-07-04 01:28:10

标签: cocoa core-graphics

我正在比较具有相同宽度和高度的两个图像之间的“颜色距离”,看它们有多相似 - 相似度的衡量标准只是逐个像素地比较它们,看看每个颜色通道的距离是多少彼此。

- (NSNumber*) calculateFitness:(NSImage*)currentImage 
              andDestinationImage:(NSImage*)destinationImage {
NSData  *tiffData = [currentImage TIFFRepresentation];
NSBitmapImageRep *currentImageRep = [NSBitmapImageRep 
                                     imageRepWithData:tiffData];

NSData *destinationImageTiffData = [destinationImage TIFFRepresentation];
NSBitmapImageRep *destinationImageRep = [NSBitmapImageRep  imageRepWithData:destinationImageTiffData];

long fitnessScore = 0;

for (int width = 0; width < currentImageRep.size.width; width++) {
    for (int height = 0; height < currentImageRep.size.height; height++) {
        NSColor *destinationColor = [destinationImageRep colorAtX:width y:height];
        NSColor *currentColor = [currentImageRep.size.height colorAtX:width y:height];

        CGFloat deltaRed = (currentColor.redComponent - destinationColor.redComponent) * 255;
        CGFloat deltaGreen = (currentColor.greenComponent - destinationColor.greenComponent) * 255;
        CGFloat deltaBlue = (currentColor.blueComponent - destinationColor.blueComponent) * 255;

        fitnessScore += (deltaRed * deltaRed) +
                        (deltaGreen * deltaGreen) +
                        (deltaBlue * deltaBlue);

        }
    }
}

我在程序中多次调用此方法来比较数千个图像的适合度。我在仪器中注意到的是,生活的NSCalibratedRGBColor对象的数量不断增长,这是由于destinationColorcurrentColor对象是使用上面的NSBitmapImageRep:colorAtX:y创建的。最终,我的整个系统内存将被消耗。

那么 - 这是否有原因发生?我究竟做错了什么?有没有更有效的方法来获取我的图像的原始位图数据?

感谢
穆斯塔法

1 个答案:

答案 0 :(得分:3)

使用原始位图数据可能会获得更好的性能。如果您浏览所有图像数据,NSBitmapImageRep的-colorAtX:y:(和-getPixel:atX:y)会非常慢。此外,所有分配的NSColors都将保留在自动释放池中,直到您的应用程序返回主循环。

unsigned char *currentData = [currentImageRep bitmapData];
unsigned char *destinationData = [destinationImageRep bitmapData];

NSUInteger width = [currentImageRep pixelWidth];
NSUInteger height = [currentImageRep pixelHeight];
NSUInteger currentBytesPerRow = [currentImageRep bytesPerRow];
NSUInteger destBytesPerRow = [destinationImageRep bytesPerRow];

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        unsigned char *srcPixel = currentData + ((x * 4) + (y * currentBytesPerRow));
        unsigned char *destPixel = destinationData + ((x * 4) + (y * destBytesPerRow));

        char sr, sg, sb;
        char dr, dg, db;

        sr = *srcPixel;
        sg = *(srcPixel + 1);
        sb = *(srcPixel + 2);

        dr = *destPixel;
        dg = *(destPixel + 1);
        db = *(destPixel + 2);

        CGFloat deltaRed = (sr - dr);
        CGFloat deltaGreen = (sg - dg);
        CGFloat deltaBlue = (sb - db);

        fitnessScore += (deltaRed * deltaRed) +
                        (deltaGreen * deltaGreen) +
                        (deltaBlue * deltaBlue);
    }
}

我写了https://medium.com/@iainx/fast-colour-analysis-d8b6422c1135来进行快速颜色分析,这是我发现的事情之一。