Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Высота, ширина, цвет точки HBITMAP-а, без модуля Graphics 
:(
    Опции темы
Dmitry_177
Дата 7.12.2006, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Если загрузить битмап из файла в переменную типа HBITMAP так:

Код

var
hBmp: HBITMAP;
...
hBmp := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);


Как можно узнать его высоту, ширину, и цвет в какой-то определенной точке не прибегая к модую Graphics?
PM MAIL   Вверх
Snowy
Дата 7.12.2006, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Размер
Код

var
  size: tagSIZE;
...
GetBitmapDimensionEx(hBmp, size);

Цвет точки
Код

  color := GetPixel(hBmp, x, y);


А, если нужна серъёзная работа с изображением, то GetDIBits справка по нему и поиск в руки.
PM MAIL   Вверх
Alexeis
Дата 7.12.2006, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Цитата(Snowy @  7.12.2006,  15:07 Найти цитируемый пост)
Размер

Еще можно GetObject();


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

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

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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 21
Всего: 88



Цитата(Snowy @  7.12.2006,  15:07 Найти цитируемый пост)
color := GetPixel(hBmp, x, y);
разве можно HBITMAP вместо HDC? 
Цитата(alexeis1 @  7.12.2006,  18:14 Найти цитируемый пост)
Еще можно GetObject(); 
не знаю как GetBitmapDimensionEx, а GetObject работает только для части битмапов. с его использованием я делал так
Код

function GetObject(hgdiobj:THANDLE;cbBuffer:integer;lpvObject:pointer):integer;
var err:DWORD;ScreenDC:HDC;bi:TBitmapInfo;
begin
result:=windows.GetObject(hgdiobj,cbBuffer,lpvObject);
err:=GetLastError;
if (result=0) and (cbBuffer=SizeOf(TBitmap)) and assigned(lpvObject)
   then begin
        bi.bmiHeader.biSize:=SizeOf(bi.bmiHeader);
        bi.bmiHeader.biBitCount:=0;
        ScreenDC:=GetDC(0);
        result:=GetDIBits(ScreenDC,hgdiobj,0,0,nil,bi,DIB_RGB_COLORS);
        err:=GetLastError;
        ReleaseDC(0,ScreenDC);
        pBitmap(lpvObject).bmType:=0;
        pBitmap(lpvObject).bmWidth:=bi.bmiHeader.biWidth;
        pBitmap(lpvObject).bmHeight:=bi.bmiHeader.biHeight;
        if (bi.bmiHeader.biWidth*bi.bmiHeader.biBitCount div 2)*2=
           bi.bmiHeader.biWidth*bi.bmiHeader.biBitCount
           then pBitmap(lpvObject).bmWidthBytes:=bi.bmiHeader.biWidth*bi.bmiHeader.biBitCount
           else pBitmap(lpvObject).bmWidthBytes:=((bi.bmiHeader.biWidth*bi.bmiHeader.biBitCount div 2)+1)*2;
        pBitmap(lpvObject).bmPlanes:=bi.bmiHeader.biPlanes;
        pBitmap(lpvObject).bmBitsPixel:=bi.bmiHeader.biBitCount;
        pBitmap(lpvObject).bmBits:=nil;
        if result<>0 then result:=SizeOf(TBitmap)
                     else result:=0;
        end;
SetLastError(err);
end;
коряво, но мысль имхо ясна



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Alexeis
Дата 9.12.2006, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Цитата(bems @  9.12.2006,  02:42 Найти цитируемый пост)
а GetObject работает только для части битмапов

А точнее только для DDB, для DIB и DIB Section вроде не работает.


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

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

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


Опытный
**


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

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



Вот если делать через GetDIBits, у меня возникло несколько вопросов:

Код

var
  memDC: HDC;
  hBkgnd: HBITMAP;
begin
  hBkgnd := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  memDC := GetDC(0);
  GetDIBits(memDC, hBkgnd, 0, 0, nil, BMI, DIB_RGB_COLORS);
  ReleaseDC(0, memDC);

  if (BMI.bmiColors[0].rgbRed = 255) and (BMI.bmiColors[0].rgbGreen = 0) and (BMI.bmiColors[0].rgbBlue = 0) then
    MessageBox(0, '0 - Красный', '', 0);

end;


Правильно ли я создаю контекст устройства memDC := GetDC(0);?

Не понятно что это за массив bmiColors, как так идет счет точек что-то я не пойму, там же всего одно число а не два, например x и y... Объясните пожалуйста..
PM MAIL   Вверх
bems
Дата 10.12.2006, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 21
Всего: 88



