Volcano software logo
Главная
 
Программы
 
Модули
 
Статьи
 
программы
Tile Manager
Time Control
поиск по сайту

16-разрядный цвет

Сегодня я собираюсь разобраться с задачей, с которой Вы, возможно, уже сталкивались, или столкнетесь в ближайшем будущем: наложение 24-разрядного изображения на 16-разрядную поверхность DirectDraw.

Несколько дней назад я работал на моем старом компьютере с видеокартой ATI VGA Wonder. Видеокарта использовала по 5 бит для каждого значения R, G и B (всего 15 бит), так что формат пикселя выглядел что-то вроде этого:

XRRRRRGGGGGBBBBB

Сейчас у моего нового компьютера более лучшая видеокарта. Она использует все 16 бит, делая формат пикселя похожим на:

RRRRRGGGGGGBBBBB

Я стал размышлять о том, как сделать так, чтобы я мог указать любой цвет для вывода на экран, так что бы он отображался корректно, независимо от того, какая видеокарта установлена.

Кстати, я написал свой собственный загрузчик растровых изображений, читающий 24-разрядные BMP и накладывающий их на 16-разрядную поверхность (я, вероятно, расскажу про это позже, скорее всего в отдельной статье).

Итак, я уселся и приступил к решению этой задачи. Первое, что я сделал, это открыл файл DirectX.hlp и нашел описание интерфейса IDirectDrawSurface. Одна из функций интерфейса называется GetPixelFormat. Отлично. У меня есть что-то, с чем можно работать.

GetPixelFormat берет указатель на структуру DDPIXELFORMAT (что не удивительно). Я рассмотрел структуру DDPIXELFORMAT и нашел пару полей, которые заинтересовали меня, а именно dwRBitMask, dwGBitMask, dwBBitMask.

Теперь у меня есть вся необходимая информация, только не в том формате, который я мог бы использовать.

ddpf: DDPIXELFORMAT;

ZeroMemory(@ddpf, SizeOf(DDPIXELFORMAT));
ddpf.dwSize := sizeof(DDPIXELFORMAT);
lpDDS.GetPixelFormat(ddpf);

Что теперь?

Ну, чтобы выяснить, насколько влево нужно сдвинуть биты, я сделал так:

//  Предупреждаю, этот код УЖАСТЕН
var
  dwBMask, dwRMask, dwGMask, 
  dwBSHL, dwRSHL, dwGSHL :DWORD;

  dwBMask := ddpf.dwBBitMask;
  dwRMask := ddpf.dwRBitMask;
  dwGMask := ddpf.dwGBitMask;

  dwBSHL=0;
  dwRSHL=0;
  dwGSHL=0;

  while (dwBMask AND 1) = 0 do
  begin
    dwBMask := dwBMask shl 1;
    Inc(dwBSHL);
  end;

  while (dwGMask AND 1) = 0 do
  begin
    dwGMask:= dwGMask shl 1;
    Inc(dwGSHL);
  end;

  while (dwRMask AND 1) = 0 do
  begin
    dwRMask:= dwRMask shl 1;
    Inc(dwRSHL);
  end;

В этом месте, если мы примем, что в трех UCHARS, названных Red, Green и Blue, хранится правильное число бит, то можно вычислить 16-разрядный цвет:

Color := Blue shr dwBSHL + 
    Green shr dwGSHL + 
    Red shr dwRSHL;

Однако, сейчас у нас по 8 бит в каждом из Red, Green и Blue, а требуется только 5 или 6. Нам нужно сдвинуть биты цветов направо перед смещением их налево, чтобы получить 16-разрядный цвет.

Итак, давайте определим, насколько бит мы должны сдвинуть их направо:

var
  dwBSHR, dwRSHR, dwGSHR :DWORD;

dwBSHR=0;
dwRSHR=0;
dwGSHR=0;

while (dwBMask AND 1) = 1 do
begin
  dwBMask := dwBMask shl 1;
  Dec(dwBSHL);
end;

while (dwGMask AND 1) = 1 do
begin
  dwGMask:= dwGMask shl 1;
  Dec(dwGSHL);
end;

while (dwRMask AND 1) = 1 do
begin
  dwRMask:= dwRMask shl 1;
  Dec(dwRSHL);
end;

Теперь, мы можем точно вычислить 16 разрядный цвет из 24 разрядного

Color :=(Blue shl dwBSHR) shr dwBSHL + 
    (Green shl dwGSHR) shr dwGSHL + 
    (Red shl dwRSHR) shr dwRSHL;

Автор: TANSTAAFL
Оригинал статьи: http://www.gamedev.net/reference/articles/article863.asp
Перевод:

Copyright © 2004
Hosted by uCoz