Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Графика и игры
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 07.03.2017, 17:12
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию 4 bit HBitmap

Здравия всем!

Столкнулся с некоторой проблемкой при работе с HBitmap;
Использую WinAPI. Суть - Не могу сделать SelectObject на 4 битный битмап.
Использую именно 4 битный, т.к. графические данные подготовлены в 16 цветной индексированной палитре, поэтому переводить в 32 бит - затратно для производительности приложения.

Вот пример использования:
Код:
Const
data2: array[0..63] of byte = (
	$00, $00, $00, $00, $01, $00, $01, $00, $41, $00, $71, $00, $55, $00, $7C, $00,
  $00, $00, $00, $00, $01, $00, $01, $00, $41, $00, $71, $00, $55, $00, $7C, $00,
  $00, $00, $00, $00, $01, $00, $01, $00, $41, $00, $71, $00, $55, $00, $7C, $00,
  $00, $00, $00, $00, $01, $00, $01, $00, $41, $00, $71, $00, $55, $00, $7C, $00
);
...

procedure TForm1.Button1Click(Sender: TObject);
var
HDC:THandle;
BufferImages:HBitmap;
BDC:THandle;
Select:LongWord;
begin
Image1.Picture.Bitmap.Width:=8;
Image1.Picture.Bitmap.Height:=8;
HDC:=Image1.Picture.Bitmap.Canvas.Handle;
BufferImages:=CreateBitmap(8,8,1,4,@data2); //??? 
BDC:=CreateCompatibleDC(HDC);
Select:= SelectObject(BDC,BufferImages);
if Select =0 then ShowMessage('Selected error');
BitBlt(HDC,0,0,8,8,BDC,0,0,SRCCOPY);
ReleaseDC(BDC,BufferImages);
DeleteDC(BDC);
DeleteObject(BufferImages);

end;
Вот почему, если я создаю
CreateBitmap(8,8,1,1,@data2) - то нормально, а если:
CreateBitmap(8,8,1,4,@data2) - то SelectObject = 0 и соответственно на контексте ничего. Аналогичная ошибка при 8, 16 битах, а 32 понятно норм.
При этом сам CreateBitmap возвращает идентификатор в любом случае.
а установка
Код:
Image1.Picture.Bitmap.PixelFormat:=pf4bit;
ничего не даёт;

Пробовал использовать CreateDIBSelection, SetDIBits, StretchDiBits - не помогает.
SetDIBits и StretchDiBits что-то пытаются, но слишком геморно.

Собственно вопрос как отрисовать 4 битный битмап (на 32 битном контексте)?
__________________
Програмистами не рождаются, ими становятся!
Ответить с цитированием
  #2  
Старый 07.03.2017, 19:39
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,057
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от MSDN
After a bitmap is created, it can be selected into a device context by calling the SelectObject function. However, the bitmap can only be selected into a device context if the bitmap and the DC have the same format.
The CreateBitmap function can be used to create color bitmaps. However, for performance reasons applications should use CreateBitmap to create monochrome bitmaps and CreateCompatibleBitmap to create color bitmaps. Whenever a color bitmap returned from CreateBitmap is selected into a device context, the system checks that the bitmap matches the format of the device context it is being selected into. Because CreateCompatibleBitmap takes a device context, it returns a bitmap that has the same format as the specified device context. Thus, subsequent calls to SelectObject are faster with a color bitmap from CreateCompatibleBitmap than with a color bitmap returned from CreateBitmap.

Ничего не подсказывает?
Т.е. для начала надо смотреть в сторону CreateCompatibleBitmap.

Последний раз редактировалось lmikle, 07.03.2017 в 19:41.
Ответить с цитированием
  #3  
Старый 07.03.2017, 20:51
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Нет, CreateCompatibleBitmap создает на основе контекста, а контекст 32 битый, а значит что битмап на выходе будет 32 битный, а мне нужен 4 битный. В этом и прикол. В итоге мне удалось реализовать задуманное через CreateDIBSelection.

Если вдруг кому понадобится:
Что нам надо,
1. Переменную структуры BITMAPINFO, в которой опишем нужный нам формат битмапа.
2. Переменную Pointer, что бы знать куда писать данные.
3. Массив с палитрой типа RGBQUAD.
4. Собственно данные.

Код:
var
ImgBitInfo:BITMAPINFO; //Описание битмапа
hDC:LongWord;             //Контекст
BufferedImage:LongWord;  // Битмап
PImgArrayPix: Array [0..7] of Integer;  //Массив данных
//можно брать 4 byte на строчку из 8 px, но это равносильно 1 integer
i,color:Integer;  //Переменки
PbyteArray:Pointer;  //Указатель на память 
Palletes:array [0..3] of RGBQUAD; //Палитра

begin
//Заполняем структуру
with ImgBitInfo.bmiHeader do
 begin
  biSize:=sizeof(ImgBitInfo.bmiHeader);
  biWidth:=8; //размер картинки 8 px
  biHeight:=8;//размер картинки 8 px
  biPlanes:=1; //Всегда 1
  biBitCount:=4;
 //4 бита на пиксель, палитра 16 цветов, индексированные цвета
  biCompression:=0; //без компрессии
  biClrUsed:=4; //используем только 4 цвета
end;
 //Создаем Битмап, точнее область в памяти
 // с DIB данными с заданными параметрами
  BufferedImage :=CreateDIBSection(DC,ImgBitInfo,0,PbyteArray,0,0);
//теперь PbyteArray - это указатель на адрес памяти где лежат данные DIB
  //Создаем контекст
  hdc           :=CreateCompatibleDC(DC);
 //Выбираем это хозяйство
  SelectObject(hdc, BufferedImage);

//Заполняем палитру нужными цветами
   for i := 0 to 3 do
   begin
    color:=NesColor[palettes[Palette,0,i]]; //Каким угодно образом 
    Palletes[i].rgbRed  := GetRValue(color);//заполняем палитру
    Palletes[i].rgbGreen:= GetGValue(color);//
    Palletes[i].rgbBlue := GetBValue(color);//
   end;
  SetDIBColorTable(hDC,0,4,Palletes); //Применяем палитру к контексту
// 0 - первый индекс цвета, 4 - количество цветов

//Заполняем массив данных, читаем его или подготавливаем заранее
  for i := 0 to 7 do PImgArrayPix[7-i]:=bit2Int(maps_Tables[Mapper,code,0, i],maps_Tables[Mapper,code,1,i]);
//Заполняется снизу вверх

//Копируем все данные массива, в адрес полученный ранее
CopyMemory(PbyteArray, @PImgArrayPix, 32);


//Выводим полученное изображение куда надо, 
 TransparentBlt(dc,x,y,8,8,hdc,0,0,8,8,NesColor[palettes[Palette,0,0]]);//с прозрачностью
 //BitBLT(DC,x,y,x+8,y+8,hdc,0,0,SRCCOPY); //или без

//Удаляем переменные.
  ReleaseDC(hDC,BufferedImage);
  DeleteDC(hDC);
  DeleteObject(BufferedImage);
end;
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 08.03.2017 в 10:55.
Ответить с цитированием
Этот пользователь сказал Спасибо SCrat.ORS за это полезное сообщение:
IvoX (22.05.2019)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 16:25.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter