in src/Avalonia.Controls.ColorPicker/Helpers/ColorPickerHelpers.cs [39:321]
public static Task CreateComponentBitmapAsync(
PooledList<byte> bgraPixelData,
int width,
int height,
Orientation orientation,
ColorModel colorModel,
ColorComponent component,
HsvColor baseHsvColor,
bool isAlphaVisible,
bool isPerceptive)
{
if (width == 0 || height == 0)
{
return Task.CompletedTask;
}
return Task.Run(() =>
{
int pixelDataIndex = 0;
double componentStep;
Color baseRgbColor = Colors.White;
Color rgbColor;
int bgraPixelDataHeight;
int bgraPixelDataWidth;
// BGRA formatted color components 1 byte each (4 bytes in a pixel)
bgraPixelDataHeight = height * 4;
bgraPixelDataWidth = width * 4;
// Maximize alpha component value
if (isAlphaVisible == false &&
component != ColorComponent.Alpha)
{
baseHsvColor = new HsvColor(1.0, baseHsvColor.H, baseHsvColor.S, baseHsvColor.V);
}
// Convert HSV to RGB once
if (colorModel == ColorModel.Rgba)
{
baseRgbColor = baseHsvColor.ToRgb();
}
// Apply any perceptive adjustments to the color
if (isPerceptive &&
component != ColorComponent.Alpha)
{
if (colorModel == ColorModel.Hsva)
{
// Maximize Saturation and Value components
switch (component)
{
case ColorComponent.Component1: // Hue
baseHsvColor = new HsvColor(baseHsvColor.A, baseHsvColor.H, 1.0, 1.0);
break;
case ColorComponent.Component2: // Saturation
baseHsvColor = new HsvColor(baseHsvColor.A, baseHsvColor.H, baseHsvColor.S, 1.0);
break;
case ColorComponent.Component3: // Value
baseHsvColor = new HsvColor(baseHsvColor.A, baseHsvColor.H, 1.0, baseHsvColor.V);
break;
}
}
else
{
// Minimize component values other than the current one
switch (component)
{
case ColorComponent.Component1: // Red
baseRgbColor = new Color(baseRgbColor.A, baseRgbColor.R, 0, 0);
break;
case ColorComponent.Component2: // Green
baseRgbColor = new Color(baseRgbColor.A, 0, baseRgbColor.G, 0);
break;
case ColorComponent.Component3: // Blue
baseRgbColor = new Color(baseRgbColor.A, 0, 0, baseRgbColor.B);
break;
}
}
}
// Create the color component gradient
if (orientation == Orientation.Horizontal)
{
// Determine the numerical increment of the color steps within the component
if (colorModel == ColorModel.Hsva)
{
if (component == ColorComponent.Component1)
{
componentStep = 360.0 / width;
}
else
{
componentStep = 1.0 / width;
}
}
else
{
componentStep = 255.0 / width;
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (y == 0)
{
rgbColor = GetColor(x * componentStep);
// Get a new color
bgraPixelData[pixelDataIndex + 0] = Convert.ToByte(rgbColor.B * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 1] = Convert.ToByte(rgbColor.G * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 2] = Convert.ToByte(rgbColor.R * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 3] = rgbColor.A;
}
else
{
// Use the color in the row above
// Remember the pixel data is 1 dimensional instead of 2
bgraPixelData[pixelDataIndex + 0] = bgraPixelData[pixelDataIndex + 0 - bgraPixelDataWidth];
bgraPixelData[pixelDataIndex + 1] = bgraPixelData[pixelDataIndex + 1 - bgraPixelDataWidth];
bgraPixelData[pixelDataIndex + 2] = bgraPixelData[pixelDataIndex + 2 - bgraPixelDataWidth];
bgraPixelData[pixelDataIndex + 3] = bgraPixelData[pixelDataIndex + 3 - bgraPixelDataWidth];
}
pixelDataIndex += 4;
}
}
}
else
{
// Determine the numerical increment of the color steps within the component
if (colorModel == ColorModel.Hsva)
{
if (component == ColorComponent.Component1)
{
componentStep = 360.0 / height;
}
else
{
componentStep = 1.0 / height;
}
}
else
{
componentStep = 255.0 / height;
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x == 0)
{
// The lowest component value should be at the 'bottom' of the bitmap
rgbColor = GetColor((height - 1 - y) * componentStep);
// Get a new color
bgraPixelData[pixelDataIndex + 0] = Convert.ToByte(rgbColor.B * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 1] = Convert.ToByte(rgbColor.G * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 2] = Convert.ToByte(rgbColor.R * rgbColor.A / 255);
bgraPixelData[pixelDataIndex + 3] = rgbColor.A;
}
else
{
// Use the color in the column to the left
// Remember the pixel data is 1 dimensional instead of 2
bgraPixelData[pixelDataIndex + 0] = bgraPixelData[pixelDataIndex - 4];
bgraPixelData[pixelDataIndex + 1] = bgraPixelData[pixelDataIndex - 3];
bgraPixelData[pixelDataIndex + 2] = bgraPixelData[pixelDataIndex - 2];
bgraPixelData[pixelDataIndex + 3] = bgraPixelData[pixelDataIndex - 1];
}
pixelDataIndex += 4;
}
}
}
Color GetColor(double componentValue)
{
Color newRgbColor = Colors.White;
switch (component)
{
case ColorComponent.Component1:
{
if (colorModel == ColorModel.Hsva)
{
// Sweep hue
newRgbColor = HsvColor.ToRgb(
MathUtilities.Clamp(componentValue, 0.0, 360.0),
baseHsvColor.S,
baseHsvColor.V,
baseHsvColor.A);
}
else
{
// Sweep red
newRgbColor = new Color(
baseRgbColor.A,
Convert.ToByte(MathUtilities.Clamp(componentValue, 0.0, 255.0)),
baseRgbColor.G,
baseRgbColor.B);
}
break;
}
case ColorComponent.Component2:
{
if (colorModel == ColorModel.Hsva)
{
// Sweep saturation
newRgbColor = HsvColor.ToRgb(
baseHsvColor.H,
MathUtilities.Clamp(componentValue, 0.0, 1.0),
baseHsvColor.V,
baseHsvColor.A);
}
else
{
// Sweep green
newRgbColor = new Color(
baseRgbColor.A,
baseRgbColor.R,
Convert.ToByte(MathUtilities.Clamp(componentValue, 0.0, 255.0)),
baseRgbColor.B);
}
break;
}
case ColorComponent.Component3:
{
if (colorModel == ColorModel.Hsva)
{
// Sweep value
newRgbColor = HsvColor.ToRgb(
baseHsvColor.H,
baseHsvColor.S,
MathUtilities.Clamp(componentValue, 0.0, 1.0),
baseHsvColor.A);
}
else
{
// Sweep blue
newRgbColor = new Color(
baseRgbColor.A,
baseRgbColor.R,
baseRgbColor.G,
Convert.ToByte(MathUtilities.Clamp(componentValue, 0.0, 255.0)));
}
break;
}
case ColorComponent.Alpha:
{
if (colorModel == ColorModel.Hsva)
{
// Sweep alpha
newRgbColor = HsvColor.ToRgb(
baseHsvColor.H,
baseHsvColor.S,
baseHsvColor.V,
MathUtilities.Clamp(componentValue, 0.0, 1.0));
}
else
{
// Sweep alpha
newRgbColor = new Color(
Convert.ToByte(MathUtilities.Clamp(componentValue, 0.0, 255.0)),
baseRgbColor.R,
baseRgbColor.G,
baseRgbColor.B);
}
break;
}
}
return newRgbColor;
}
return bgraPixelData;
});
}