Цитата(Dmitry_177 @  10.12.2006,  19:04 Найти цитируемый пост)
Правильно ли я создаю контекст устройства memDC := GetDC(0);?
тут ты получаешь контекст экрана. У меня так работало.


Цитата(Dmitry_177 @  10.12.2006,  19:04 Найти цитируемый пост)
Не понятно что это за массив bmiColors

это значения цветов, которые есть в битмапе. (объявлен, как с одним элементом но это в основном не так)



Цитата(Dmitry_177 @  10.12.2006,  19:04 Найти цитируемый пост)
там же всего одно число а не два, например x и y... 
само содержимое битмапа скопируется в область lpvBits (если передать в этом параметре не nil)
Оно будет состоять из индексов массива bmiColors (типа первая точка имеет цвет, содержащийся в массиве по такому-то индексу, вторая - по такому - то и тд.) Но массив bmiColors не используется если в BITMAPINFOHEADER.biCompression указать BI_RGB, а в BITMAPINFOHEADER.biBitCount - 24 или 32. Тогда bmiColors вообще не трогаешь, а читаешь значения из lpvBits. Если 24 бита то там массив записей RGBTRIPLE, если 32 - RGBQUAD.

если твой битмап отводит меньше чем 24 бита на точку, то все равно можно использовать такой вариант - GetDIBits сконвертит все в соответствии с тем, как ты инициализировал BITMAPINFOHEADER (нужно соответствующи оюразом заполнить biSize, biWidth, biHeight, biPlanes, biBitCount и biCompression
)

например сначала вызвать GetDIBits с lpvBits=nil и получить реальную BITMAPINFOHEADER, потом изменить в ней формат пикселей на тот, с которым проще работать (24 или 32), выделить память под lpvBits (высота и ширина есть, количество бит на точку задаешь сам - значит можешь пощитать размер в памяти) и вызвать GetDIBits снова но уже с измененной BITMAPINFOHEADER и lpvBits<>nil (указатель на буфер для цветов). 

Получишь в буфере сконвертированую версию содеожимого битмапа. Из нее и читай цвета в трех составляющих.

Добавлено @ 22:45 
biHeight может быть отрицательным - значит строки в получаемом массиве идут в порядке от верхней к нижней. Если biHeight положительная, то строки - снизу вверх. Второй вариант почему-то более распространен

Добавлено @ 22:46 
и прочитай на форуме статью alexeis1 про формат битмапов.


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Dmitry_177
Дата 11.12.2006, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



У меня в файле битмап сохранен 24 битами на точку... Т.е. вот это:

если твой битмап отводит меньше чем 24 бита на точку, то все равно можно использовать такой вариант - GetDIBits сконвертит все в соответствии с тем, как ты инициализировал BITMAPINFOHEADER (нужно соответствующи оюразом заполнить biSize, biWidth, biHeight, biPlanes, biBitCount и biCompression
)

например сначала вызвать GetDIBits с lpvBits=nil и получить реальную BITMAPINFOHEADER, потом изменить в ней формат пикселей на тот, с которым проще работать (24 или 32), выделить память под lpvBits (высота и ширина есть, количество бит на точку задаешь сам - значит можешь пощитать размер в памяти) и вызвать GetDIBits снова но уже с измененной BITMAPINFOHEADER и lpvBits<>nil (указатель на буфер для цветов).


Мне не надо делать?

А еще мне не понятна область lpvBits если само содержимое битмапа копируется, посмотрел в описании функции:
function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: TBitmapInfo; Usage: UINT): Integer; stdcall;
Я как понял это указатель на буфер цветов, а вот как его объявлять не пойму никак...

И еще, при считывании размеров:
Код

var
  memDC: HDC;
  hBkgnd: HBITMAP;
  BMI: TBitmapInfo;
begin
  hBkgnd := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  memDC := GetDC(0);
  GetDIBits(memDC, hBkgnd, 0, 0, nil, BMI, DIB_RGB_COLORS);
  ReleaseDC(0, memDC);
end;


BMI.bmiHeader.biWidth и BMI.bmiHeader.biHeight (пускай хоть и отрицательный) не правильно определяются ширина с высотой, т.е. Реальные размеры картинки 283 x 149, если посмотреть в свойствах файла в виндовсе, а у меня определяется как 70 x 5...

Что-то я не пойму никак что не так...
PM MAIL   Вверх
Alexeis
Дата 11.12.2006, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Ой блин да вот простейший пример
Код

