Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Особенности заполнения RGBQuad / 11 сообщений из 11, страница 1 из 1
29.12.2020, 15:01
    #40032276
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
Был такой код на 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
29.12.2020, 15:10
    #40032281
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
Выравнивание?
...
Рейтинг: 0 / 0
29.12.2020, 15:15
    #40032292
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
Barmaley57,
оно и есть
Код: pascal
1.
TBitmapInfoX = packed record


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

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

А после FMap.SaveToFile() какой цвет на выходе?
Может по пути/в процессе загрузки в LMemStrm перевернул RGB?
Если дело не в выравнивании заголовка, то только на байты в LMemStrm грешить нужно, имхо
...
Рейтинг: 0 / 0
30.12.2020, 21:39
    #40032748
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
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
30.12.2020, 21:47
    #40032751
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
_Vasilisk_,
стоп, я сразу не заметил - а нафига тут вообще палитра?
Код: plaintext
1.
bm.bmiHeader.biBitCount = 32;


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

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


?
...
Рейтинг: 0 / 0
30.12.2020, 21:59
    #40032758
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Особенности заполнения RGBQuad
Соколинский Борис
стоп, я сразу не заметил - а нафига тут вообще палитра?
Код: 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
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Особенности заполнения RGBQuad / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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