0

See the following image from the output of a 24-bit color ANSI library for .NET Core I'm writing. I would like to improve the DrawBox function, which draws the rectangular outlines to gradient boxes to retain the underlaying background color attribute from the screen buffer as a new character is written.

ReadConsoleOutput lets me get the screen buffer at a certain location, but CHAR_INFO gets attributes that reflect the standard 16-color version. Is there a way to get the 24-bit color of the foreground and background attribute of a character at a certain screen buffer location?

https://learn.microsoft.com/en-us/windows/console/readconsoleoutput

https://learn.microsoft.com/en-us/windows/console/char-info-str

enter image description here

John Ernest
  • 785
  • 1
  • 8
  • 20
  • Do you want to get the RGB values of a character? – Strive Sun Jun 05 '20 at 07:54
  • @StriveSun-MSFT yes that is correct, when I look at the attributes produced by ReadConsoleOutput it lets me know that the red, green, and blue bit flags of the attribute were set, but that’s as far as it goes, I don’t know how and want to know how to get the extended RGB values for colors that were produced earlier by esc[38;2;RG;Bm or esc[48;2;R;G;Bm off the screen buffer that may have been produced prior to the execution of the app on the same console. – John Ernest Jun 05 '20 at 08:01
  • @StriveSun-MSFT I take it by the deletion of your other comments that the results of your research were unfavorable? Seems like something that should have been implemented in the VT standard across the board as a csi code. – John Ernest Jun 06 '20 at 07:34
  • The win32 console window does not support gradient background. How does your project develop gradient colors? Can I think your purpose is to read the RGB color value of any point on your window?Please see this [link](https://github.com/Microsoft/WSL/issues/1118#issuecomment-249240033). – Strive Sun Jun 08 '20 at 07:57
  • @StriveSun-MSFT very easily in C# just a linear interpolation between a start and end color with an x/y/size/width defined, then esc[48;2;R;G;Bm VT codes and use the space character. However, that overwrites the existing rectangle of the screen buffer entirely. So as a workaround to this rectangle gradient function I return an array of the linear interpolated colors for now. I will be releasing a console library soon for C#. – John Ernest Jun 10 '20 at 09:07
  • @StriveSun-MSFT to clarify, yes, my purpose in this question was to see if the RGB color value could be read for any point in the window. The only workaround I can see is to clear the screen at the beginning of your app and keep track of the background colors at each point in the current screen. – John Ernest Jun 11 '20 at 05:05
  • I'm sorry, I didn't understand your workaround. Why need to clear the screen at the beginning of the app? I have submitted a request internally, regarding whether there is an API to read the console 24-bit color, this may need takes some time. If you have any progress on your question, please feel free to update the thread. – Strive Sun Jun 12 '20 at 06:14
  • Hi, I have received an internal response. There is no API for getting the 24-bit color of the console. – Strive Sun Jun 15 '20 at 01:53
  • @StriveSun-MSFT that’s what I figured. – John Ernest Jun 16 '20 at 02:44
  • Maybe you can use some algorithms to calculate the color value of each coordinate point. I have not tried this, but it is similar to what you said above. – Strive Sun Jun 19 '20 at 06:04
  • @StriveSun-MSFT check the answer it's basically the same. – John Ernest Jun 19 '20 at 06:38

1 Answers1

1

This is the workaround I use in the meantime, which is just simply to keep track of the background values manually in result, so that if I want to composite with a new foreground I can do so at a specific x/y value.

    var background1 = GradientRectangle(
        new Point() { X = 2, Y = 2 },
        new Size() { Width = 40, Height = 10 },
        new RGBColor() { R = 0, G = 0, B = 127 },
        new RGBColor() { R = 0, G = 0, B = 0 },
        ' ', true);

    public List<RGBColor> GradientRectangle(Point startPoint, Size size, RGBColor startColor, RGBColor endColor, ushort character = (ushort)' ', bool horizontal = false)
    {
        List<RGBColor> result = new List<RGBColor>();
        if (horizontal)
        {
            int idx = 0;
            for (int x = startPoint.X; x <= startPoint.X + size.Width; x++)
            {
                float t = (float)idx / (float)size.Width;
                RGBColor lerpColor = startColor.Lerp(endColor, t);
                SetBackgroundColor(lerpColor);
                for (int y = startPoint.Y; y <= startPoint.Y + size.Height; y++)
                {
                    SetCursor(new Point() { X = x, Y = y });
                    Console.Write(""+(char)character);
                }
                result.Add(lerpColor);
                idx++;
            }
        }
        else
        {
            int idx = 0;
            for (int y = startPoint.Y; y <= startPoint.Y + size.Height; y++)
            {
                float t = (float)idx / (float)size.Height;
                SetCursor(new Point() { X = startPoint.X, Y = y });
                RGBColor lerpColor = startColor.Lerp(endColor, t);
                SetBackgroundColor(lerpColor);
                Console.Write("".PadLeft(size.Width+1, (char)character));
                result.Add(lerpColor);
                idx++;
            }
        }
        return result;
    }
John Ernest
  • 785
  • 1
  • 8
  • 20