//遍历图片像素,更改图片颜色
void ProviderReleaseData (void *info, const void *data, size_t size)
{
free((void*)data);
}
+ (UIImage *)imageBlackToTransparent:(UIImage*) image
{
// 分配内存
const int imageWidth = image.size.width;
const int imageHeight = image.size.height;
size_t bytesPerRow = imageWidth * 4;
uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
// 创建context
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
// 遍历像素
int pixelNum = imageWidth * imageHeight;
uint32_t* pCurPtr = rgbImageBuf;
for (int i = 0; i < pixelNum; i++, pCurPtr++)
{
//if (*pCurPtr & 0xFFFFFF00) == 0xffffff00) // 为白色的部分
//else if ((*pCurPtr & 0xFFFFFF00) == 0) // 为黑色的部分
uint8_t* ptr = (uint8_t*)pCurPtr;
//下面是颜色反转,黑色变白色,白色变黑色,其他类似对调
// ptr[0] ; //这个表示alpha
ptr[1] = 255 - ptr[1]; ////0~255
ptr[2] = 255 - ptr[2];
ptr[3] = 255 - ptr[3];
// }
}
// 将内存转成image
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData);
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,NULL, true, kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
// 释放
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// free(rgbImageBuf) 创建dataProvider时已提供释放函数,这里不用free
return resultUIImage;
}
无意中发现的一篇文章,上面的代码就是在这篇文章的基础上实现的
+(UIImage*) grayscale:(UIImage*)anImage type:(char)type {
CGImageRef imageRef;
imageRef = anImage.CGImage;
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
// ピクセルを構成するRGB各要素が何ビットで構成されている
size_t bitsPerComponent;
bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
// ピクセル全体は何ビットで構成されているか
size_t bitsPerPixel;
bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
// 画像の横1ライン分のデータが、何バイトで構成されているか
size_t bytesPerRow;
bytesPerRow = CGImageGetBytesPerRow(imageRef);
// 画像の色空間
CGColorSpaceRef colorSpace;
colorSpace = CGImageGetColorSpace(imageRef);
// 画像のBitmap情報
CGBitmapInfo bitmapInfo;
bitmapInfo = CGImageGetBitmapInfo(imageRef);
// 画像がピクセル間の補完をしているか
bool shouldInterpolate;
shouldInterpolate = CGImageGetShouldInterpolate(imageRef);
// 表示装置によって補正をしているか
CGColorRenderingIntent intent;
intent = CGImageGetRenderingIntent(imageRef);
// 画像のデータプロバイダを取得する
CGDataProviderRef dataProvider;
dataProvider = CGImageGetDataProvider(imageRef);
// データプロバイダから画像のbitmap生データ取得
CFDataRef data;
UInt8* buffer;
data = CGDataProviderCopyData(dataProvider);
buffer = (UInt8*)CFDataGetBytePtr(data);
// 1ピクセルずつ画像を処理
NSUInteger x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
UInt8* tmp;
tmp = buffer + y * bytesPerRow + x * 4; // RGBAの4つ値をもっているので、1ピクセルごとに*4してずらす
// RGB値を取得
UInt8 red,green,blue;
red = *(tmp + 0);
green = *(tmp + 1);
blue = *(tmp + 2);
UInt8 brightness;
switch (type) {
case 1://モノクロ
// 輝度計算
brightness = (77 * red + 28 * green + 151 * blue) / 256;
*(tmp + 0) = brightness;
*(tmp + 1) = brightness;
*(tmp + 2) = brightness;
break;
case 2://セピア
*(tmp + 0) = red;
*(tmp + 1) = green * 0.7;
*(tmp + 2) = blue * 0.4;
break;
case 3://色反転
*(tmp + 0) = 255 - red;
*(tmp + 1) = 255 - green;
*(tmp + 2) = 255 - blue;
break;
default:
*(tmp + 0) = red;
*(tmp + 1) = green;
*(tmp + 2) = blue;
break;
}
}
}
// 効果を与えたデータ生成
CFDataRef effectedData;
effectedData = CFDataCreate(NULL, buffer, CFDataGetLength(data));
// 効果を与えたデータプロバイダを生成
CGDataProviderRef effectedDataProvider;
effectedDataProvider = CGDataProviderCreateWithCFData(effectedData);
// 画像を生成
CGImageRef effectedCgImage;
UIImage* effectedImage;
effectedCgImage = CGImageCreate(
width, height,
bitsPerComponent, bitsPerPixel, bytesPerRow,
colorSpace, bitmapInfo, effectedDataProvider,
NULL, shouldInterpolate, intent);
effectedImage = [[UIImage alloc] initWithCGImage:effectedCgImage];
// データの解放
CGImageRelease(effectedCgImage);
CFRelease(effectedDataProvider);
CFRelease(effectedData);
CFRelease(data);
return effectedImage;
}