Discussion:
цвета
(слишком старое сообщение для ответа)
Aleksey Kozlov
2009-04-08 16:53:09 UTC
Permalink
Hi, All!

Имеется дельфийский компонент. Он отрисовывается в памяти на битмап 24bpp, и
копируется на канву функцией BitBlt. В режиме экрана 24bpp компонент имеет
одинаковый оттенок с окружающими панелями, а при 16bpp - чуть светлее. Скриншот
даёт, что компонент имеет честный цвет clSilver = C0C0C0, а окружающие панели и
другие программы, к примеру, встроенный виндовый калькулятор, имеют цвет
BFBFBF.
Получается если заливать прямоугольник с помощью FillRect, цвет выходит
"левый", но вот GetPixel возвращает исходный C0C0C0, т.е. преобразование
работает в обе стороны.
Особенно странно, что C0 круглое число, делится на что угодно, и как его можно
округлить до BF непонятно, как раз обратное было бы более объяснимо.
Собственно вопрос а) как это получается?
и б) как с этим бороться?
Пока покрасил компонент в BFBFBF, при 16 битовом цвете разницы с фоном нет. При
32 битном - тоже. Совсем уже ничего не понимаю. В любом случае есть в этом что
то неправильное.

With best regards, Aleksey.
Michael Mamaev
2009-04-08 17:28:33 UTC
Permalink
Хайль Гитлеp капyт, Aleksey!
Сpеда Апpель 08 2009 21:53, Aleksey Kozlov wrote to All:

AK> Имеется дельфийский компонент.

[...лишние бyквы выpезаны...]

AK> В любом слyчае есть в этом что то непpавильное.



Майкл
Nickita A Startcev
2009-04-08 16:34:56 UTC
Permalink
Привет, Aleksey !


08 Apr 09 , 21:53 Aleksey Kozlov писал к All:

AK> Имеется дельфийский компонент. Он отрисовывается в памяти на битмап
AK> 24bpp, и копируется на канву функцией BitBlt. В режиме экрана 24bpp
AK> компонент имеет одинаковый оттенок с окружающими панелями, а при 16bpp
AK> - чуть светлее. Скриншот даёт, что компонент имеет честный цвет
AK> clSilver = C0C0C0, а окружающие панели и другие программы, к примеру,
AK> встроенный виндовый калькулятор, имеют цвет BFBFBF.

Цвет панелей надо брать из системных настроек.

. С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Редкий Карлсон долетит до середины моей крыши
Aleksey Kozlov
2009-04-11 04:21:22 UTC
Permalink
Hi, Nickita A Startcev!

08 Apr 09 21:34, you wrote to me:

NS> Цвет панелей надо брать из системных настроек.

Да естественно, они изначально были именно системными цветами, потом уже в
плане экспериментов перешел к физическим цветам. И это, как мне кажется,
понятней для объяснения ситуации, чем цвет Рельефных Объектов.
Кстати, на NT4 всё выглядит нормально. Единственная правильная ось, в остальных
либо глюк, либо неизвестная мне фича. Получается, что и красить компонент
наугад в BFBFBF тоже не выход, так как в NT4 он выглядит как и должен
выглядить, более тёмным, чем серебристые панели.
Ещё раз повторю ситуацию, может быть, несколько с другого ракурса. В 16 битном
режиме экрана берём цвет, неважно системный цвет Рельефных Объектов aka
clBtnFace или физический clSilver aka $C0C0C0 и заливаем им некую панель
функцией FillRect. Естественно наш цвет преобразуется в некий 16 битный.
Теперь берём 24 битный битмап в памяти и заливаем его той же функцией, тем же
цветом. Теперь копируем битмап на панель функцией BitBlt(..., SRCCOPY); опять
же 24 битный цвет преобразуются в 16 битный. В NT цвета получаются идентичными,
в ХР и 98 - они отличаются.
Вот собственно и суть вопроса, в разности преобразования цветов разными
системными функциями.

