Попытка динамически закрасить прозрачные UIImages, но получить размытый результат.Что я делаю неправильно? - PullRequest
5 голосов
/ 09 ноября 2010

В моем приложении для iPhone есть пользовательские UITableViewCell с иконками. В нормальном состоянии ячейки эти значки черные с прозрачным фоном. Вместо того чтобы связывать второй набор перевернутых значков с приложением для выделенного состояния (белого на прозрачном фоне), я бы хотел на лету инвертировать эти значки с помощью Core Graphics всякий раз, когда пользователь касается соответствующей ячейки таблицы.

Я нашел некоторые другие ответы, связанные с наложением UIImage цветом или перекраской UIImage s, но все эти методы дают мне размытый результат (см. Ниже). Я пробовал все виды CGBlendMode s, а также вручную вычислял более точную маску (возможно, я сделал это неправильно), но кажется, что полупрозрачные пиксели по краям моих значков теряют прозрачность или в основном отбрасывается - давая изменчивый / размытый вид. Я в растерянности за то, что я делаю неправильно.

Это также не вариант изменить все мои значки, чтобы они были чисто черно-белыми без прозрачности - мне нужно, чтобы значки располагались на прозрачном фоне, чтобы их можно было накладывать поверх других элементов пользовательского интерфейса. .

Код (любезно предоставленный Чедвиком Вудом), который я использую для инвертирования иконки (я вызываю этот метод на каждой из моих оригинальных иконок и передаю [UIColor whiteColor] в качестве второго аргумента) и пример вывода (на iPhone 4 с iOS 4.1) находится ниже (игнорируйте синий фон на выделенном изображении - это выделенный фон выбранной ячейки таблицы).

Любая помощь очень ценится.

Пример ввода и вывода:

Icon before & after programmatic recoloring.

@implementation UIImage(FFExtensions)

+ (UIImage *)imageNamed:(NSString *)name withColor:(UIColor *)color {

 // load the image
 UIImage *img = [UIImage imageNamed:name];

 // begin a new image context, to draw our colored image onto
 UIGraphicsBeginImageContext(img.size);

 // get a reference to that context we created
 CGContextRef context = UIGraphicsGetCurrentContext();
 CGContextSetInterpolationQuality(context, kCGInterpolationHigh);

 // set the fill color
 [color setFill];

 // translate/flip the graphics context (for transforming from CG* coords to UI* coords
 CGContextTranslateCTM(context, 0, img.size.height);
 CGContextScaleCTM(context, 1.0, -1.0);

 // set the blend mode to color burn, and the original image
 CGContextSetBlendMode(context, kCGBlendModeMultiply);
 CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
 //CGContextDrawImage(context, rect, img.CGImage);

 // set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
 CGContextClipToMask(context, rect, img.CGImage);
 CGContextAddRect(context, rect);
 CGContextDrawPath(context,kCGPathFill);


 // generate a new UIImage from the graphics context we drew onto
 UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();

 //return the color-burned image
 return coloredImg;
}

@end

1 Ответ

5 голосов
/ 10 ноября 2010

Благодаря наблюдению Питера и Стивена о том, что разрешение выходного изображения оказалось ниже входного, я понял, что при создании контекста изображения не учитывал масштабный коэффициент экрана.

Изменение строки:

UIGraphicsBeginImageContext(img.size);

на

UIGraphicsBeginImageContextWithOptions(img.size, NO, [UIScreen mainScreen].scale);

устраняет проблему.

...