Objective-c – 获取图像中最less使用和最常用的颜色

我试图获得最less使用的颜色,并从MP3文件的专辑图稿中最常用的颜色为音乐播放应用程序。 我需要颜色来做一个像新的itunes 11一样的效果。菜单的背景颜色是最常用的颜色,最less使用的颜色是歌曲标签和艺术家名称的颜色。 我在用

`- (UIColor*) getPixelColorAtLocation:(CGPoint)point { UIColor* color = nil; CGImageRef inImage = self.image.CGImage; // Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage]; if (cgctx == NULL) { return nil; /* error */ } size_t w = CGImageGetWidth(inImage); size_t h = CGImageGetHeight(inImage); CGRect rect = {{0,0},{w,h}}; // Draw the image to the bitmap context. Once we draw, the memory // allocated for the context for rendering will then contain the // raw image data in the specified color space. CGContextDrawImage(cgctx, rect, inImage); // Now we can get a pointer to the image data associated with the bitmap // context. unsigned char* data = CGBitmapContextGetData (cgctx); if (data != NULL) { //offset locates the pixel in the data from x,y. //4 for 4 bytes of data per pixel, w is width of one row of data. int offset = 4*((w*round(point.y))+round(point.x)); int alpha = data[offset]; int red = data[offset+1]; int green = data[offset+2]; int blue = data[offset+3]; NSLog(@"offset: %i colors: RGB A %i %i %i %i",offset,red,green,blue,alpha); color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)]; } // When finished, release the context CGContextRelease(cgctx); // Free image data memory for the context if (data) { free(data); } return color; } - (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; // Get image width, height. We'll use the entire image. size_t pixelsWide = CGImageGetWidth(inImage); size_t pixelsHigh = CGImageGetHeight(inImage); // Declare the number of bytes per row. Each pixel in the bitmap in this // example is represented by 4 bytes; 8 bits each of red, green, blue, and // alpha. bitmapBytesPerRow = (pixelsWide * 4); bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); // Use the generic RGB color space. colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); if (colorSpace == NULL) { fprintf(stderr, "Error allocating color space\n"); return NULL; } // Allocate memory for image data. This is the destination in memory // where any drawing to the bitmap context will be rendered. bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { fprintf (stderr, "Memory not allocated!"); CGColorSpaceRelease( colorSpace ); return NULL; } // Create the bitmap context. We want pre-multiplied ARGB, 8-bits // per component. Regardless of what the source image format is // (CMYK, Grayscale, and so on) it will be converted over to the format // specified here by CGBitmapContextCreate. context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, // bits per component bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst); if (context == NULL) { free (bitmapData); fprintf (stderr, "Context not created!"); } // Make sure and release colorspace before returning CGColorSpaceRelease( colorSpace ); return context; }` 

获取图像底部的颜色,使其融入我的视图控制器中,该控制器使用其背景的颜色,并具有混合的阴影。

问题:所以,正如它所说:我如何从图像中获得最less和最常用的颜色?

不知道如何find大多数的颜色或最less的颜色,但这里是找出平均颜色的方法。

 - (UIColor *)averageColor { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char rgba[4]; CGContextRef context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), self.CGImage); CGColorSpaceRelease(colorSpace); CGContextRelease(context); if(rgba[3] > 0) { CGFloat alpha = ((CGFloat)rgba[3])/255.0; CGFloat multiplier = alpha/255.0; return [UIColor colorWithRed:((CGFloat)rgba[0])*multiplier green:((CGFloat)rgba[1])*multiplier blue:((CGFloat)rgba[2])*multiplier alpha:alpha]; } else { return [UIColor colorWithRed:((CGFloat)rgba[0])/255.0 green:((CGFloat)rgba[1])/255.0 blue:((CGFloat)rgba[2])/255.0 alpha:((CGFloat)rgba[3])/255.0]; } } 

你也许可以按照类似的方法找出最常用的颜色。

另外检查这个答案有关计算图像中的红色像素。

下面的方法将图像分析为主要颜色,步骤如下:

1.)缩小图像并确定主要像素颜色。

2)增加一些颜色的灵活性,以允许在缩放期间的损失

3.)区分颜色,删除相似的颜色

4.)将颜色作为有序数组或其百分比返回

你可以适应它返回一个特定数量的颜色,例如,如果你需要一个保证数量的颜色返回的图像中的前10色,或者只是使用“细节”variables,如果你不这样做。