With best regards, Aleksey.
Alex Mizrahi
2009-04-20 15:33:48 UTC
Permalink
AK> некий 16 битный. Теперь берём 24 битный битмап в памяти и заливаем его
AK> той же функцией, тем же цветом. Теперь копируем битмап на панель
AK> функцией BitBlt(..., SRCCOPY); опять же 24 битный цвет преобразуются в
AK> 16 битный. В NT цвета получаются идентичными, в ХР и 98 - они
AK> отличаются. Вот собственно и суть вопроса, в разности преобразования
AK> цветов разными системными функциями.

да вроде есть тонкости с этими преобразованиями, чтобы с ними не
связываться,
лучше сразу работать с 16-битными битмапами.

AK> кажется, понятней для объяснения ситуации, чем цвет Рельефных Объектов.
AK> Кстати, на NT4 всё выглядит нормально. Единственная правильная ось, в
AK> остальных либо глюк, либо неизвестная мне фича.

насколько я помню, NT4 работает с цветами более примитивно, например, когда
я проверял работу приложения в 256 цветах, XP конвертило изображения
довольно
сносно, а в NT4 были жуткие разводы.

когда система конвертирует битмапы, у неё больше средств чем при конвертации
отдельного цвета -- она может, к примеру, применить dither чтобы сделать
"похожий" цвет из группы пикселов. так что конвертация битмапа и
конвертация
одного цвета могут идти по разным алгоритмам.
Aleksey Kozlov
2009-04-23 08:52:17 UTC
Permalink
Hi, Alex Mizrahi!

20 Apr 09 19:33, Alex Mizrahi wrote to me:

AM> да вроде есть тонкости с этими преобразованиями, чтобы с ними не
AM> связываться,
AM> лучше сразу работать с 16-битными битмапами.

Дело в том, что перед выводом делается антиалиасинг изображения. Естественно
делать алгоритм под все возможные битности, это излишне заморачиваться, когда
ось сама "может" (но не хочет) делать конвертацию в нужный формат.
Если кто предложит другой вариант AA, я только за.
Hа всякий случай, AA здесь не причём, при выводе чистого цвета, эффект тот же
самый.

AM> насколько я помню, NT4 работает с цветами более примитивно, например,
AM> когда я проверял работу приложения в 256 цветах, XP конвертило
AM> изображения довольно сносно, а в NT4 были жуткие разводы.

Я за примитивизм :-) Или хотя бы алгоритм должен быть документирован.
Совершенно не понятно, заполняю битмап цветом 0xC0C0C0, в двоичном виде каждый
цвет будет 11000000, при переходе к 5и битам (16bpp) должно быть 11000. Вот и
весь алгоритм, никаких потерь при округлении не должно быть. А получается -
10111, зачем то вычитается единица. Так работает FillRect.
А BitBlt единицу не вычитает.

AM> когда система конвертирует битмапы, у неё больше средств чем при
AM> конвертации отдельного цвета -- она может, к примеру, применить dither
AM> чтобы сделать "похожий" цвет из группы пикселов. так что конвертация
AM> битмапа и конвертация одного цвета могут идти по разным алгоритмам.

Чтобы наглядно проиллюстрировать проблему приведу кусочек кода, по крайней мере
все при желании смогут убедится. При работе с API напрямую, не через
дельфийские компоненты, результат тот же самый. Да и компоненты в конце концов
те же функции и вызывают.

===cut===
var bitmap:TBitmap;
procedure TForm1.FormCreate(Sender: TObject);
begin
bitmap:=TBitmap.Create;
with bitmap do
begin
PixelFormat:=pf24bit;
Width:=40;
Height:=30;
Canvas.Brush.Color:=Form1.Color;
Canvas.Brush.Style:=bsSolid;
Canvas.FillRect(Rect(0,0,Width,Height));
end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Draw(10,10,bitmap);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
bitmap.Free;
end;
===cut===
В режиме 16bpp в левом верхнем углу окна будет виден светлый прямоугольник, в
других режимах его цвет будет совпадать с цветом окна.

