Неразделимые режимы смешения
Как вы видели в статье SkiaSharp сепарируемые режимы смешения, режимы сепарируемых смешения выполняют операции с красными, зелеными и голубыми каналами отдельно. Неразделимые режимы смешивания не выполняются. Работая на уровнях цвета hue, Saturation и Luminosity, режимы неразделимого смешения могут изменять цвета интересными способами:
Модель Hue-Saturation-Luminosity
Чтобы понять неразделимые режимы смешения, необходимо обрабатывать конечные и исходные пиксели как цвета в модели Hue-Saturation-Luminosity. (Luminosity также называется Lightness.)
Цветовая модель HSL обсуждалась в статье Интеграция с Xamarin.Formsи пример программы в этой статье позволяет экспериментировать с цветами HSL. Можно создать значение с помощью значений SKColor
Hue, Saturation и Luminosity с помощью статического SKColor.FromHsl
метода.
Hue представляет доминирующую длину волны цвета. Значения Hue варьируются от 0 до 360 и циклически через аддитивные и субтрактивные первичные элементы: красный — 0, желтый — 60, зеленый — 120, синий — 180, синий — 240, 300, а цикл возвращается к красному в 360.
Если нет доминирующего цвета , например, цвет белый или черный или серый оттенк , то Hue не определен и обычно имеет значение 0.
Значения насыщенности могут варьироваться от 0 до 100 и указывать чистоту цвета. Значение насыщенности 100 является самым чистым цветом, а значения ниже 100 приводят к тому, что цвет становится более серым. Значение насыщенности 0 приводит к оттенку серого.
Значение Luminosity (или Lightness) указывает, насколько яркий цвет. Значение Luminosity 0 черное независимо от других параметров. Аналогичным образом значение Luminosity 100 является белым.
Значение HSL (0, 100, 50) — это значение RGB (FF, 00, 00), которое является чистым красным. Значение HSL (180, 100, 50) — это rgb-значение (00, FF, FF), чистое синя. По мере уменьшения насыщенности основной цветной компонент уменьшается, а другие компоненты увеличиваются. На уровне насыщенности 0 все компоненты одинаковы, и цвет является серым оттенком. Уменьшите светимость, чтобы перейти к черному; увеличьте Luminosity, чтобы перейти к белому.
Режимы смешения подробно
Как и в других режимах смешения, четыре неразделимых режима смешения включают назначение (это часто растровое изображение) и источник, который часто является одним цветом или градиентом. Режимы смешивания объединяют значения Hue, Saturation и Luminosity из назначения и источника:
Режим смешивания | Компоненты из источника | Компоненты из назначения |
---|---|---|
Hue |
Оттенок | Насыщенность и светимость |
Saturation |
Насыщенность | Hue и Luminosity |
Color |
Оттенки и насыщенность | Яркость |
Luminosity |
Яркость | Оттенки и насыщенность |
См. спецификацию W3C Compositing и Blending Level 1 для алгоритмов.
Страница режимов Picker
неразрывной смешивания содержит один из этих режимов смешения и три Slider
представления, чтобы выбрать цвет HSL:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
xmlns:skiaviews="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="SkiaSharpFormsDemos.Effects.NonSeparableBlendModesPage"
Title="Non-Separable Blend Modes">
<StackLayout>
<skiaviews:SKCanvasView x:Name="canvasView"
VerticalOptions="FillAndExpand"
PaintSurface="OnCanvasViewPaintSurface" />
<Picker x:Name="blendModePicker"
Title="Blend Mode"
Margin="10, 0"
SelectedIndexChanged="OnPickerSelectedIndexChanged">
<Picker.ItemsSource>
<x:Array Type="{x:Type skia:SKBlendMode}">
<x:Static Member="skia:SKBlendMode.Hue" />
<x:Static Member="skia:SKBlendMode.Saturation" />
<x:Static Member="skia:SKBlendMode.Color" />
<x:Static Member="skia:SKBlendMode.Luminosity" />
</x:Array>
</Picker.ItemsSource>
<Picker.SelectedIndex>
0
</Picker.SelectedIndex>
</Picker>
<Slider x:Name="hueSlider"
Maximum="360"
Margin="10, 0"
ValueChanged="OnSliderValueChanged" />
<Slider x:Name="satSlider"
Maximum="100"
Margin="10, 0"
ValueChanged="OnSliderValueChanged" />
<Slider x:Name="lumSlider"
Maximum="100"
Margin="10, 0"
ValueChanged="OnSliderValueChanged" />
<StackLayout Orientation="Horizontal">
<Label x:Name="hslLabel"
HorizontalOptions="CenterAndExpand" />
<Label x:Name="rgbLabel"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
</ContentPage>
Чтобы сэкономить место, три Slider
представления не определены в пользовательском интерфейсе программы. Вам нужно помнить, что порядок — Hue, Saturation и Luminosity. Два Label
представления в нижней части страницы показывают значения цветов HSL и RGB.
Файл кода загрузит один из ресурсов растрового изображения, отображает, что максимально большой размер на холсте, а затем охватывает холст прямоугольником. Цвет прямоугольника основан на трех Slider
представлениях, а режим смешивания — один из следующих вариантов:Picker
public partial class NonSeparableBlendModesPage : ContentPage
{
SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
typeof(NonSeparableBlendModesPage),
"SkiaSharpFormsDemos.Media.Banana.jpg");
SKColor color;
public NonSeparableBlendModesPage()
{
InitializeComponent();
}
void OnPickerSelectedIndexChanged(object sender, EventArgs args)
{
canvasView.InvalidateSurface();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
{
// Calculate new color based on sliders
color = SKColor.FromHsl((float)hueSlider.Value,
(float)satSlider.Value,
(float)lumSlider.Value);
// Use labels to display HSL and RGB color values
color.ToHsl(out float hue, out float sat, out float lum);
hslLabel.Text = String.Format("HSL = {0:F0} {1:F0} {2:F0}",
hue, sat, lum);
rgbLabel.Text = String.Format("RGB = {0:X2} {1:X2} {2:X2}",
color.Red, color.Green, color.Blue);
canvasView.InvalidateSurface();
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform);
// Get blend mode from Picker
SKBlendMode blendMode =
(SKBlendMode)(blendModePicker.SelectedIndex == -1 ?
0 : blendModePicker.SelectedItem);
using (SKPaint paint = new SKPaint())
{
paint.Color = color;
paint.BlendMode = blendMode;
canvas.DrawRect(info.Rect, paint);
}
}
}
Обратите внимание, что программа не отображает значение цвета HSL, выбранное тремя ползунками. Вместо этого он создает значение цвета из этих ползунков, а затем использует ToHsl
метод для получения значений Hue, Saturation и Luminosity. Это связано с тем, что FromHsl
метод преобразует цвет HSL в цвет RGB, который хранится внутри SKColor
структуры. Метод ToHsl
преобразуется из RGB в HSL, но результат не всегда будет исходным значением.
Например, FromHsl
преобразует значение HSL (180, 50, 0) в цвет RGB (0, 0, 0), так как Luminosity
значение равно нулю. Метод ToHsl
преобразует цвет RGB (0, 0, 0, 0) в цвет HSL (0, 0, 0), так как значения оттенка и насыщенности не имеют значения. При использовании этой программы лучше увидеть представление цвета HSL, используемого программой, а не указанного с ползунками.
В режиме SKBlendModes.Hue
смешивания используется уровень Hue источника при сохранении уровней насыщенности и luminosity назначения. При тестировании этого режима смешивания необходимо задать ползунки насыщенности и светимости, отличные от 0 или 100, так как в этих случаях Hue не определяется уникальным образом.
При использовании ползунка значение 0 (как и с снимок экрана iOS слева), все становится красным. Но это не означает, что изображение полностью отсутствует зеленого и синего. Очевидно, что в результате по-прежнему присутствуют серые оттенки. Например, цвет RGB (40, 40, C0) эквивалентен цвету HSL (240, 50, 50). Hue синий, но значение насыщенности 50 указывает, что также есть красные и зеленые компоненты. Если для hue задано значение 0, то цвет HSL имеет значение (0 SKBlendModes.Hue
, 50, 50), который является цветом RGB (C0, 40, 40). Есть все еще синий и зеленый компоненты, но теперь доминирующий компонент красный.
Режим SKBlendModes.Saturation
смешивания объединяет уровень насыщенности источника с Hue и Luminosity назначения. Как и Hue, насыщенность не определена, если Luminosity равно 0 или 100. В теории, любой параметр Luminosity между этими двумя крайностями должен работать. Тем не менее, параметр Luminosity, кажется, влияет на результат больше, чем он должен. Задайте значение 50 светимости, и вы увидите, как задать уровень насыщенности рисунка:
Этот режим смешения можно использовать для увеличения насыщенности цвета скучного изображения или уменьшения насыщенности до нуля (как на снимке экрана iOS слева) для результирующих изображений, состоящих только из серых оттенков.
Режим SKBlendModes.Color
смешивания сохраняет Luminosity назначения, но использует Hue и Saturation источника. Опять же, это означает, что любой параметр ползунка Luminosity где-то между крайностями должен работать.
Вскоре вы увидите приложение этого режима смешивания.
Наконец, SKBlendModes.Luminosity
режим смешивания является противоположностью SKBlendModes.Color
. Он сохраняет хью и насыщенность назначения, но использует Luminosity источника. Режим Luminosity
смешивания является самым таинственным из пакета: ползунки Hue и Saturation влияют на изображение, но даже на средний Luminosity, изображение не отличается:
В теории увеличение или уменьшение светимости изображения должно сделать его светлее или темнее. Этот пример свойства Luminosity или этот S КБ lendMode Enum может быть интересен.
Обычно это не так, что вы хотите использовать один из неразделимых режимов смешения с источником, состоящим из одного цвета, примененного ко всему целевому изображению. Эффект слишком велик. Вы хотите ограничить эффект одной частью изображения. В этом случае источник, вероятно, будет включать транспараранность, или, возможно, источник будет ограничен меньшим графическим элементом.
Матовый для разрежимаемого режима
Ниже приведен один из растровых изображений, включенных в пример в качестве ресурса. Имя файла Banana.jpg:
Можно создать матовое, которое охватывает только банан. Это также ресурс в примере. Имя файла BananaMatte.png:
Помимо черной фигуры банана, остальная часть растрового изображения является прозрачной.
Синяя банановая страница использует этот мат для изменения Hue и насыщенности банана , что обезьяна держит, но изменить ничего другого в изображении.
В следующем BlueBananaPage
классе Banana.jpg растровое изображение загружается в виде поля. Конструктор загружает растровое изображение BananaMatte.png как matteBitmap
объект, но он не сохраняет этот объект за пределами конструктора. Вместо этого создается третье растровое изображение blueBananaBitmap
. Нарисуется blueBananaBitmap
matteBitmap
наследуемом SKPaint
с Color
его набором синего цвета и его BlendMode
наборомSKBlendMode.SrcIn
. Остается blueBananaBitmap
в основном прозрачным, но с твердым синим изображением банана:
public class BlueBananaPage : ContentPage
{
SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
typeof(BlueBananaPage),
"SkiaSharpFormsDemos.Media.Banana.jpg");
SKBitmap blueBananaBitmap;
public BlueBananaPage()
{
Title = "Blue Banana";
// Load banana matte bitmap (black on transparent)
SKBitmap matteBitmap = BitmapExtensions.LoadBitmapResource(
typeof(BlueBananaPage),
"SkiaSharpFormsDemos.Media.BananaMatte.png");
// Create a bitmap with a solid blue banana and transparent otherwise
blueBananaBitmap = new SKBitmap(matteBitmap.Width, matteBitmap.Height);
using (SKCanvas canvas = new SKCanvas(blueBananaBitmap))
{
canvas.Clear();
canvas.DrawBitmap(matteBitmap, new SKPoint(0, 0));
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Blue;
paint.BlendMode = SKBlendMode.SrcIn;
canvas.DrawPaint(paint);
}
}
SKCanvasView canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform);
using (SKPaint paint = new SKPaint())
{
paint.BlendMode = SKBlendMode.Color;
canvas.DrawBitmap(blueBananaBitmap,
info.Rect,
BitmapStretch.Uniform,
paint: paint);
}
}
}
Обработчик PaintSurface
рисует растровое изображение с обезьяной, удерживая банан. За этим кодом следует отображение blueBananaBitmap
с помощью SKBlendMode.Color
. На поверхности банана каждый пиксель Hue и Saturation заменен твердым синим цветом, который соответствует значению оттенка 240 и насыщенности 100. Тем не менее, Luminosity остается тем же, что означает, что банан продолжает иметь реалистичную текстуру, несмотря на его новый цвет:
Попробуйте изменить режим SKBlendMode.Saturation
смешивания на . Банан остается желтым, но это более интенсивный желтый. В реальном приложении это может быть более желательным эффектом, чем превратить банан синие.