Delphi TBitmap - почему отличаются пиксели и ScanLine?

При использовании 32-битного TBitmap я переключился с Canvas.Pixels на ScanLine.

Затем я установил значение Red, только чтобы найти, что оно отображается синим цветом.

Есть идеи почему?

Вот выдержка из кода:

procedure TForm1.FormPaint(Sender: TObject);
var
  varBitmap: TBitmap;
  pLock: PIntegerArray;
  iColor: integer;
begin
  varBitmap := TBitmap.Create;
  varBitmap.PixelFormat := pf32bit;
  varBitmap.Width := 800;
  varBitmap.Height := 600;

  // Set Pixels to Red
  varBitmap.Canvas.Pixels[0, 0] := $0000FF;

  // Shows $FF0000 (blue)
  pLock := varBitmap.ScanLine[0];
  iColor := pLock[0];
  ShowMessageFmt('%x', [iColor]);

  // Set ScanLine to Red
  pLock[0] := $0000FF;

  // Displays a blue pixel
  Canvas.Draw(0, 0, varBitmap);
end;

Кажется, что-то TColor не то же самое, что в памяти, но это не имеет смысла.

Любые предложения приветствуются.;)

2 ответа

Решение

32-битные пиксельные данные находятся в $AARRGGBB формат. Вы устанавливаете синий компонент, а не красный. использование $FF0000 вместо $0000FF, Или лучше использовать RGB() функция.

Растровый класс VCL, TBitmap является оберткой вокруг независимой от Windows растровой карты (DIB) Эти растровые объекты могут хранить растровые изображения в широком разнообразии форматов пикселей. Они могут быть монохромными с одним битом на пиксель, до 32 бит на пиксель, формат, который вы используете. Их также можно использовать для хранения растровых изображений на основе палитры, где каждый пиксель содержит индекс в таблицу цветов.

Два метода доступа к пиксельным данным, на которые вы ссылаетесь, это Pixels собственностью TCanvas и ScanLine собственностью TBitmap,

Pixels собственностью TCanvas это обертка вокруг GDI GetPixel а также SetPixel функции. Это функции высокого уровня, которые работают на COLORREF ценности. Документация для COLORREF говорит:

Байт младшего разряда содержит значение для относительной интенсивности красного цвета; второй байт содержит значение для зеленого; и третий байт содержит значение для синего цвета. Старший байт должен быть нулевым. Максимальное значение для одного байта составляет 0xFF.

Другими словами, COLORREF значение имеет фиксированный способ кодирования цвета пикселя. GetPixel а также SetPixel функции много обрабатывают преобразование между фиксированным COLORREF форма и исходные необработанные данные растрового пикселя. Обратите внимание также, что COLORREF не может представлять значение альфа. COLORREF значение в формате $00BBGGRR.

С другой стороны, ScanLine собственностью TBitmap возвращает вам указатель на необработанные данные пикселей базового объекта DIB. Данные, с которыми вы здесь работаете, представляют собой пиксельные данные 32bpp, и для этих данных принято, что они хранятся в формате $AARRGGBB. Документация Windows для данных 32bpp гласит:

Растровое изображение имеет максимум 2^32 цветов. Если элемент biCompression элемента BITMAPINFOHEADER имеет значение BI_RGB, элемент bmiColors элемента BITMAPINFO имеет значение NULL. Каждый DWORD в массиве растровых изображений представляет относительную интенсивность синего, зеленого и красного для пикселя. Значение для синего - это 8 младших разрядов, за которыми следуют 8 бит для зеленого и красного. Старший байт в каждом DWORD не используется.

Так что на самом деле этот текст неверен и устарел. Старший байт в каждом DWORD фактически альфа-канал, если он используется.

Другие вопросы по тегам