With best regards, Aleksey.
Alex Mizrahi
2009-04-25 17:45:16 UTC
Permalink
AK> В режиме 16bpp в левом верхнем углу окна будет виден светлый
AK> прямоугольник, в других режимах его цвет будет совпадать с цветом окна.

пример запустил, у меня цвет получился одинаковый. причём почему-то
в 16-битном режиме C6C3C6. (и C0C0C0 в 24-битном).
Delphi7, XP и win2k.

AM>> насколько я помню, NT4 работает с цветами более примитивно, например,
AM>> когда я проверял работу приложения в 256 цветах, XP конвертило
AM>> изображения довольно сносно, а в NT4 были жуткие разводы.

AK> Я за примитивизм :-) Или хотя бы алгоритм должен быть документирован.
AK> Совершенно не понятно, заполняю битмап цветом 0xC0C0C0, в двоичном виде
AK> каждый цвет будет 11000000, при переходе к 5и битам (16bpp) должно быть
AK> 11000.

насколько я помню, в винде формат 565.

AK> Вот и весь алгоритм, никаких потерь при округлении не должно быть. А
AK> получается - 10111, зачем то вычитается единица. Так работает FillRect.

конвертирование цветов отрабатывает до FillRect, где-то в районей
CreateBrushIndirect.
а на него в документации написано:

ICM: No color is done at brush creation. However, color management is
performed when the brush is selected into an ICM-enabled device context.

может в ICM дело?

AK> крайней мере все при желании смогут убедится. При работе с API
AK> напрямую, не через дельфийские компоненты, результат тот же самый. Да и
AK> компоненты в конце концов те же функции и вызывают.

ну прежде чем вызвать функции оно может цвет конвертировать, где-нибудь в
недрах
TBrush..
Aleksey Kozlov
2009-04-27 12:12:06 UTC
Permalink
Hi, Alex Mizrahi!

25 Apr 09 21:45, Alex Mizrahi wrote to me:

AM> пример запустил, у меня цвет получился одинаковый. причём почему-то

Будем теперь разбирать компы по винтикам, искать разницу?

AM> в 16-битном режиме C6C3C6. (и C0C0C0 в 24-битном).

Hе понял, как C6 можно записать 5 битами, ни слева, ни справа не обрезать.

AM> Delphi7, XP и win2k.

AM> насколько я помню, в винде формат 565.

Each WORD in the bitmap array represents a single pixel. The relative
intensities of red, green, and blue are represented with five bits for each
color component. The most significant bit is not used.

AM> может в ICM дело?

Очень похоже на это. И на bit transfer-ные функции ICM не действует в отличии
от остальных. Hо SetICMMode(Canvas.Handle,ICM_QUERY) возвращает ICM_OFF и
установка ICM_OFF (как впрочем и ICM_ON) ничего не меняет.
Hе знаю уже в какую сторону думать.

AM> ну прежде чем вызвать функции оно может цвет конвертировать,
AM> где-нибудь в недрах TBrush..

Вот примерчик на самом что ни на есть GUI, даже FillRect не использовал, дабы
обойти USER. Варианты GetSysColorBrush, CreateSolidBrush, GetStockObject дают
одинаковый результат.

===cut===
procedure TForm1.FormPaint(Sender: TObject);
var gdiobj:HGDIOBJ;
begin
SetICMMode(Canvas.Handle,ICM_OFF);
gdiobj:=SelectObject(Canvas.Handle,GetSysColorBrush(Color and $FF));
Rectangle(Canvas.Handle,0,0,clientwidth,clientheight);
SelectObject(Canvas.Handle,gdiobj);
Canvas.Draw(10,10,bitmap);
end;
===cut===

Всё равно форма заливается цветом более тёмным, чем выводимый битмап. Hо этот
(тёмный) цвет совпадает с цветом прочих окон, так что к особенностям
Дельфийских библиотек это никак не привяжешь.

With best regards, Aleksey.

Loading...