Чтение значений RGB консольной цветовой палитры

Мясо

В C или C++ есть ли способ непосредственно прочитать значения RGB цветовой палитры? Особенно интересным является расширенное цветовое пространство, используемое xterm (и другими) для определения до 256 терминальных цветов.

Картофель

Например, я хочу определить свои собственные цвета (используя escape-последовательности ANSI, например, \e]4;3;rgb:cc/78/33\e\\или непосредственно в c), но мне нужно сохранить цвета пользователей перед тем, как переопределить их (в маловероятном случае, когда они уже переопределили свои цвета), чтобы я мог восстановить их после завершения моей программы. Нечеткая настройка пользователя не хороша.

Прямо сейчас я собираюсь использовать escape-последовательности ANSI, чтобы сделать это клиентским способом. Но так как я не могу найти, как вы получаете цвета, я начинаю изучать это в c или C++.

Решение будет написано как рубиновый гем с собственным расширением (в основном это встроенный код c или C++), и я буду стремиться получить кроссплатформенное решение, даже если основной целью является OS X и, во-вторых, среды Linux...

Sause

Из моих первоначальных экспериментов я дошел до того, что я могу определить любые цвета, которые я хочу для кодовой точки в цветовой палитре. Я также могу легко восстановить системные цвета по умолчанию (так как они являются стандартом ANSI). Я искал способ сделать это в управляющих кодах ANSI, но не нашел ни одного. Я полагаю, что это где-то хранится в памяти, и, если есть какой-то способ найти, читать цвета должно быть легко...

Десерт

Подведем итоги информации в комментариях:

Похоже, что единственный способ сделать это последовательно - это распечатать экран из █ символов разных цветов и извлечь из него цвета. Поскольку предполагается, что этот проект будет кроссплатформенным по всем трем основным ОС, а Linux в настоящее время имеет 3 диспетчера отображения пользователей при их использовании, а в Windows два (7 и 8), я могу только представить, сколько часов удовольствия я потрачу на это. было бы:)

Поэтому мое "решение"™ заключается в том, чтобы просто помять цвета пользователей (если у них было что-то кроме системных значений по умолчанию... что, давайте посмотрим правде в глаза, это довольно необычно). Я предоставлю файл настроек, где пользователь может сообщить плагину, какие цвета должны быть восстановлены, если они не удовлетворены настройками системы по умолчанию. Прагматичный и скучный, но это заставляет меня снова идти на это:)

3 ответа

[Edit 1] извините, это не приводит к решению, но для других я добавил доступ к IO палитры ЦАП

посмотрите старые устаревшие ссылки на EGA/VGA...

  • Вы можете получить доступ к палитре через I/O
  • я думаю, что это были порты 0x03C8, 0x03C9 hex.
  • конечно в современной ОС у вас нет к ней доступа
  • так что попробуйте в DOS-BOX или что-нибудь еще и сохраните исходные значения палитры, они должны быть одинаковыми.

для прямого доступа попробуйте это:

BYTE r,g,b,c=5; // R,G,B values are 6 bit only !!!
out 0x3C8,c;    // set color index to work with <0,255>
in  r,0x3C9;    // read color pallete for color c
in  g,0x3C9;    // not sure if it should be r,g,b 
in  b,0x3C9;    // or b,g,r ... i did not use it for too many years
out 0x3C8,c;    // set color index to work with <0,255>
out 0x3C9,r;    // write color pallete for color c
out 0x3C9,g;
out 0x3C9,b;

C / C++ не имеет операций in,out, поэтому используйте это:

BYTE i,o;       // this must be local !!!
WORD port;      // this must be local !!!
asm {
    mov dx,port // in i,port
    in al,dx
    mov o,al

    mov dx,port // out port,o
    mov al,o
    out dx,al
    }

С помощью xterm (и некоторых аналогов) вы можете использовать escape-последовательности для получения цветовой палитры. Это задокументировано в XTerm Control Sequences:

OSC Пс ; Пт ST

