Skip to content

Instantly share code, notes, and snippets.

@Tricertops
Last active January 26, 2019 05:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tricertops/6474123 to your computer and use it in GitHub Desktop.
Save Tricertops/6474123 to your computer and use it in GitHub Desktop.
UIImage method that makes color histogram from the image and sort them by number of occurences. Clone and edit for your specific purpose.
- (NSMutableData *)mutableRGBAData {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGSize scaledSize = (CGSize){
.width = self.size.width * self.scale,
.height = self.size.height * self.scale,
};
NSUInteger const bytesPerPixel = 4;
NSUInteger const bitsPerComponent = 8;
NSUInteger const bytesPerRow = bytesPerPixel * scaledSize.width;
NSMutableData *bitmap = [[NSMutableData alloc] initWithLength:scaledSize.height * scaledSize.width * bytesPerPixel];
CGContextRef context = CGBitmapContextCreate(bitmap.mutableBytes,
scaledSize.width, scaledSize.height,
bitsPerComponent, bytesPerRow,
colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGRect rect = (CGRect) {
.origin = CGPointZero,
.size = scaledSize,
};
CGContextDrawImage(context, rect, self.CGImage);
CGColorSpaceRelease(colorSpace), colorSpace = NULL;
CGContextRelease(context), context = NULL;
return bitmap;
}
- (void)loadMostUsedColors {
NSData *bitmap = [self mutableRGBAData];
const unsigned char *bytes = bitmap.bytes;
NSCountedSet *colorHistogram = [[NSCountedSet alloc] initWithCapacity:32];
for (NSUInteger index = 0; index < bitmap.length; index += 4) {
UIColor *pixelColor = [UIColor colorWithRed:bytes[index + 0] / 255.
green:bytes[index + 1] / 255.
blue:bytes[index + 2] / 255.
alpha:1];
[colorHistogram addObject:pixelColor];
}
CGSize scaledSize = (CGSize){
.width = self.size.width * self.scale,
.height = self.size.height * self.scale,
};
NSUInteger minimalOccurence = (scaledSize.width * scaledSize.height) / 100; // 1 %
NSMutableDictionary *colorToOccurence = [[NSMutableDictionary alloc] initWithCapacity:colorHistogram.count];
for (UIColor *color in colorHistogram) {
NSUInteger occurence = [colorHistogram countForObject:color];
if (occurence >= minimalOccurence) {
[colorToOccurence setObject:@(occurence) forKey:color];
}
}
NSArray *mostUsedColors = [[[colorToOccurence keysSortedByValueUsingSelector:@selector(compare:)] reverseObjectEnumerator] allObjects];
// `mostUsedColors` is an array of colors with more than 1% share of the image
// `colorToOccurence` is a dictionary with UIColor keys and their number of occurences as values
}
@Tricertops
Copy link
Author

To incorporate some tolerance or average, you may want to add some rounding to the raw values and/or use different storage type, than plain counted set.

@Tricertops
Copy link
Author

Note: Transparent pixel in image will result in black color. Edit the code for your needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment