Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SetDIBitsToDevice, Черный экран 
:(
    Опции темы
CynicRus
Дата 9.4.2014, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Приветствую уважаемых форумчан. Имеется массив пикселов в формате TRGBTriple, 
  
Код

   pPixelArray = ^TPixelArray;
   TPixelArray = array [0..MaxPixelCount-1] of TRGBTriple;


нужно это дело быстро отрисовать на канве. Пробую это сделать с помощью 
Код

SetDIBitsToDevice


пробую это сделать следующим образом:
Код

procedure TDTMBitmap.FastDrawToCanvas(const X, Y: integer; Canvas: TCanvas);
var
  HeaderSize : integer;
  bmpInfo : PBitmapInfo;
begin
  if not Assigned(FData) then exit;

  HeaderSize := Sizeof(TBitmapInfo) + (256 * Sizeof(TRGBTRIPLE));
  BmpInfo := AllocMem(HeaderSize);
  if BmpInfo = nil then
    raise Exception.Create('Failed to allocate a DIB');
  with BmpInfo^.bmiHeader do begin
    biSize        := SizeOf(TBitmapInfoHeader);
    biWidth       := Width;
    biHeight      := -Height;
    biPlanes      := 1;
    biBitCount    := 8;
    biCompression := BI_RGB;
    biClrUsed     := 0;
    biClrImportant:= 0;
  end;
  SetDIBitsToDevice(Canvas.Handle, X, Y, Width, Height, 0, 0, 0, Height,
                    FData, BmpInfo^, DIB_RGB_COLORS);
  FreeMem(BmpInfo, HeaderSize);
end;


И собственно получаю чёрный экран вместо изображения в указанной области-)

Собственно вопрос - как вывести картинку из массива указанного типа в Canvas при помощи SetDIBitsToDevice?

UPD: изменил biBitCount на 24, но получаю какое-то кривое изображение вместо требуемого-( Тоесть оно геометрически верное, а вот цвета какие-то не те-)

Это сообщение отредактировал(а) CynicRus - 9.4.2014, 09:43
PM MAIL   Вверх
Alexeis
Дата 9.4.2014, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



  Причин может быть много, всегда нужно начинать со значения, которое возвращает функция. Но некоторые странности видны сразу.
 Почему biHeight      := -Height; ? В битмапах высота может быть отрицательной, если строки идут в обратном порядке, но не факт, что эта функция переваривает такие. Я бы задал для начала положительную.
  Почему biBitCount    := 8; при том что TRGBTriple указывает на 24х битный формат цвета? 
  
  Но в любом случае начинаем дебаг с возвращаемых значений. Нужно знать, то ли функция не выполнилась, то ли выполнилась при том что рассматривала входные данные иначе чем предполагалось .

Это сообщение отредактировал(а) Alexeis - 9.4.2014, 09:51


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CynicRus
Дата 9.4.2014, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Фух. Вот с таким онанизмом у меня получилось вывести пиксели как надо:

Код

var
  Bitmap: TBitmap;
  bi : PBITMAPINFO;
  Bits   : Pointer;
  BitsSize: integer;
begin
  if not Assigned(FData) then exit;
  Bitmap:=TBitmap.Create;
  GetMem(bi, SizeOf(TBitmapInfo));
    try
      ToBMP(Bitmap);
      FillChar(bi^, SizeOf(TBITMAPINFO), 0);
      with bi^.bmiHeader do
      begin
        biSize          := SizeOf(TBITMAPINFOHEADER);
        biWidth         := Bitmap.Width;
        biHeight        := -Bitmap.Height;
        biPlanes        := 1;
        biBitCount      := 24;
        biCompression   := BI_RGB;
      end;
      BitsSize:=Bitmap.Width * Bitmap.Height * (bi^.bmiHeader.biBitCount shr 3);
      GetMem(Bits, BitsSize);
      GetDIBits(Bitmap.Canvas.Handle, Bitmap.Handle, 0, Bitmap.Height, Bits, TBitmapInfo(bi^), DIB_RGB_COLORS);
      SetDIBitsToDevice(Canvas.Handle, X, Y, Width, Height, 0, 0, 0, Height,
                    Bits, bi^, DIB_RGB_COLORS);
    finally
      bitmap.Free
    end;
  FreeMem(Bits,BitsSize);
  FreeMem(bi,SizeOf(TBitmapInfo));
end;

где ToBMP:
Код

var
 i,j,dd: integer;
 Pixels: pPixelArray;
begin
   dd:=width*height-1;
   bmp.PixelFormat := pf24bit;
   bmp.Width  := width;
   bmp.Height := height;
  for i := Bmp.Height - 1 downto 0 do
  begin
   Pixels:=Bmp.ScanLine[i];
   for j :=Bmp.Width - 1  downto 0  do
    begin
    Pixels[j]:=FData^[dd];
    dec(DD);
    end;
  end;
end;


Но, помоему - это напрочь не оптимальный вариант быстрого вывода на экран-))

Как бы теперь выпилить это самое лишнее преобразование в битмап с выдиранием его пикселей?

PM MAIL   Вверх
Alexeis
Дата 9.4.2014, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



  Непонятно для чего тут GetDIBits . Достаточно иметь объект класса TBitmap в нужных размерах. Я так понимаю, что он выступает в роли бэк буфера для рисования.
Расскажу по секрету, что если взять Bmp.ScanLine[Bmp.heigth - 1], то это и будет указатель на начало диб секции TBitmap. Соответственно выпиливаем из кода вообще все, кроме.
      SetDIBitsToDevice(Canvas.Handle, X, Y, Width, Height, 0, 0, 0, Height,
                    Bmp.ScanLine[Bmp.heigth - 1], bi^, DIB_RGB_COLORS);
Важно обратить внимание чтобы Width, Height совпадали с Bmp.heigth и Bmp.Width, а лучше вообще именно их передавать в SetDIBitsToDevice. Очевидно, что всю инициализацию следует убрать из функции рендера. В ней должен остаться только один вызов SetDIBitsToDevice и больше ничего. Разве что можно добавить еще ValidateRect чтобы винда узнала, о том, что область больше не нуждается в перерисовке и WM_PAINT больше не нужно слать.
 

Это сообщение отредактировал(а) Alexeis - 9.4.2014, 11:16


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CynicRus
Дата 9.4.2014, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Спасибо! Только я попробовал с SetDIBitsToDevice(Canvas.Handle, X, Y, Width, Height, 0, 0, 0, Height,
                    Bmp.ScanLine[Bmp.heigth - 1], bi^, DIB_RGB_COLORS); - и ничего, белый экран.
PM MAIL   Вверх
Alexeis
Дата 9.4.2014, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



  Нужно убедиться, что размеры битмапа совпадают с размерами передаваемыми как Width, Height и то что на битмапе что-то нарисовано. Если битмап создается пустой, то он изначально залит белым цветом. Может это как раз и говорит, что все правильно рисуется. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CynicRus
Дата 11.4.2014, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Цитата(Alexeis @ 9.4.2014,  14:29)
Нужно убедиться, что размеры битмапа совпадают с размерами передаваемыми как Width, Height и то что на битмапе что-то нарисовано. Если битмап создается пустой, то он изначально залит белым цветом. Может это как раз и говорит, что все правильно рисуется.

SetDIBitsToDevice(Canvas.Handle, X, Y, Width, Height, 0, 0, 0, Height,
                    Bmp.ScanLine[Bmp.heigth - 1], bi^, DIB_RGB_COLORS); - разобрался я с этим, спасибо большое!

Единственное, по непонятной причине - цвета...Точнее не цвета, а тона на отображаемом становятся темнее, чем на оригинале. При этом - при сохранении просто в файл - всё ок.

Хм, странно - но выставив DIB_PAL_COLORS последним параметром, я получил нормальный цвета-)

Это сообщение отредактировал(а) CynicRus - 11.4.2014, 10:30
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0508 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.