Форум: "Media";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];
ВнизЦветовые маски в 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 вся ветка
Форум: "Media";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.038 c