较大的图像将花费很长时间来进行高细节的分析。

毫无疑问,该方法可以清理一下,但可能是一个很好的起点。

像这样使用:

  NSDictionary * mainColours = [s mainColoursInImage:image detail:1]; 

示例图像以详细的“1”

 -(NSDictionary*)mainColoursInImage:(UIImage *)image detail:(int)detail { //1. determine detail vars (0==low,1==default,2==high) //default detail float dimension = 10; float flexibility = 2; float range = 60; //low detail if (detail==0){ dimension = 4; flexibility = 1; range = 100; //high detail (patience!) } else if (detail==2){ dimension = 100; flexibility = 10; range = 20; } //2. determine the colours in the image NSMutableArray * colours = [NSMutableArray new]; 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); float x = 0; float y = 0; for (int n = 0; n<(dimension*dimension); n++){ int index = (bytesPerRow * y) + x * bytesPerPixel; int red = rawData[index]; int green = rawData[index + 1]; int blue = rawData[index + 2]; int alpha = rawData[index + 3]; NSArray * a = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%i",red],[NSString stringWithFormat:@"%i",green],[NSString stringWithFormat:@"%i",blue],[NSString stringWithFormat:@"%i",alpha], nil]; [colours addObject:a]; y++; if (y==dimension){ y=0; x++; } } free(rawData); //3. add some colour flexibility (adds more colours either side of the colours in the image) NSArray * copyColours = [NSArray arrayWithArray:colours]; NSMutableArray * flexibleColours = [NSMutableArray new]; float flexFactor = flexibility * 2 + 1; float factor = flexFactor * flexFactor * 3; //(r,g,b) == *3 for (int n = 0; n<(dimension * dimension); n++){ NSArray * pixelColours = copyColours[n]; NSMutableArray * reds = [NSMutableArray new]; NSMutableArray * greens = [NSMutableArray new]; NSMutableArray * blues = [NSMutableArray new]; for (int p = 0; p<3; p++){ NSString * rgbStr = pixelColours[p]; int rgb = [rgbStr intValue]; for (int f = -flexibility; f<flexibility+1; f++){ int newRGB = rgb+f; if (newRGB<0){ newRGB = 0; } if (p==0){ [reds addObject:[NSString stringWithFormat:@"%i",newRGB]]; } else if (p==1){ [greens addObject:[NSString stringWithFormat:@"%i",newRGB]]; } else if (p==2){ [blues addObject:[NSString stringWithFormat:@"%i",newRGB]]; } } } int r = 0; int g = 0; int b = 0; for (int k = 0; k<factor; k++){ int red = [reds[r] intValue]; int green = [greens[g] intValue]; int blue = [blues[b] intValue]; NSString * rgbString = [NSString stringWithFormat:@"%i,%i,%i",red,green,blue]; [flexibleColours addObject:rgbString]; b++; if (b==flexFactor){ b=0; g++; } if (g==flexFactor){ g=0; r++; } } } //4. distinguish the colours //orders the flexible colours by their occurrence //then keeps them if they are sufficiently disimilar NSMutableDictionary * colourCounter = [NSMutableDictionary new]; //count the occurences in the array NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:flexibleColours]; for (NSString *item in countedSet) { NSUInteger count = [countedSet countForObject:item]; [colourCounter setValue:[NSNumber numberWithInteger:count] forKey:item]; } //sort keys highest occurrence to lowest NSArray *orderedKeys = [colourCounter keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){ return [obj2 compare:obj1]; }]; //checks if the colour is similar to another one already included NSMutableArray * ranges = [NSMutableArray new]; for (NSString * key in orderedKeys){ NSArray * rgb = [key componentsSeparatedByString:@","]; int r = [rgb[0] intValue]; int g = [rgb[1] intValue]; int b = [rgb[2] intValue]; bool exclude = false; for (NSString * ranged_key in ranges){ NSArray * ranged_rgb = [ranged_key componentsSeparatedByString:@","]; int ranged_r = [ranged_rgb[0] intValue]; int ranged_g = [ranged_rgb[1] intValue]; int ranged_b = [ranged_rgb[2] intValue]; if (r>= ranged_r-range && r<= ranged_r+range){ if (g>= ranged_g-range && g<= ranged_g+range){ if (b>= ranged_b-range && b<= ranged_b+range){ exclude = true; } } } } if (!exclude){ [ranges addObject:key]; } } //return ranges array here if you just want the ordered colours high to low NSMutableArray * colourArray = [NSMutableArray new]; for (NSString * key in ranges){ NSArray * rgb = [key componentsSeparatedByString:@","]; float r = [rgb[0] floatValue]; float g = [rgb[1] floatValue]; float b = [rgb[2] floatValue]; UIColor * colour = [UIColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f]; [colourArray addObject:colour]; } //if you just want an array of images of most common to least, return here //return [NSDictionary dictionaryWithObject:colourArray forKey:@"colours"]; //if you want percentages to colours continue below NSMutableDictionary * temp = [NSMutableDictionary new]; float totalCount = 0.0f; for (NSString * rangeKey in ranges){ NSNumber * count = colourCounter[rangeKey]; totalCount += [count intValue]; temp[rangeKey]=count; } //set percentages NSMutableDictionary * colourDictionary = [NSMutableDictionary new]; for (NSString * key in temp){ float count = [temp[key] floatValue]; float percentage = count/totalCount; NSArray * rgb = [key componentsSeparatedByString:@","]; float r = [rgb[0] floatValue]; float g = [rgb[1] floatValue]; float b = [rgb[2] floatValue]; UIColor * colour = [UIColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f]; colourDictionary[colour]=[NSNumber numberWithFloat:percentage]; } return colourDictionary; } 

非常感谢您的代码@JohnnyRockex。 这有助于我开始朝着自己的目标迈进(根据图像中最主要的颜色找出重音颜色)。

通过它后,我发现代码可以简化并且易于阅读,所以我想回馈给我自己的版本; -colorsselect器处于UIImage扩展。

 - (NSArray *)colors { // Original code by Johnny Rockex http://stackoverflow.com/a/29266983/825644 // Higher the dimension, the more pixels are checked against. const float pixelDimension = 10; // Higher the range, more similar colors are removed. const float filterRange = 60; unsigned char *rawData = (unsigned char*) calloc(pixelDimension * pixelDimension * kBytesPerPixel, sizeof(unsigned char)); NSUInteger bytesPerRow = kBytesPerPixel * pixelDimension; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(rawData, pixelDimension, pixelDimension, kBitsInAByte, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, pixelDimension, pixelDimension), [self CGImage]); CGContextRelease(context); NSMutableArray * colors = [[NSMutableArray alloc] init]; float x = 0; float y = 0; const int pixelMatrixSize = pixelDimension * pixelDimension; for (int i = 0; i < pixelMatrixSize; i++){ int index = (bytesPerRow * y) + x * kBytesPerPixel; int red = rawData[index]; int green = rawData[index + 1]; int blue = rawData[index + 2]; int alpha = rawData[index + 3]; UIColor * color = [UIColor colorWithRed:(red / 255.0f) green:(green / 255.0f) blue:(blue / 255.0f) alpha:alpha]; [colors addObject:color]; y++; if (y == pixelDimension){ y = 0; x++; } } free(rawData); NSMutableDictionary * colorCounter = [[NSMutableDictionary alloc] init]; NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:colors]; for (NSString *item in countedSet) { NSUInteger count = [countedSet countForObject:item]; [colorCounter setValue:[NSNumber numberWithInteger:count] forKey:item]; } NSArray *orderedColors = [colorCounter keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){ return [obj2 compare:obj1]; }]; NSMutableArray *filteredColors = [NSMutableArray new]; for (UIColor *color in orderedColors){ bool filtered = false; for (UIColor *rangedColor in filteredColors){ if (abs(color.redRGBComponent - rangedColor.redRGBComponent) <= filterRange && abs(color.greenRGBComponent - rangedColor.greenRGBComponent) <= filterRange && abs(color.blueRGBComponent - rangedColor.blueRGBComponent) <= filterRange) { filtered = true; break; } } if (!filtered) { [filteredColors addObject:color]; } } return [filteredColors copy]; 

UIColor扩展的代码添加-rgbComponent函数可以在下面find,但是我在Swift中编写了它(尝试在Swift中编写所有新类,但是对于-colorsselect器,这不是这种情况):

 extension UIColor { open func redRGBComponent() -> UInt8 { let colorComponents = cgColor.components! return UInt8(colorComponents[0] * 255) } open func greenRGBComponent() -> UInt8 { let colorComponents = cgColor.components! return UInt8(colorComponents[1] * 255) } open func blueRGBComponent() -> UInt8 { let colorComponents = cgColor.components! return UInt8(colorComponents[2] * 255) } } 

请享用!