Задайте параметры текста. Некоторые управляющие последовательности возвращают информацию:
Ps = 4 ; в ; spec ⇒ Изменить номер цвета c на цвет, указанный в спецификации.
Если "?" дается, а не имя или спецификация RGB,xterm отвечает управляющей последовательностью той же формы, которая может использоваться для установки соответствующего цвета. Поскольку в одной управляющей последовательности может быть задано более одной пары номера цвета и спецификации,xterm может дать более одного ответа.

Делать это можно медленно. xterm предоставляет escape-последовательности для управления цветовой палитрой в стеке:

Вечера # P
Поместить текущие цвета динамической и ANSI-палитры в стек (XTPUSHCOLORS),xterm. Параметры (целые числа в диапазоне от 1 до 10, так как значение по умолчанию 0 будет помещено в стек) могут использоваться для сохранения палитры в стек без помещения в стек.

CSI Pm # Q
Всплывающий стек для установки цветов динамической и ANSI-палитры (XTPOPCOLORS),xterm. Параметры (целые числа в диапазоне от 1 до 10, так как по умолчанию будет выталкиваться 0) могут использоваться для восстановления палитры из стека без извлечения.

Журналы изменений для iTerm2 и Windows Terminal указывают, что они поддерживают эти функции xterm.

      /* Hi -- I think this C code will reveal all that you need to do all that you asked.  Best wishes...*/
/*--------------------------------------------------------------------------

 CONSOLE_LEGACY_PALETTE.C

 Code by Greg Spears 
 Created 2022.10.22 and released into the public domain.
 Tested, use at your own risk.
---------------------------------------------------------------------------*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

/* This is what the palette used to be before it was updated by Microsoft in 2017.*/
BYTE legacy_palette[16][3] = {
{0,0,0 },
{0,0,128},
{0,128,0},
{0,128,128},
{128,0,0},
{128,0,128},
{128,128,0},
{192,192,192},
{128,128,128},
{0,0,255},
{0,255,0},
{0,255,255},
{255,0,0},
{255,0,255},
{255,255,0},
{255,255,255}
};

/* Used for displaying the color palette by printf()*/
static char *szTextColors[] = {
"BLACK",
"BLUE",
"GREEN",
"CYAN",
"RED",
"MAGENTA",
"BROWN",
"LIGHTGRAY",
"DARKGRAY",
"LIGHTBLUE",
"LIGHTGREEN",
"LIGHTCYAN",
"LIGHTRED",
"LIGHTMAGENTA",
"YELLOW",
"WHITE"
};


/*--------------------------------------------------------------------------

set_legacy_palette()

DATE:       REASON:
2022.10.22 - Created 

Params: none
Returns: TRUE if the console palette updates successfully.  FALSE if not.

---------------------------------------------------------------------------*/
int set_legacy_palette(void)
{
    CONSOLE_SCREEN_BUFFER_INFOEX csbix;
    int iii;
    HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);

    if(!hConOut)
    {
        printf("set_legacy_palette():  bad handle: hConOut");
        return FALSE;
    }

    /* Use GetConsoleScreenBufferInfoEx() to get the console palette*/
    csbix.cbSize = sizeof(csbix);
    if(!GetConsoleScreenBufferInfoEx(hConOut, &csbix))
    {
        printf("GetConsoleScreenBufferInfoEx() failed!");
        return FALSE;
    }

    printf("printing color palette: --------------------------\n");
    for (iii = 0; iii < 16; iii++)
        printf("ColorTable[%d] =  \t%-12s [%3d,%3d,%3d]\n", iii, szTextColors[iii], 
            GetRValue(csbix.ColorTable[iii]), 
            GetGValue(csbix.ColorTable[iii]), 
            GetBValue(csbix.ColorTable[iii]));
    printf("--------------------------------------------------\n");

    /* Fill the palette strcuture with legacy RGB values*/
    for(iii = 0; iii < 16; iii++)
        csbix.ColorTable[iii] = 
            RGB(legacy_palette[iii][0], legacy_palette[iii][1], legacy_palette[iii][2]);

    /* use SetConsoleScreenBufferInfoEx() to send the updated palette to the OS.
    */
    if (!SetConsoleScreenBufferInfoEx(hConOut, &csbix))
    {
        printf("set_legacy_palette(): SetConsoleScreenBufferInfoEx() failed!");
        return FALSE;
    }
    return TRUE;
}
Другие вопросы по тегам