遇到一个需求,要提取图片中的色调,但还有一点特殊的需求,就是不是提取颜色最多的色调,也不是平均的色调,是图片中偏暗的色调
这就需要我们动态的调整我们提取的算法,
下面就看代码
-(void)getImage:(UIImage
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大
int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGSize thumbSize = CGSizeMake(100, 100*self.backgroundImgView.height/(self.backgroundImgView.width ?: 100));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,thumbSize.width,thumbSize.height, 8, thumbSize.width*4, colorSpace,bitmapInfo);
CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
CGContextDrawImage(context, drawRect, image.CGImage);
CGColorSpaceRelease(colorSpace);
// 第二步 取每个点的像素值
unsigned char* data = CGBitmapContextGetData (context);
if (data == NULL) {
dispatch_async(dispatch_get_main_queue(), ^{
callBack(nil);
});
};
NSCountedSet* cls = [NSCountedSet setWithCapacity: thumbSize.width * thumbSize.height];
for (int x = 0; x < thumbSize.width; x++) {
for (int y = 0; y < thumbSize.height; y++) {
int offset = 4 * (x * y);
int red = data[offset];
int green = data[offset + 1];
int blue = data[offset + 2];
int alpha = data[offset + 3];
// 过滤透明的、基本白色、基本黑色
// 这里限制170是因为要去除偏亮的颜色 越接近250越亮
if (alpha > 0 && (red < 170 && green < 170 && blue < 170) && (red > 5 && green > 5 && blue > 5)) {
NSArray *clr = @[@(red),@(green),@(blue),@(alpha)];
[cls addObject:clr];
}
}
}
CGContextRelease(context);
//第三步 找到出现次数最多的那个颜色
NSEnumerator *enumerator = [cls objectEnumerator];
NSArray *curColor = nil;
NSArray *MaxColor = nil;
NSUInteger MaxCount = 0;
while ((curColor = [enumerator nextObject]) != nil){
NSUInteger tmpCount = [cls countForObject:curColor];
if ( tmpCount < MaxCount ) continue;
MaxCount = tmpCount;
MaxColor = curColor;
}
UIColor * subjectColor = [UIColor colorWithRed:([MaxColor[0] intValue]/255.0f) green:([MaxColor[1] intValue]/255.0f) blue:([MaxColor[2] intValue]/255.0f) alpha:([MaxColor[3] intValue]/255.0f)];
dispatch_async(dispatch_get_main_queue(), ^{
callBack(subjectColor);
});
});
}
如以上代码,要注意这句条件限制
red < 170 && green < 170 && blue < 170 ,这就限制我们提取比较暗的色调,因为越接近250, 颜色是越亮的,当然,我们可以根据自己的实际需求自己动态的调整提取的色调