替换图像的某种色值

Posted yuxiaoyiyou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了替换图像的某种色值相关的知识,希望对你有一定的参考价值。

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

 

以上是关于替换图像的某种色值的主要内容,如果未能解决你的问题,请参考以下文章

收藏|分享前端开发常用代码片段

关于js----------------分享前端开发常用代码片段

无法替换图像视图,用于来自相机或画廊的图像(它不起作用)

512*512 256色值的索引图像的大小是多少?

片段 - 替换容器,如果 id 不是唯一的

Android - 通过 FragmentManager 替换片段后,片段返回到它们的第一个状态