powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Особенности заполнения RGBQuad
11 сообщений из 11, страница 1 из 1
Особенности заполнения RGBQuad
    #40032276
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Был такой код на C по заполнению структуры BITMAPINFO и последующего вызова StretchDIBits(). Код честно был утянут из интернета и проверен как работающий
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
class BitmapInfoX {
public:
	BITMAPINFOHEADER bmiHeader;
	DWORD bmiColors[3];
};

// Blit the drawing surface to the window.
BitmapInfoX bm;
bm.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bm.bmiHeader.biWidth = bmp->Width();
bm.bmiHeader.biHeight = -bmp->Height();
bm.bmiHeader.biPlanes = 1;
bm.bmiHeader.biBitCount = 32;
bm.bmiHeader.biCompression = BI_BITFIELDS;
bm.bmiHeader.biSizeImage = 0;
bm.bmiHeader.biXPelsPerMeter = 1000;
bm.bmiHeader.biYPelsPerMeter = 1000;
bm.bmiHeader.biClrUsed = 0;
bm.bmiHeader.biClrImportant = 0;
bm.bmiColors[0] = 0xFF000000;
bm.bmiColors[1] = 0xFF0000;
bm.bmiColors[2] = 0xFF00;
const void * bitmap_data = bmp->Data();
unsigned int lines = ::StretchDIBits(hDC,
	left, top, width, height,
	0, 0, bmp->Width(), bmp->Height(),
	bitmap_data, (BITMAPINFO *)(&bm), DIB_RGB_COLORS, SRCCOPY
);

Потом я этот код перенес на делфи
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
procedure TForm1.DrawBitmapFromStream;
type
  TBitmapInfoX = record
    bmiHeader: BITMAPINFOHEADER;
    bmiColors: array[0..2] of DWORD;
  end;
var
  LMemStrm: TMemoryStream;
  LIStrm: IStream;
  LHeight, LWidth: Integer;
  LBitsPerPixel: Integer;
  LBmpInfo: TBitmapInfoX;
  LLines: DWORD;
begin
  LMemStrm := TMemoryStream.Create;
  try
    LIStrm := TStreamAdapter.Create(LMemStrm, soReference);
    FMap.SaveBitmap(LIStrm, LWidth, LHeight, LBitsPerPixel);
    //
    LBmpInfo.bmiHeader.biSize := SizeOf(BITMAPINFOHEADER);
    LBmpInfo.bmiHeader.biWidth := LWidth;
    LBmpInfo.bmiHeader.biHeight := -LHeight;
    LBmpInfo.bmiHeader.biPlanes := 1;
    LBmpInfo.bmiHeader.biBitCount := LBitsPerPixel;
    LBmpInfo.bmiHeader.biCompression := BI_BITFIELDS;
    LBmpInfo.bmiHeader.biSizeImage := 0;
    LBmpInfo.bmiHeader.biXPelsPerMeter := 1000;
    LBmpInfo.bmiHeader.biYPelsPerMeter := 1000;
    LBmpInfo.bmiHeader.biClrUsed := 0;
    LBmpInfo.bmiHeader.biClrImportant := 0;
    LBmpInfo.bmiColors[0] := $FF000000;
    LBmpInfo.bmiColors[1] := $FF0000;
    LBmpInfo.bmiColors[2] := $FF00;
    LLines := StretchDIBits(
      FMapBitmap.Canvas.Handle,
        0, 0, FMapBitmap.Width, FMapBitmap.Height,
        0, 0, LWidth, LHeight,
        LMemStrm.Memory, PBitmapInfo(@LBmpInfo)^, DIB_RGB_COLORS, SRCCOPY
    );
    case LLines of
      0: raise EOSError.Create('Draw failed');
      GDI_ERROR: raise EOSError.Create('Unsupported format');
    end;
  finally
    LMemStrm.Free;
  end;
end;

