const unsigned char RGBMAX = 255;
#define EqualZero(a) ((a) == 0)
void cvtRGBToHSI(CGFloat iR,CGFloat iG, CGFloat iB, unsigned char * rH, unsigned char * rS, unsigned char *rI)
{
/*
当人观察一个彩色物体时,用色调、饱和度、亮度来描述物体的颜色。HSI〔Hue-Saturation-Intensity(Lightness),HSI或HSL〕颜色模型用H、S、I三参数描述颜色特性,其中H定义颜色的波长,称为色调;S表示颜色的深浅程度,称为饱和度;I表示强度或亮度。在HSI颜色模型的双六棱锥表示,I是强度轴,色调H的角度范围为[0,2π],其中,纯红色的角度为0,纯绿色的角度为2π/3,纯蓝色的角度为4π/3
*/
const float PI2 = 2*3.1415926;
float r = (float)iR;
float g = (float)iG;
float b = (float)iB;
float maxVal = MAX(MAX(r, g), b);
float minVal = MIN(MIN(r, g), b);
float i = (r + g + b)/3;
float s = 0.0f;
float h = 0.0f;
if(!EqualZero(i) && !EqualZero(maxVal -minVal))
{
float diff = 0.5f*(r-g + r-b);
float diff2 = (r-g)*(r-g) + (r-g)*(g-b); //diff2 永远 > 0
float sita = acos(diff/sqrt(diff2))/PI2; //角度,PI2为1
h = (g>=b) ? sita : (1.0f - sita);
s = 1.0f - minVal/i;
}
if (h < 0.0f ) h += 1.0f;
else if (h > 1.0f ) h -= 1.0f;
*rH = (unsigned char)round(h*RGBMAX); //range: 0 to 255;
*rS = (unsigned char)round(s*RGBMAX); //range: 0 to 255;
*rI = (unsigned char)round(i*RGBMAX); //range: 0 to 255;
}
unsigned char subUnsignedChar(unsigned char a,unsigned char b)
{
return (a>b)?(a-b):(b-a);
}
-(BOOL)beSimilarColor:(UIColor*)color1 withColor:(UIColor*)color2 withDifference:(unsigned char)difference
{
CGFloat r1,r2,g1,g2,b1,b2,a1,a2;
unsigned char h1,h2,s1,s2,i1,i2;
[color1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
[color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
cvtRGBToHSI(r1, g1, b1, &h1, &s1, &i1);
cvtRGBToHSI(r2, g2, b2, &h2, &s2, &i2);
unsigned char maxGap = difference;
if (a1 == a2 && (subUnsignedChar(h1, h2) <= maxGap) && (subUnsignedChar(s1, s2) <= maxGap) && (subUnsignedChar(i1, i2) <= maxGap)) {
return YES;
}
return NO;
}
#pragma mark 图片替换颜色
-(UIImage*)videoPictureImageForReplaceColor:(UIColor*)color toColor:(UIColor*)otherColor withImage:(UIImage*)image withDifference:(unsigned char)difference
{
CVPixelBufferRef pixelBuffer = NULL;
CGImageRef img = image.CGImage;
size_t width = CGImageGetWidth(img);
size_t height = CGImageGetHeight(img);
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, nil, &pixelBuffer);
if (status != kCVReturnSuccess) {
return NULL;
}
size_t rowBytes = CVPixelBufferGetBytesPerRow(pixelBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
void *data = CVPixelBufferGetBaseAddress(pixelBuffer);
CGFloat r,g,b,a;
[otherColor getRed:&r green:&g blue:&b alpha:&a];
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(data, width, height, 8, rowBytes, rgbColorSpace, (CGBitmapInfo) kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGContextClearRect(context, CGRectMake(0, 0, width, height));
CGContextDrawImage(context, CGRectMake(0, 0, width, height), img);
unsigned char *colorPtr = (unsigned char *)data;
for (size_t h = 0; h < height; h++) {
for (size_t w = 0; w < width; w++) {
if ([self beSimilarColor:[UIColor colorWithRed:colorPtr[0]/255.0f green:colorPtr[1]/255.0f blue:colorPtr[2]/255.0f alpha:colorPtr[3]/255.0f] withColor:color withDifference:difference]) {
// printf("%d %d %d %d\n",colorPtr[0],colorPtr[1],colorPtr[2],colorPtr[3]);
colorPtr[0] = round(r*255);
colorPtr[1] = round(g*255);
colorPtr[2] = round(b*255);
colorPtr[3] = round(a*255);
}
colorPtr += 4;
}
}
CGImageRef imageRef = CGBitmapContextCreateImage (context);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
//clean up
CGImageRelease(imageRef);
CVPixelBufferRelease(pixelBuffer);
return returnImage;
}