public static Task CreateComponentBitmapAsync()

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;
            });
        }