procedure TForm1.Button1Click(Sender: TObject);
var
 DC : hDC;
 Bitmap : HBITMAP;
 bmInfo: TDIBSection;           // структура BITMAP WinAPI
 W, H : Integer;                 // высота и ширина растра
 bmDIB: hBitmap;                // дискрептор независимого растра
 bmiInfo: BITMAPINFO;           // структура BITMAPINFO WinAPI
 lpBits: PRGBTriple;            // указатели на структуры RGBTRIPLE WinAPI

begin
  DC := Form1.Canvas.Handle; {DC := GetDC(Handle)
                              Handle - окна вывода(или любого)}

  Bitmap := LoadImage(0,
      'IMG.bmp',
      IMAGE_BITMAP,
      0,
      0,
      LR_DEFAULTSIZE or
      LR_LOADFROMFILE);

  GetObject(Bitmap, SizeOf(bmInfo), @bmInfo);

  W := bmInfo.dsBm.bmWidth;//ширина 
  H := bmInfo.dsBm.bmHeight;//высота

  bmiInfo.bmiHeader.biWidth:=W;            // ширина
  bmiInfo.bmiHeader.biHeight:=H;           // высота    
  bmiInfo.bmiHeader.biPlanes:=1;           // всегда 1    
  bmiInfo.bmiHeader.biBitCount:=24;        // три байта на пиксель    
  bmiInfo.bmiHeader.biCompression:=BI_RGB; // без компрессии    
  bmiInfo.bmiHeader.biSizeImage:=0;        // размер не знаем, ставим в ноль    
  bmiInfo.bmiHeader.biXPelsPerMeter:=2834; // пикселей на метр, гор.    
  bmiInfo.bmiHeader.biYPelsPerMeter:=2834; // пикселей на метр, верт.    
  bmiInfo.bmiHeader.biClrUsed:=0;          // палитры нет, все в ноль    
  bmiInfo.bmiHeader.biClrImportant:=0;     // то же    
  bmiInfo.bmiHeader.biSize:=SizeOf(bmiInfo.bmiHeader); // размер структруы    
  bmDIB := CreateDIBSection(DC, bmiInfo, DIB_RGB_COLORS,
  Pointer(lpBits), 0, 0); //создаем аппаратно-независимый растр (секцию DIB) WxHx24, без палитры, в указателе lpBits получаем    
  //адрес первого байта этого растра. bmDIB - дискрептор растра    
  GetDIBits(DC, Bitmap, 0, H - 1, lpBits, bmiInfo, DIB_RGB_COLORS); //растр преобразуется по адресу lpBits

  p := Pointer(lpBits); //тут начало растра.
end;




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

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

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


Опытный
**


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

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



p := Pointer(lpBits); //тут начало растра.

А как мне этот сам растр считывать?
PM MAIL   Вверх
Alexeis
Дата 11.12.2006, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Цитата(Dmitry_177 @  11.12.2006,  20:53 Найти цитируемый пост)
А как мне этот сам растр считывать? 

да как угодно, хоть байтами хоть строками, хоть пикселами.

Код

type
  PByteArray = ^TByteArray; //байтами будет так
  TByteArray = array[0..2147483646] of Byte;

  TRGBColor = packed record
            G, B, R : Byte;
            end;

  PPixelArray = ^TPixelArray; //пикселами так
  TPixelArray = array[0..2147483646] of TRGBColor;
var
  b : PByteArray;
  c : PPixelArray;
Begin
............

b := Pointer(lpBits);
b[23] := 255;

c := Pointer(lpBits);
c[28].r := 255;





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

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

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


Опытный
**


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

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



Опять же таки не пойму я... Мы узнали высоту и ширину(пока еще не пробовал так как в примере, но допустим)... Как считывать байтами или пикселями, тоже понятно... А вот как определить цвет определенной точки например (x=22; y=33)? В каком порядке считываются точки? Если построчно то я как понимаю так нужно посчитать порядковый номер точки: Width*(y-1)+x которая и будет тем цветом который мы хотим узнать?

Это сообщение отредактировал(а) Dmitry_177 - 12.12.2006, 00:02
PM MAIL   Вверх
Alexeis
Дата 12.12.2006, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Ох и зря вы не прочитали про графический формат BMP http://forum.vingrad.ru/index.php?showtopic=94227&hl=

Там все подробно описано и про то, что размер строки (для 24 бита/пиксель ) определяется 
3 * width при этом выравнивается на границу 4х байт, т.е. дополняется байтами до кратности 4м, и что строки в буфере идут снизу вверх, т.е. первая строка в буфере, является последней в изображении. 
А найти нужный пиксел легко. Совершенно верно Width*(Height - y+1)+x, главное правильно посчитать длину строки в байтах (в статье приводится формула там есть даже пример чтения из файла, правда без API, т.е. напрямую.)


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

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

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

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

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

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

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

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


 




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


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

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