и картинка стала у меня скатываться в красный цвет. Выяснилось, что неправильно заполнялся массив LBmpInfo.bmiColors (который содержит элементы RGBQuad). И его нужно заполнять так
Код: pascal
1.
2.
3.
    LBmpInfo.bmiColors[0] := $FF0000;
    LBmpInfo.bmiColors[1] := $FF00;
    LBmpInfo.bmiColors[2] := $FF;

Вопрос: а почему в Си все работало?

С уважением, Vasilisk
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032281
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выравнивание?
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032292
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,
оно и есть
Код: pascal
1.
TBitmapInfoX = packed record


Хедер битмапа - 42 байта, еще пару компилятор добавил.
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032724
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57
Выравнивание?
Нет. И там и там размер BitmapInfoX 52 байта
Соколинский Борис
Хедер битмапа - 42 байта
40. Плюс 3 4 -х байтовых поля. Итого честные 52 байта без всяких packed. Хедер выровнен на 4 байта
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032725
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
_Vasilisk_
Barmaley57
Выравнивание?
Нет. И там и там размер BitmapInfoX 52 байта
Соколинский Борис
Хедер битмапа - 42 байта
40 + 3 * 4 = 52 байта. Хедер выровнен на 4 байта

у тебя байт где-то съехал в описании структуры
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032732
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
defecator
у тебя байт где-то съехал в описании структуры
Почему? С чего ты взял?
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032744
pvv.pas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_,

А после FMap.SaveToFile() какой цвет на выходе?
Может по пути/в процессе загрузки в LMemStrm перевернул RGB?
Если дело не в выравнивании заголовка, то только на байты в LMemStrm грешить нужно, имхо
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032748
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pvv.pas
Может по пути/процессе в FMap перевернул RGB?
Еще раз. Я делаю вот так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
var
  LColor: TRGBQuad;
begin
  DWORD(LColor) := $FF000000;
  ShowMessageFmt('Reserved: %d, R: %d, G: %d, B: %d', [
    LColor.rgbReserved, LColor.rgbRed, LColor.rgbGreen, LColor.rgbBlue
  ]);
end;

и вижуReserved: 255, R: 0, G: 0, B: 0и это правильно. Но подразумевалось, что во всех трех присвоениях Reserved будет равен 0 и в Си именно так и происходит. Т.е. по симптомам похоже, что в Си инвертируется порядок байт при присвоении. Т.е. в Си rgbReserved берется из младшего байта, а в Delphi - из старшего.

И да, я понимаю, что на одной платформе такого быть не может, но вот так.

Вот еще отличие: Си проект компилируется под 64 бита, а Делфи под 32
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032751
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,
стоп, я сразу не заметил - а нафига тут вообще палитра?
Код: plaintext
1.
bm.bmiHeader.biBitCount = 32;


это BGRX/A формат, одного хедера достаточно.
косяк видимо уже при отрисовке
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032756
pvv.pas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_,

Я не вижу противоречий записи этих трёх величин между С и паскалем.
В этом месте нет подвоха:
Код: pascal
1.
LBmpInfo.bmiHeader.biBitCount := LBitsPerPixel;


?
...
Рейтинг: 0 / 0
Особенности заполнения RGBQuad
    #40032758
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис
стоп, я сразу не заметил - а нафига тут вообще палитра?
Код: plaintext
1.
bm.bmiHeader.biBitCount = 32;

Потому что
_Vasilisk_
Код: plaintext
1.
bm.bmiHeader.biCompression = BI_BITFIELDS;

https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheaderIf biCompression equals BI_BITFIELDS, the bitmap uses three DWORD color masks (red, green, and blue, respectively), which specify the byte layout of the pixels. The 1 bits in each mask indicate the bits for that color within the pixel.
Соколинский Борис
косяк видимо уже при отрисовке
Отрисовка в обоих случаях идет на один и тот же TBitmap.Header.Handle
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Особенности заполнения RGBQuad
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]