Формула режима наложения наложения?

У меня есть 2 цвета: один динамически установлен, а другой всегда белый с 0,5 альфа. Я хочу рассчитать результирующий белый цвет, как если бы он был нарисован поверх динамического цвета с использованием режима наложения Overlay.

Мне известно, что Оверлей сочетает в себе режимы наложения Умножение и Экран.

Формула режима наложения Multiply:

Result Color = (Top Color) * (Bottom Color) /255

В то время как режим наложения экрана:

Result Color = 255 - [((255 - Top Color)*(255 - Bottom Color))/255]

Как рассчитать результирующий цвет для режима наложения Overlay?

Есть ли класс расширения UIColor, который делает это из коробки?


person samvermette    schedule 28.04.2011    source источник


Ответы (3)


Формула состоит из двух частей:

Первая часть: если значение нижнего слоя> 127,5, выполните следующие действия:

Единица значения = (255-значение нижнего уровня) / 127,5

Мин. Значение = значение нижнего уровня - (255-значение нижнего уровня)

Наложение = (Значение верхнего уровня * Единица значения) + Мин. Значение

Вторая часть: Если значение нижнего слоя ‹127,5, то сделайте следующее -

Единица значения = значение нижнего уровня / 127,5

Наложение = Значение верхнего уровня * Единица измерения

Из формулы видно, что конечный результат во многом зависит от значения верхнего уровня. Если значение верхнего слоя выше (светлее), то конечный результат, скорее всего, будет светлее.

Из здесь.

person willi    schedule 28.04.2011
comment
Большой. Это не было частью моего первоначального вопроса, но знаете ли вы какой-нибудь класс расширения UIColor, который делает это из коробки? - person samvermette; 29.04.2011
comment
Не реализация OTB, но это может вам помочь: github .com / facebook / three20 / blob / master / src / Three20Style /. - person Vincent Guerci; 29.04.2011

Следуя ответу Уилли, вот формула, перенесенная в код:

CGFloat newComponents[4];
const CGFloat *topComponents = CGColorGetComponents([[UIColor colorWithRed:1 green:1 blue:1 alpha:1] CGColor]);
const CGFloat *components = CGColorGetComponents(self.color.CGColor);
const int n = CGColorGetNumberOfComponents(self.color.CGColor);

for(int i=0; i < n; i++) {

    if(components[i] > 0.5) {
        CGFloat value = (topComponents[i]-components[i])/0.5;
        CGFloat min = components[i]-(topComponents[i]-components[i]);
        newComponents[i] = topComponents[i]*value+min; 
    } else {
        CGFloat value = components[i]/0.5;
        newComponents[i] = topComponents[i]*value; 
    }
}

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UIColor *resultColor = [UIColor colorWithCGColor:CGColorCreate(colorSpace, newComponents)];
CGColorSpaceRelease(colorSpace);
person samvermette    schedule 29.04.2011

Я понятия не имею о вашей цели и, возможно, совершенно не по теме, но почему бы просто не использовать Quartz 2D?

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
... draw with overlay blending

CGBlendMode предлагает через CGContextSetBlendMode Overlay, Multiply, Screen и многое другое ...:

enum CGBlendMode {
    /* Available in Mac OS X 10.4 & later. */
    kCGBlendModeNormal,
    kCGBlendModeMultiply,
    kCGBlendModeScreen,
    kCGBlendModeOverlay,
    kCGBlendModeDarken,
    kCGBlendModeLighten,
    kCGBlendModeColorDodge,
    kCGBlendModeColorBurn,
    kCGBlendModeSoftLight,
    kCGBlendModeHardLight,
    kCGBlendModeDifference,
    kCGBlendModeExclusion,
    kCGBlendModeHue,
    kCGBlendModeSaturation,
    kCGBlendModeColor,
    kCGBlendModeLuminosity,

    /* Available in Mac OS X 10.5 & later. R, S, and D are, respectively,
       premultiplied result, source, and destination colors with alpha; Ra,
       Sa, and Da are the alpha components of these colors.

       The Porter-Duff "source over" mode is called `kCGBlendModeNormal':
         R = S + D*(1 - Sa)

       Note that the Porter-Duff "XOR" mode is only titularly related to the
       classical bitmap XOR operation (which is unsupported by
       CoreGraphics). */

    kCGBlendModeClear,          /* R = 0 */
    kCGBlendModeCopy,           /* R = S */
    kCGBlendModeSourceIn,       /* R = S*Da */
    kCGBlendModeSourceOut,      /* R = S*(1 - Da) */
    kCGBlendModeSourceAtop,     /* R = S*Da + D*(1 - Sa) */
    kCGBlendModeDestinationOver,    /* R = S*(1 - Da) + D */
    kCGBlendModeDestinationIn,      /* R = D*Sa */
    kCGBlendModeDestinationOut,     /* R = D*(1 - Sa) */
    kCGBlendModeDestinationAtop,    /* R = S*(1 - Da) + D*Sa */
    kCGBlendModeXOR,            /* R = S*(1 - Da) + D*(1 - Sa) */
    kCGBlendModePlusDarker,     /* R = MAX(0, (1 - D) + (1 - S)) */
    kCGBlendModePlusLighter     /* R = MIN(1, S + D) */
};
typedef enum CGBlendMode CGBlendMode; /* Available in Mac OS X 10.4 & later. */
person Vincent Guerci    schedule 28.04.2011
comment
Я этим и занимаюсь. Но мне нужно сохранить ссылку на этот результат белого цвета 0,5 альфа, нарисованного с использованием режима наложения Overlay. Таким образом, я могу использовать его в другом месте и нарисовать с помощью kCGBlendModeNormal, и он будет выглядеть так, как если бы я нарисовал его с помощью kCGBlendModeOverlay. - person samvermette; 29.04.2011
comment
ах, я вижу, я думаю, вы можете объединить несколько рисунков, чтобы сделать это, я не хотел бы кодировать это, как вы, в любом случае, если это сработает ... :) - person Vincent Guerci; 29.04.2011