iOS: применение фильтра RGB к PNG в оттенках серого - PullRequest
4 голосов
/ 13 июля 2011

У меня есть вид сверху полутонового самоцвета.

(формат PNG, поэтому есть альфа-компонент)

image

Я хотел бы создать из этого изображения 12 кнопок небольшого размера, каждая разного цвета.

Ради чистоты, я хотел бы сделать это в коде, а не внешне, в каком-то пакете произведений искусства.

Может ли кто-нибудь предоставить метод (или даже некоторый код) для этого?

PS Мне известно о том, как сделать это в GL с использованием смешного количества кода, я надеюсь, что есть более простой способ использования базовой графики / базовой анимации

РЕДАКТИРОВАТЬ: Рабочее решение, благодаря удивительным снизу ответ

    CGSize targetSize = (CGSize){100,100};
    UIImage* image;
    {
        CGRect rect = (CGRect){ .size = targetSize };

        UIGraphicsBeginImageContext( targetSize );
        {
            CGContextRef X = UIGraphicsGetCurrentContext();

            UIImage* uiGem = [UIImage imageNamed: @"GemTop_Dull.png"];

            // draw gem
            [uiGem drawInRect: rect];

            // overlay a red rectangle
            CGContextSetBlendMode( X, kCGBlendModeColor ) ;
            CGContextSetRGBFillColor ( X,  0.9, 0, 0,  1 );
            CGContextFillRect ( X, rect );

            // redraw gem 
            [uiGem drawInRect: rect
                    blendMode: kCGBlendModeDestinationIn
                        alpha: 1. ];

            image = UIGraphicsGetImageFromCurrentImageContext();
        }
        UIGraphicsEndImageContext();
    }

Ответы [ 3 ]

4 голосов
/ 13 июля 2011

Самый простой способ сделать это - нарисовать изображение в RGB-цветовом пространстве CGBitmapContext , использовать CGContextSetBlendMode для установки kCGBlendModeColor, а затем нарисовать его сплошным цветом (например, с помощью CGContextFillRect).

1 голос
/ 13 июля 2011

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

0 голосов
/ 26 июня 2014

Это улучшение ответа на вопрос и реализация @ Anomie

Во-первых, поместите это в начало класса UIButton или контроллера представления.Он преобразуется из UIColor в RGBA значение, которое вам понадобится позже.

typedef enum { R, G, B, A } UIColorComponentIndices;


@implementation UIColor (EPPZKit)

- (CGFloat)redRGBAValue {
    return CGColorGetComponents(self.CGColor)[R];
}

- (CGFloat)greenRGBAValue  {
    return CGColorGetComponents(self.CGColor)[G];
}

- (CGFloat)blueRGBAValue  {
    return CGColorGetComponents(self.CGColor)[B];
}

- (CGFloat)alphaRGBAValue  {
    return CGColorGetComponents(self.CGColor)[A];
}

@end

Теперь убедитесь, что у вас есть кнопка с пользовательским изображением в IB, с изображением в градациях серого и в правом кадре.,Это значительно лучше и проще, чем создавать пользовательскую кнопку изображения программно, потому что:

  • вы можете позволить IB загрузить изображение, вместо того, чтобы загружать его вручную
  • вы можете настроитьнажмите кнопку и посмотрите на нее визуально в IB
  • ваш IB будет больше похож на ваше приложение во время выполнения
  • вам не нужно вручную устанавливать кадры

Предполагая, что выесли кнопка находится в IB (в нижней части будет поддерживаться ее программное создание), добавьте этот метод в свой контроллер представления или в класс детенышей кнопки:

- (UIImage*)customImageColoringFromButton:(UIButton*)customImageButton fromColor:(UIColor*)color {
    UIImage *customImage = [customImageButton.imageView.image copy];

    UIGraphicsBeginImageContext(customImageButton.imageView.frame.size); {
        CGContextRef X = UIGraphicsGetCurrentContext();

        [customImage drawInRect: customImageButton.imageView.frame];

        // Overlay a colored rectangle
        CGContextSetBlendMode( X, kCGBlendModeColor) ;
        CGContextSetRGBFillColor ( X, color.redRGBAValue, color.greenRGBAValue, color.blueRGBAValue, color.alphaRGBAValue);
        CGContextFillRect ( X, customImageButton.imageView.frame);

        // Redraw
        [customImage drawInRect:customImageButton.imageView.frame blendMode: kCGBlendModeDestinationIn alpha: 1.0];

        customImage = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext();

    return customImage;
}

Затем вам нужно будет вызвать его вУстановите метод в вашем контроллере вида или подклассе кнопки и установите для него imageView кнопки:

[myButton.imageView setImage:[self customImageColoringFromButton:myButton fromColor:desiredColor]];

Если вы не используете IB для создания кнопки, используйте этот метод:

- (UIImage*)customImageColoringFromImage:(UIImage*)image fromColor:(UIColor*)color fromFrame:(CGRect)frame {
    UIImage *customImage = [image copy];

    UIGraphicsBeginImageContext(frame.size); {
        CGContextRef X = UIGraphicsGetCurrentContext();

        [customImage drawInRect: frame];

        // Overlay a colored rectangle
        CGContextSetBlendMode( X, kCGBlendModeColor) ;
        CGContextSetRGBFillColor ( X, color.redRGBAValue, color.greenRGBAValue, color.blueRGBAValue, color.alphaRGBAValue);
        CGContextFillRect ( X, frame);

        // Redraw
        [customImage drawInRect:frame blendMode: kCGBlendModeDestinationIn alpha: 1.0];

        customImage = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext();

    return customImage;
}

И позвоните по этому номеру:

[self.disclosureButton.imageView setImage:[self customImageColoringFromImage:[UIImage imageNamed:@"GemTop_Dull.png"] fromColor:desiredColor fromFrame:desiredFrame]];
...