В моем приложении для iPhone есть экземпляр UIImage. Я хочу получить производный UIImage, который является результатом первого UIImage, в котором один из его цветов (например, пурпурный) сделан прозрачным. Как я могу это сделать?
Как сделать один цвет прозрачным на UIImage?
Ответы (10)
-(void)changeColor
{
UIImage *temp23=[UIImage imageNamed:@"leaf.png"];
CGImageRef ref1=[self createMask:temp23];
const float colorMasking[6] = {1.0, 2.0, 1.0, 1.0, 1.0, 1.0};
CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking);
UIImage *resultedimage=[UIImage imageWithCGImage:New];
}
-(CGImageRef)createMask:(UIImage*)temp
{
CGImageRef ref=temp.CGImage;
int mWidth=CGImageGetWidth(ref);
int mHeight=CGImageGetHeight(ref);
int count=mWidth*mHeight*4;
void *bufferdata=malloc(count);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst);
CGRect rect = {0,0,mWidth,mHeight};
CGContextDrawImage(cgctx, rect, ref);
bufferdata = CGBitmapContextGetData (cgctx);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL);
CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent);
CFRelease(colorSpaceRef);
return savedimageref;
}
Приведенный выше код протестирован, и я изменил зеленый цвет на красный с помощью маски
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(nil, size.width, size.height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask); /* (Other code) */ CGContextRelease(context); CGColorSpaceRelease(colorSpace);
- person Jonny; 03.04.2012
В ПОРЯДКЕ. Попробовав, я не знаю, сколько версий этих решений, у меня есть собственная настроенная версия. Я обнаружил, что решение от @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;
}
CGImageRelease
для CGBitmapContextCreateImage
? например: CGImageRef imgref = CGBitmapContextCreateImage(context); UIImage *result = [UIImage imageWithCGImage:imgref]; CGImageRelease(imgref);
- person ; 09.10.2014
Это настройка кода yubenyi, которая будет работать с несколькими проходами. Он удаляет альфа-канал перед обработкой путем преобразования изображения в несжатый JPEG. Также добавлены некоторые комментарии о том, как работает выбор цветового диапазона.
-(UIImage *)changeWhiteColorTransparent: (UIImage *)image
{
//convert to uncompressed jpg to remove any alpha channels
//this is a necessary first step when processing images that already have transparency
image = [UIImage imageWithData:UIImageJPEGRepresentation(image, 1.0)];
CGImageRef rawImageRef=image.CGImage;
//RGB color range to mask (make transparent) R-Low, R-High, G-Low, G-High, B-Low, B-High
const double colorMasking[6] = {222, 255, 222, 255, 222, 255};
UIGraphicsBeginImageContext(image.size);
CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking);
//iPhone translation
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
CGImageRelease(maskedImageRef);
UIGraphicsEndImageContext();
return result;
}
const float colorMasking[6]
на const double colorMasking[6]
- person moobi; 30.01.2015
const double colorMasking[6]
до const CGFloat colorMasking[6]
в iOS9
- person Jordi Puigdellívol; 02.06.2016
После использования ваших функций я нашел более простой способ сделать прозрачный фон для UIImage :)
Например, у вас есть изображение PNG с черным фоном, и вы хотите сделать этот фон прозрачным на экране.
Вы можете попробовать это:
UIImage * image = [UIImage imageNamed:@"image.png"];
const CGFloat colorMasking[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
image = [UIImage imageWithCGImage: CGImageCreateWithMaskingColors(image.CGImage, colorMasking)];
In Swift 5
:
let colorMasking: [CGFloat] = [0, 0, 0, 0, 0, 0]
guard let cgImage = cgImage?.copy(maskingColorComponents: colorMasking) else { return }
image = UIImage(cgImage: cgImage)
У вас получилось изображение с прозрачным фоном.
Это все :)
эта функция может работать!
-(UIImage *)changeWhiteColorTransparent: (UIImage *)image
{
CGImageRef rawImageRef=image.CGImage;
const float colorMasking[6] = {222, 255, 222, 255, 222, 255};
UIGraphicsBeginImageContext(image.size);
CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking);
{
//if in iphone
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
}
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
CGImageRelease(maskedImageRef);
UIGraphicsEndImageContext();
return result;
}
Swift 4: (для белой маскировки)
extension UIImage {
func imageByMakingWhiteBackgroundTransparent() -> UIImage? {
let image = UIImage(data: UIImageJPEGRepresentation(self, 1.0)!)!
let rawImageRef: CGImage = image.cgImage!
let colorMasking: [CGFloat] = [222, 255, 222, 255, 222, 255]
UIGraphicsBeginImageContext(image.size);
let maskedImageRef = rawImageRef.copy(maskingColorComponents: colorMasking)
UIGraphicsGetCurrentContext()?.translateBy(x: 0.0,y: image.size.height)
UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsGetCurrentContext()?.draw(maskedImageRef!, in: CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result
}
}
let image = UIImage(data: self.jpegData(compressionQuality: 1.0)!)!
- person Daniel Barclay; 21.06.2020
Основываясь на превосходном ответе @ PKCLsoft, я внес правку, в которой он делает только белый цвет прозрачным, но он делает альфа-канал в зависимости от того, насколько «белый» пиксель. Это может пригодиться, когда вы пытаетесь создать маску из черно-белого изображения, чтобы получить гладкие края на текстах или фигурах.
- (UIImage *)makeWhiteColorTransparentInImage:(UIImage *)image {
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);
int byteIndex = 0;
while (byteIndex < bitmapByteCount) {
unsigned char red = rawData[byteIndex];
unsigned char green = rawData[byteIndex + 1];
unsigned char blue = rawData[byteIndex + 2];
unsigned char alpha = rawData[byteIndex + 3];
if (alpha == 0.0) {
rawData[byteIndex + 3] = 0.0;
} else {
rawData[byteIndex + 3] = 255.0 - (red + green + blue) / 3.0;
}
byteIndex += 4;
}
CGImageRef imgref = CGBitmapContextCreateImage(context);
UIImage *result = [UIImage imageWithCGImage:imgref];
CGImageRelease(imgref);
CGContextRelease(context);
free(rawData);
return result;
}
Надеюсь, когда-нибудь это кому-то поможет :)
быстрая версия для белого цвета фона до прозрачного цвета
extension UIImage {
func imageByMakingWhiteBackgroundTransparent() -> UIImage? {
let image = UIImage(data: self.jpegData(compressionQuality: 1.0)!)!
let rawImageRef: CGImage = image.cgImage!
let colorMasking: [CGFloat] = [222, 255, 222, 255, 222, 255]
UIGraphicsBeginImageContext(image.size);
let maskedImageRef = rawImageRef.copy(maskingColorComponents: colorMasking)
UIGraphicsGetCurrentContext()?.translateBy(x: 0.0,y: image.size.height)
UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsGetCurrentContext()?.draw(maskedImageRef!, in: CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result
}
}
Сам я никогда ничего подобного не делал, но похоже, CGImageCreateWithMaskingColors
может здесь пригодиться. Однако использование Core Graphics выходит за рамки того, что я могу объяснить в ответе на этом сайте; Изучите свою документацию и найдите учебные пособия в Интернете.
Расширение UIImage в swift 5 с возможностью изменения любого цвета на прозрачный. На основе ответа @fegoulart.
extension UIImage {
func remove(color: UIColor) -> UIImage? {
let cgColor = color.cgColor
let components = cgColor.components
var r = components?[0] ?? 0.0
var g = components?[1] ?? 0.0
var b = components?[2] ?? 0.0
r = r * 255.0
g = g * 255.0
b = b * 255.0
let colorMasking: [CGFloat] = [r, r, g, g, b, b]
let image = UIImage(data: self.jpegData(compressionQuality: 1.0)!)!
let rawImageRef: CGImage = image.cgImage!
UIGraphicsBeginImageContext(image.size);
let maskedImageRef = rawImageRef.copy(maskingColorComponents: colorMasking)
UIGraphicsGetCurrentContext()?.translateBy(x: 0.0,y: image.size.height)
UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsGetCurrentContext()?.draw(maskedImageRef!, in: CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result
}
}