OK. Попробовав, я не знаю, сколько версий этих решений, у меня есть собственная настроенная версия. Я обнаружил, что решение @yubenyi работает довольно хорошо, но если вы хотите взять вывод из его функции changeWhiteColorTransparent () и вернуть его обратно, оно не будет работать.
Моим первым шагом было изменение его функции, чтобы она принимала определенный цвет и допуск, чтобы вызывающий мог указать диапазон цветов, чтобы сделать его прозрачным. Это работало нормально, почти без изменений, но я обнаружил, что вывод не был допустимым изображением для прохождения через тот же код со вторым цветовым диапазоном.
После долгих проб и ошибок я получил эту работу, выполнив замену цвета самостоятельно. Я сопротивлялся этому, потому что казалось, что слишком много тяжелой работы, когда есть API, чтобы делать это, но они не всегда ведут себя так, как вы хотите. В частности, вывод из CGImageCreateWithMaskingColors () не может использоваться как вход для другого вызова той же функции. Я не смог понять почему, но я думаю, что это как-то связано с альфа-каналом.
В любом случае, мое решение:
- (UIImage*) replaceColor:(UIColor*)color inImage:(UIImage*)image withTolerance:(float)tolerance {
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
NSUInteger bitmapByteCount = bytesPerRow * height;
unsigned char *rawData = (unsigned char*) calloc(bitmapByteCount, sizeof(unsigned char));
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGColorRef cgColor = [color CGColor];
const CGFloat *components = CGColorGetComponents(cgColor);
float r = components[0];
float g = components[1];
float b = components[2];
//float a = components[3]; // not needed
r = r * 255.0;
g = g * 255.0;
b = b * 255.0;
const float redRange[2] = {
MAX(r - (tolerance / 2.0), 0.0),
MIN(r + (tolerance / 2.0), 255.0)
};
const float greenRange[2] = {
MAX(g - (tolerance / 2.0), 0.0),
MIN(g + (tolerance / 2.0), 255.0)
};
const float blueRange[2] = {
MAX(b - (tolerance / 2.0), 0.0),
MIN(b + (tolerance / 2.0), 255.0)
};
int byteIndex = 0;
while (byteIndex < bitmapByteCount) {
unsigned char red = rawData[byteIndex];
unsigned char green = rawData[byteIndex + 1];
unsigned char blue = rawData[byteIndex + 2];
if (((red >= redRange[0]) && (red <= redRange[1])) &&
((green >= greenRange[0]) && (green <= greenRange[1])) &&
((blue >= blueRange[0]) && (blue <= blueRange[1]))) {
// make the pixel transparent
//
rawData[byteIndex] = 0;
rawData[byteIndex + 1] = 0;
rawData[byteIndex + 2] = 0;
rawData[byteIndex + 3] = 0;
}
byteIndex += 4;
}
CGImageRef imgref = CGBitmapContextCreateImage(context);
UIImage *result = [UIImage imageWithCGImage:imgref];
CGImageRelease(imgref);
CGContextRelease(context);
free(rawData);
return result;
}