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 ",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; }