Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.04;
Скачать: CL | DM;

Вниз

Цветовые маски в DirectDraw   Найти похожие ветки 

 
Ермак ©   (2003-12-05 13:09) [0]

Добрый день, мастера!

Ерунда какая-то, однако...
Директ Дро дает в PixelFormat следующие RGB-маски:
TrueColor
RedMask = 00FF0000
GreenMask = 0000FF00
BlueMask = 000000FF
HighColor
RedMask = 0000F800
GreenMask = 000007E0
BlueMask = 0000001F

То есть, цвета якобы идут в прямом формате - RGB. При прямой же работе с поверхностью обнаруживается, что писать цвета надо в обратном формате - BGR. Это глюк, или так и должно быть?

Версия ДХ - 8 или старше, чипсет - Intel i740.


 
Sapersky ©   (2003-12-05 14:05) [1]

Может, пишешь не вполне правильно?


 
Ermak   (2003-12-05 15:24) [2]

Нет, с написанием все верно.
Вот код:
ptr[0] := $F8;
ptr[1] := $00;
где ptr - pByteArray - указывает на начало видеопамяти при LockSurface. По идее должна появиться красная точка в углу экрана, а появляется синяя! Т.е. схема BGR. То же самое в 24бит режиме. Я вывожу данные прямо из BMP (где они, как известно в BGR) на экран - и все ОК! А маски выдаются такие, как я привел, якобы RGB. Поскольку надо обеспечить совместимость с разными режимами, нужно учитывать маски. В том-то и вопрос: если они всегда в перевернутом виде даются - то нет проблем, а вот если это глюк на моем чипсете?


 
Sapersky ©   (2003-12-06 14:18) [3]

Хм, ну не знаю. Может, правда глюки с драйверами или ещё чем. Надо протестировать на другой видеокарте...
Насколько помню, у меня тоже с порядком записи были проблемы. Сейчас для задания цвета пользуюсь следующей процедурой и она вроде бы работает везде:

procedure SetImagePixel(Var pb : PByte; Color : TRGBQuad; Const PixelFormat : TPixelFormat);
// pb - указатель на текущий пиксель поверхность (сдвигается здесь же), Color - исходный цвет
Var rr, gg, bb : Byte;
begin
With PixelFormat do begin
 If BytesPP=2 then begin // в случае 16-битного цвета преобразуем
   rr:=Color.rgbRed   shr RShift;
   gg:=Color.rgbGreen shr GShift;
   bb:=Color.rgbBlue  shr BShift;
   PWord(pb)^:=(rr shl LoRBit) or (gg shl LoGBit) or (bb shl LoBBit);
 end else
   PDWord(pb)^:=(Color.rgbRed shl LoRBit) or (Color.rgbGreen shl LoGBit) or
                (Color.rgbBlue shl LoBBit);

 Inc(pb,BytesPP); // сдвигаем указатель
end;
end;

RShift, GShift, BShift - разница в количестве бит для 24/32-битного режима (8 бит на цвет) и цветовой составляющей данного режима (например, для режима 5-6-5 будет 3-2-3).
Преобразование получается не совсем точное, для цветового ключа, например, лучше использовать:
rr:=Color.rgbRed   * MaxRValue div 255;
gg:=Color.rgbGreen * MaxGValue div 255;
bb:=Color.rgbBlue  * MaxBValue div 255;
MaxRValue, MaxGValue, MaxBValue - максимальные значения для цветовой составляющей.
LoRBit, LoGBit, LoBBit - номера младшего (крайнего слева) бита цветовой составляющей.
Всё это получается из масок следующим образом:

procedure GetSurfPixelFormat(surf : IDirectDrawSurface7; Var PFormat : TPixelFormat);
Var rc,gc,bc,ac : Byte;

 function Bit_LowerNum(value : DWord): Byte;
 Var n,m : DWord;
 begin
 Result:=0; m:=1;
 For n:=0 to 31 do begin
   If (value and m)=m then begin Result:=n; Exit; end;
   m:=m shl 1;
 end;
 end;

 function Bit_OnesCount(value : DWord): Byte;
 Var n,m : DWord;
 begin
 Result:=0; m:=1;
 For n:=0 to 31 do begin
   If (value and m)=m then Inc(Result); m:=m shl 1;
 end;
 end;

begin
With PFormat do begin
 ZeroMemory(@DDPFormat,SizeOf(TDDPixelFormat));
 DDPFormat.dwSize:=SizeOf(TDDPixelFormat);
 surf.GetPixelFormat(DDPFormat);
 BytesPP:=DDPFormat.dwRGBBitCount div 8;
 LoRBit:=Bit_LowerNum(DDPFormat.dwRBitMask);
 LoGBit:=Bit_LowerNum(DDPFormat.dwGBitMask);
 LoBBit:=Bit_LowerNum(DDPFormat.dwBBitMask);
 LoABit:=Bit_LowerNum(DDPFormat.dwRGBAlphaBitMask);
 rc:=Bit_OnesCount(DDPFormat.dwRBitMask);
 gc:=Bit_OnesCount(DDPFormat.dwGBitMask);
 bc:=Bit_OnesCount(DDPFormat.dwBBitMask);
 ac:=Bit_OnesCount(DDPFormat.dwRGBAlphaBitMask);
 MaxRValue:=(1 shl rc)-1; MaxGValue:=(1 shl gc)-1;
 MaxBValue:=(1 shl bc)-1; MaxAValue:=(1 shl ac)-1;
 RShift:=8-rc; GShift:=8-gc; BShift:=8-bc; AShift:=8-ac;
end;
end;

Вроде нигде ничего не переворачивается (RGB на BGR и т.п.)? Или я просто этого не замечаю :)

Хотя, например, YUV следует явно писать (выяснено экспериментальным путём) в обратном порядке (т.е. если формат UYVY, то пишется Y1-V-Y0-U).

Вообще можно использовать GetDC/BitBlt и забыть о форматах пикселей. Притом что у меня по тестам это получается быстрее - видимо, моя процедура сильно кривая :( Или слишком универсальная - понимает практически все форматы, в т.ч. YUV.


 
Ермак ©   (2003-12-06 14:51) [4]

Спасибо Sapersky, попробую!

Я тоже написал свою процедуру, которая по DX Pixel Format автоматически приводит к 16-бит формату, но выяснилась вышеописанная ерунда...

Еще раз спасибо!!!



Страницы: 1 вся ветка

Текущий архив: 2004.04.04;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.03 c
14-1078935501
juiceman
2004-03-10 19:18
2004.04.04
справочник WinApi


3-1078414136
Ceval
2004-03-04 18:28
2004.04.04
Есть таблица у нее поля упорядочить по ним значения


3-1078328982
Yuri Btr
2004-03-03 18:49
2004.04.04
Перемещение записи


1-1079608292
argom
2004-03-18 14:11
2004.04.04
Как в моей проге отследить команду "Свернуть все окна"


8-1068202473
Maxon
2003-11-07 13:54
2004.04.04
Windows Media Player