确定UIImage的主要和次要颜色

我想知道如果有人能帮我弄清楚如何确定UIImage中的主要和次要颜色。 我一直无法在Google中find非常有用的东西。

Panic的工程师写了一个algorithm来进行类似iTunes 11中的颜色分析(以确定好的主色,次色和细节色)。 他们在他们的博客上发布了一个关于它是如何工作和代码的解释。

在这里输入图像说明

基于上面的恐慌博客,这是一个快速的方法(<10ms取决于variables)。

采取UIImageinput和输出:

  • 背景色
  • 原色
  • 二次色

当将UIImage传递给方法时,也传递一个“边”。 这是指图像的哪个部分暴露在视图的其余部分(请参阅下面的图像以获得澄清):

  • 边缘= 0 =顶部
  • 边= 1 =左边
  • 边= 2 =底
  • 边缘= 3 =正确

**

步骤1。

**设定尺寸。 这是指图像上下多less像素应该是。

步骤2.根据尺寸input调整图像大小(例如20 x 20 = 400px)。

第3步。创build一个颜色数组,从第2步中创build的原始数据中提取RGB值。另外收集沿所选边缘运行的像素。

步骤4.计算边缘或背景颜色。 稍后用于对比重音颜色,根据恐慌博客。

第5步。通过收集的颜色(RGB值),并确定它们是否与边缘/背景颜色充分对比。 如果不这样做,所需的最小对比度会降低。 而且,对于每个颜色对象,将其“距离”设置为其他颜色。 这是对颜色与图像中其他颜色的相似程度的粗略估计。

步骤6.按距离sorting(最短距离意味着最相似),最上面出现最相似的颜色。 将最常用的颜色设置为主要颜色。

第7步。通过其余的颜色,并确定与原色最重要的对比。 然后设置你的第二色。

警告:我相信这种方法可以改进,但这是一个快速的起点。 例如,您可以确定图像右上angular或左上angular的像素颜色(往往放置后面的图标等),并为图标上的图标提供对比颜色。

代码如下:

-(NSDictionary *)coloursForImage:(UIImage *)image forEdge:(int)edge { NSLog(@"start"); //1. set vars float dimension = 20; //2. resize image and grab raw data //this part pulls the raw data from the image CGImageRef imageRef = [image CGImage]; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char *rawData = (unsigned char*) calloc(dimension * dimension * 4, sizeof(unsigned char)); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * dimension; NSUInteger bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, dimension, dimension, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, dimension, dimension), imageRef); CGContextRelease(context); //3. create colour array NSMutableArray * colours = [NSMutableArray new]; float x = 0, y = 0; //used to set coordinates float eR = 0, eB = 0, eG = 0; //used for mean edge colour for (int n = 0; n<(dimension*dimension); n++){ Colour * c = [Colour new]; //create colour int i = (bytesPerRow * y) + x * bytesPerPixel; //pull index cr = rawData[i]; //set red cg = rawData[i + 1]; //set green cb = rawData[i + 2]; //set blue [colours addObject:c]; //add colour //add to edge if true if ((edge == 0 && y == 0) || //top (edge == 1 && x == 0) || //left (edge == 2 && y == dimension-1) || //bottom (edge == 3 && x == dimension-1)){ //right eR+=cr; eG+=cg; eB+=cb; //add the colours } //update pixel coordinate x = (x == dimension - 1) ? 0 : x+1; y = (x == 0) ? y+1 : y; } free(rawData); //4. calculate edge colour Colour * e = [Colour new]; er = eR/dimension; eg = eG/dimension; eb = eB/dimension; //5. calculate the frequency of colour NSMutableArray * accents = [NSMutableArray new]; //holds valid accents float minContrast = 3.1; //play with this value while (accents.count < 3) { //minimum number of accents for (Colour * a in colours){ //NSLog(@"contrast value is %f", [self contrastValueFor:a andB:e]); //5.1 ignore if it does not contrast with edge if ([self contrastValueFor:a andB:e] < minContrast){ continue;} //5.2 set distance (frequency) for (Colour * b in colours){ ad += [self colourDistance:a andB:b]; } //5.3 add colour to accents [accents addObject:a]; } minContrast-=0.1f; } //6. sort colours by the most common NSArray * sorted = [[NSArray arrayWithArray:accents] sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@"d" ascending:true]]]; //6.1 set primary colour (most common) Colour * p = sorted[0]; //7. get most contrasting colour float high = 0.0f; //the high int index = 0; //the index for (int n = 1; n < sorted.count; n++){ Colour * c = sorted[n]; float contrast = [self contrastValueFor:c andB:p]; //float sat = [self saturationValueFor:c andB:p]; if (contrast > high){ high = contrast; index = n; } } //7.1 set secondary colour (most contrasting) Colour * s = sorted[index]; NSLog(@"er %i eg %i eb %i", er, eg, eb); NSLog(@"pr %i pg %i pb %i", pr, pg, pb); NSLog(@"sr %i sg %i sb %i", sr, sg, sb); NSMutableDictionary * result = [NSMutableDictionary new]; [result setValue:[UIColor colorWithRed:er/255.0f green:eg/255.0f blue:eb/255.0f alpha:1.0f] forKey:@"background"]; [result setValue:[UIColor colorWithRed:pr/255.0f green:pg/255.0f blue:pb/255.0f alpha:1.0f] forKey:@"primary"]; [result setValue:[UIColor colorWithRed:sr/255.0f green:sg/255.0f blue:sb/255.0f alpha:1.0f] forKey:@"secondary"]; NSLog(@"end"); return result; } -(float)contrastValueFor:(Colour *)a andB:(Colour *)b { float aL = 0.2126 * ar + 0.7152 * ag + 0.0722 * ab; float bL = 0.2126 * br + 0.7152 * bg + 0.0722 * bb; return (aL>bL) ? (aL + 0.05) / (bL + 0.05) : (bL + 0.05) / (aL + 0.05); } -(float)saturationValueFor:(Colour *)a andB:(Colour *)b { float min = MIN(ar, MIN(ag, ab)); //grab min float max = MAX(br, MAX(bg, bb)); //grab max return (max - min)/max; } -(int)colourDistance:(Colour *)a andB:(Colour *)b { return abs(ar-br)+abs(ag-bg)+abs(ab-bb); } 

Color对象是一个简单的自定义类:

 @interface Colour : NSObject @property int r, g, b, d; @end