Фильтры цветов SkiaSharp
Фильтры цветов могут переводить цвета в растровом изображении (или другом изображении) в другие цвета для эффектов, таких как плакатизация:
Чтобы использовать фильтр цветов, задайте ColorFilter
свойство SKPaint
объекта типа SKColorFilter
, созданного одним из статических методов в этом классе. В этой статье показано:
- Преобразование цвета, созданное
CreateColorMatrix
с помощью метода. - Таблица цветов, созданная с
CreateTable
помощью метода.
Преобразование цвета
Преобразование цвета включает использование матрицы для изменения цветов. Как и большинство трехмерных графических систем, SkiaSharp использует матрицы в основном для преобразования точек координат, как показано в статье "Матрица преобразований в SkiaSharp". Кроме SKColorFilter
того, матрица поддерживает преобразования матриц, но матрица преобразует цвета RGB. Некоторые понятия матрицы необходимы для понимания этих преобразований цветов.
Матрица преобразования цвета имеет измерение четырех строк и пяти столбцов:
| M11 M12 M13 M14 M15 | | M21 M22 M23 M24 M25 | | M31 M32 M33 M34 M35 | | M41 M42 M43 M44 M45 |
Он преобразует цвет источника RGB (R, G, B, A) в целевой цвет (R', G', B', A).
При подготовке к умножению матрицы исходный цвет преобразуется в матрицу 5×1:
| R | | G | | B | | A | | 1 |
Эти значения R, G, B и A — это исходные байты от 0 до 255. Они не нормализованы для значений с плавающей запятой в диапазоне от 0 до 1.
Для коэффициента перевода требуется дополнительная ячейка. Это аналогично использованию матрицы 3×3 для преобразования двухмерных точек координат, как описано в разделе "Причина 3-к-3 Матрицы " в статье об использовании матриц для преобразования точек координат.
Матрица 4×5 умножается на матрицу 5×1, а продукт — это матрица 4×1 с преобразованным цветом:
| M11 M12 M13 M14 M15 | | R | | R' | | M21 M22 M23 M24 M25 | | G | | G' | | M31 M32 M33 M34 M35 | × | B | = | B' | | M41 M42 M43 M44 M45 | | A | | A' | | 1 |
Ниже приведены отдельные формулы для R', G', B и A':
R' = M11·R + M12·G + M13·B + M14·A + M15
G' = M21·R + M22·G + M23·B + M24·A + M25
B' = M31·R + M32·G + M33·B + M34·A + M35
A' = M41·R + M42·G + M43·B + M44·A + M45
Большая часть матрицы состоит из мультипликативных факторов, которые обычно находятся в диапазоне от 0 до 2. Однако последний столбец (M15–M45) содержит значения, добавленные в формулы. Эти значения обычно варьируются от 0 до 255. Результаты зажаты между значениями от 0 до 255.
Матрица удостоверений:
| 1 0 0 0 0 | | 0 1 0 0 0 | | 0 0 1 0 0 | | 0 0 0 1 0 |
Это не приводит к изменению цветов. Формулы преобразования:
R' = R
G' = G
B' = B
A' = A
Ячейка M44 очень важна, так как она сохраняет прозрачность. Как правило, это так, что M41, M42 и M43 являются нулевыми, потому что вы, вероятно, не хотите, чтобы прозрачность была основана на красных, зеленых и синих значениях. Но если M44 равно нулю, то "А" будет нулевым, и ничего не будет видно.
Одним из наиболее распространенных вариантов использования цветовой матрицы является преобразование растровой карты цвета в серую масштабируемую растровую карту. Это включает в себя формулу для взвешенный средний показатель красных, зеленых и синих значений. Для отображения видео с помощью цветового пространства SRGB ("стандартный красный зеленый синий") эта формула:
серый оттенок = 0,2126· R + 0.7152· G + 0.0722· B
Чтобы преобразовать цветовую растровую карту в серую масштабируемую растровую карту, результаты R', G и B должны быть равными одному и тому же значению. Матрица:
| 0.21 0.72 0.07 0 0 | | 0.21 0.72 0.07 0 0 | | 0.21 0.72 0.07 0 0 | | 0 0 0 1 0 |
Тип данных SkiaSharp не соответствует этой матрице. Вместо этого необходимо представить матрицу в виде массива из 20 float
значений в порядке строк: первая строка, вторая строка и т. д.
SKColorFilter.CreateColorMatrix
Статический метод имеет следующий синтаксис:
public static SKColorFilter CreateColorMatrix (float[] matrix);
где matrix
массив из 20 float
значений. При создании массива в C#можно легко отформатировать числа, чтобы они напоминали матрицу 4×5. Это показано на странице "Матрица серого масштабирования" в примере:
public class GrayScaleMatrixPage : ContentPage
{
SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
typeof(CenteredTilesPage),
"SkiaSharpFormsDemos.Media.Banana.jpg");
public GrayScaleMatrixPage()
{
Title = "Gray-Scale Matrix";
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();
using (SKPaint paint = new SKPaint())
{
paint.ColorFilter =
SKColorFilter.CreateColorMatrix(new float[]
{
0.21f, 0.72f, 0.07f, 0, 0,
0.21f, 0.72f, 0.07f, 0, 0,
0.21f, 0.72f, 0.07f, 0, 0,
0, 0, 0, 1, 0
});
canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
}
}
}
Метод DrawBitmap
, используемый в этом коде, состоит из файла BitmapExtension.cs , включенного в пример.
Ниже приведен результат работы в iOS, Android и универсальная платформа Windows:
Следите за значением в четвертой строке и четвертом столбце. Это важный фактор, умноженный на значение исходного цвета для значения преобразованного цвета A. Если эта ячейка равна нулю, отображается ничего, и проблема может оказаться сложной.
При эксперименте с цветными матрицами можно рассматривать преобразование либо с точки зрения источника, либо с точки зрения назначения. Как красный пиксель источника способствует красному, зеленому и синему пикселям назначения? Это определяется значениями в первом столбце матрицы. Кроме того, каким образом целевой красный пиксель должен влиять на красный, зеленый и синий пиксели источника? Это определяется первой строкой матрицы.
Некоторые идеи о том, как использовать преобразования цветов, см. на страницах "Перекраска изображений". Обсуждение касается Windows Forms, и матрица является другим форматом, но основные понятия одинаковы.
Матрица пастели вычисляет целевой красный пиксель, затеняя исходный красный пиксель и немного подчеркивая красные и зеленые пиксели. Этот процесс выполняется аналогичным образом для зеленых и синих пикселей:
public class PastelMatrixPage : ContentPage
{
SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
typeof(PastelMatrixPage),
"SkiaSharpFormsDemos.Media.MountainClimbers.jpg");
public PastelMatrixPage()
{
Title = "Pastel Matrix";
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();
using (SKPaint paint = new SKPaint())
{
paint.ColorFilter =
SKColorFilter.CreateColorMatrix(new float[]
{
0.75f, 0.25f, 0.25f, 0, 0,
0.25f, 0.75f, 0.25f, 0, 0,
0.25f, 0.25f, 0.75f, 0, 0,
0, 0, 0, 1, 0
});
canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
}
}
}
Результатом является отключение интенсивности цветов, как можно увидеть здесь:
Цветовые таблицы
SKColorFilter.CreateTable
Статический метод поставляется в двух версиях:
public static SKColorFilter CreateTable (byte[] table);
public static SKColorFilter CreateTable (byte[] tableA, byte[] tableR, byte[] tableG, byte[] tableB);
Массивы всегда содержат 256 записей. В методе CreateTable
с одной таблицей та же таблица используется для красных, зеленых и синих компонентов. Это простая таблица поиска: если исходный цвет имеет значение (R, G, B), а конечный цвет — (R', B', G'), то конечные компоненты получаются путем индексирования table
с помощью исходных компонентов:
R' = table[R]
G' = table[G]
B' = table[B]
Во втором методе каждый из четырех компонентов цвета может иметь отдельную таблицу цветов, или одни и те же таблицы цветов могут быть общими для двух или нескольких компонентов.
Если вы хотите задать один из аргументов второго CreateTable
метода в цветовую таблицу, содержащую значения от 0 до 255 в последовательности, можно использовать null
вместо этого. Очень часто CreateTable
вызов имеет null
первый аргумент для альфа-канала.
В разделе " Плакатизация " статьи о доступе к битам растрового изображения SkiaSharp вы узнали, как изменить отдельные биты растрового изображения, чтобы уменьшить разрешение цвета. Это метод, называемый афистеризацией.
Вы также можете плакать растровое изображение с помощью цветовой таблицы. Конструктор страницы "Плакатизация таблицы " создает цветовую таблицу, которая сопоставляет его индекс с байтами с нижними 6 битами, равными нулю:
public class PosterizeTablePage : ContentPage
{
SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
typeof(PosterizeTablePage),
"SkiaSharpFormsDemos.Media.MonkeyFace.png");
byte[] colorTable = new byte[256];
public PosterizeTablePage()
{
Title = "Posterize Table";
// Create color table
for (int i = 0; i < 256; i++)
{
colorTable[i] = (byte)(0xC0 & i);
}
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();
using (SKPaint paint = new SKPaint())
{
paint.ColorFilter =
SKColorFilter.CreateTable(null, null, colorTable, colorTable);
canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
}
}
}
Программа выбирает использовать эту таблицу цветов только для зеленых и синих каналов. Красный канал продолжает иметь полное разрешение:
Для различных цветовых каналов можно использовать различные таблицы цветов для различных эффектов.