Чтение значений 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;
}