UIImage のピクセルカラーを変更する

2012/04/20

画像処理に使えるUIImageのTips10個」を参考に、UIImage のカラーを変更してみます。 UIimageのカラーを変更する場合、UIImageからピクセルを取得し新たな画像を作成してやります。

サンプル

任意の red値でカラーを変更する。

- (UIImage *)changeRImage:(UIImage *)image red:(CGFloat)value {
    CFDataRef cfDataRef = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    NSData* pixelData = (__bridge NSData*) cfDataRef;
    unsigned char* bitmap = (unsigned char *)[pixelData bytes];
    CGFloat width = image.size.width;
    CGFloat height = image.size.height;
    
    for(int i = 0; i < [pixelData length]; i += 4) {
        CGFloat _value = bitmap[i] + value;
        if (_value > 255) _value = 255;
        bitmap[i] = _value;
        bitmap[i+1] = bitmap[i+1];
        bitmap[i+2] = bitmap[i+2];
        bitmap[i+3] = bitmap[i+3];
    }
    CGDataProviderRef dataProviderRef = CGDataProviderCreateWithData(NULL, bitmap, width*height*4, NULL);
    CGImageRef result = CGImageCreate(image.size.width, image.size.height, 8, 32, width*4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaLast, dataProviderRef, NULL, 0, kCGRenderingIntentDefault);
    UIImage *newImage = [[UIImage alloc] initWithCGImage:result];
    
    CGImageRelease(result);
    //CFRelease(dataProviderRef);
    
    return newImage;
}

UIImage から CFDataRef を作成し、bytes を取得するとビッチマップデータになります。 ※ARCを利用する場合は、CFDataRef と NSData のキャストでブリッジしてやる必要があり

ビットマップのRGBAは、for文の通り「+4」ステップで取得し、ピクセル値を変更してやります。

後は、CGDataProviderCreateWithData() などでごにょごにょして UIImage を作成します。

またアルファチャンネルとマスクでカラー変更する方法が「Bezelボタンを作る[12]画像をグレースケールで表示する(その2) 」に記載されていました。

グレースケールサンプル

- (UIImage *)grayscale:(UIImage *)image {
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef alphaContext = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0,
                                                      colorSpace, kCGImageAlphaOnly);
    CGContextDrawImage(alphaContext, rect, [image CGImage]);
    CGImageRef alphaImage = CGBitmapContextCreateImage(alphaContext);
    CGContextRelease(alphaContext);
    
    CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0,
                                                 colorSpace, kCGImageAlphaNone);
    CGContextDrawImage(context, rect, [image CGImage]);
    CGImageRef grayScaleImage = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    
    UIImage* grayScaleUIImage = [UIImage imageWithCGImage:
                                 CGImageCreateWithMask(grayScaleImage, alphaImage)];
    
    CGImageRelease(grayScaleImage);
    CGImageRelease(alphaImage);
    CGColorSpaceRelease(colorSpace);

    return grayScaleUIImage;
}