干し石榴長文用

長文以外はTumblrへ徐々に移します。

UITabBarに適当なアイコン画像を使う場合のフィルター

UITabBarに置くアイコンはアルファ値しか使われないらしく、それを考慮した画像を作らないとベタ塗りになってしまいます。
今回アイコン画像をアプリ実行時にダウンロードしてくるケースのため静的リソースとして作成できず、CIFilterの組み込みフィルターを調べてみるもそれっぽいのが見当たらず、
RGBの平均をアルファ値にするフィルター(?)処理を自分で書いてみました。

【参考】

【Before】
f:id:zak-raw:20130920175505p:plain

【After】
f:id:zak-raw:20130920175524p:plain

【フィルターのコード】

+ (UIImage*) alphalize:(UIImage*)image
{
	CGImageRef inImage = image.CGImage;
	CFDataRef ref = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
	int length = CFDataGetLength(ref);
	unsigned char *inData = (unsigned char *) CFDataGetBytePtr(ref);
	
	CGContextRef context = [self createBitmapContext:inImage];
	unsigned char *outData = CGBitmapContextGetData(context);
	
	for (int i = 0; i < length; i += 4) {
		int r = *(inData + i);
		int g = *(inData + i + 1);
		int b = *(inData + i + 2);
		
		*(outData + i + 0) = 0;
		*(outData + i + 1) = 0;
		*(outData + i + 2) = 0;
		*(outData + i + 3) = (r + g + b) / 3;
	}
	
	CGImageRef outImage = CGBitmapContextCreateImage(context);
	UIImage* filteredImage = [UIImage imageWithCGImage:outImage
						 scale:image.scale
					   orientation:UIImageOrientationUp];

	CGContextRelease(context);
	CGImageRelease(inImage);
	CGImageRelease(outImage);
	
	return filteredImage;
}

+ (CGContextRef) createBitmapContext:(CGImageRef)inImage
{
	size_t width = CGImageGetWidth(inImage);
	size_t height = CGImageGetHeight(inImage);
	
	int bytesPerRow = (width * 4);
	int byteCount = (bytesPerRow * height);
	
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
	CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(inImage);
	
	void* bitmapData = malloc(byteCount);
	CGContextRef ref = CGBitmapContextCreate(bitmapData,
						 width,
						 height,
						 8,
						 bytesPerRow,
						 colorSpace,
						 alphaInfo);
	
	CGColorSpaceRelease(colorSpace);
	
	return ref;
}

C全然書いたことないのでリソース解放漏れとかあるかもしれません。
ARC環境なら大丈夫なのかな。
あとアルファが後ろにある前提なのでそこは適宣。