
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.231.217.107] |
![]() |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
![]() |
Сообщ.
#16
,
|
|
Спасибо, не нужно ![]() ![]() ![]() ![]() ![]() procedure MakeAlphaBlend(DIBColorSrc, DIBDest: PRGBQuad; const DIBColorSrcSize: Integer); assembler; asm // Запоминаем значение регистров в стеке push eax push ebx push ecx push edx push edi push esi mov esi, DIBColorSrc // карта цветов иконки mov edi, DIBDest // карта цветов фона //mov ecx, DIBColorSrcSize // размер массивов (приходит в ECX сам по себе) shr ecx, 2 // размер элемента массива равен четырем, // поэтому поправим счетчик цикла // ----------------------------------------------------------------------------- @loop: // цвета представленны следующим образом // [esi] = синий // [esi + 1] = зеленый // [esi + 2] = красный // [esi + 3] = альфа канал mov al, [esi + 3] // читаем значение альфа канала cmp al, 0 // есть ли изображение иконки в данном пикселе? jne @paint_full add esi, 4 // если нет - берем следующий элемент add edi, 4 loop @loop jmp @done // ----------------------------------------------------------------------------- @paint_full: cmp al, 255 // Смотрим интенсивность цвета jne @paint_alpha mov eax, [esi] // Данный пиксель полностью заполнен цветом иконки mov [edi], eax // копируем его целиком add esi, 4 // берем следующий элемент add edi, 4 loop @loop jmp @done // ----------------------------------------------------------------------------- @paint_alpha: // присутствует альфаканал xor ebx, ebx call @make_alpha // микшируем синий цвет inc ebx call @make_alpha // микшируем зеленый цвет inc ebx call @make_alpha // микшируем красный цвет add esi, 4 // берем следующий элемент add edi, 4 loop @loop jmp @done // ----------------------------------------------------------------------------- @make_alpha: // функция смешивает два цвета в зависимости от значения EBX, // которое указывает какой именно брать байт из RGB xor eax, eax xor edx, edx mov al, byte [edi + ebx] // берем цвет приемника mov dl, byte [esi + 3] // берем значение альфаканала not dl // значение альфаканала вычитаем из 255 mul dl // умножаем на получившееся значение or dl, $FF div dl // делим на 255 mov byte [edi + ebx], al // запоминаем первый результат xor eax, eax xor edx, edx mov al, byte [esi + ebx] // берем цвет источника mov dl, byte [esi + 3] // берем значение альфаканала mul dl // умножаем на значение альфаканала or dl, $FF div dl // делим на 255 xor edx, edx mov dl, byte [edi + ebx] // читаем первый результат add ax, dx // к нему прибавляем второй результат mov byte [edi + ebx], al // сумму помещаем обратно ret // ----------------------------------------------------------------------------- @done: // Восстановление значений регистров из стека pop esi pop edi pop edx pop ecx pop ebx pop eax end; |
Сообщ.
#17
,
|
|
|
А еще мне не понятна область 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... Что-то я не пойму никак что не так... |
Сообщ.
#18
,
|
|
|
Цитата Rouse_ @ 32-битные битмапы действительно не содержат палитру, но данные храняться в виде RGBQUAD А есть еще 24-х и 16-ти битные. На них твой пример и загнется ![]() Цитата Rouse_ @ надеюсь все в курсе5 что внутри иконки лежат битмапы? Там еще и маски есть ![]() Цитата Rouse_ @ У меня на сайте тоже есть пример работы И на основании этого ты и сделал вывод что в bmiColors[] хранится цвет точек? Этот пример совершенно не показывает структуру BMP ![]() Цитата Dmitry_177 @ А еще мне не понятна область lpvBits Я так понял. Это буфер для образа рисунка, т.е. если нужно преобразовать битмап не в контекст устройства(DC) а в буфер, то в этом параметре передаешь на нее указатель. После чего сможешь легко определить любой пиксель ![]() Цитата Dmitry_177 @ Я как понял это указатель на буфер цветов, а вот как его объявлять не пойму никак... GetMem() Цитата Dmitry_177 @ Реальные размеры картинки 283 x 149, если посмотреть в свойствах файла в виндовсе, а у меня определяется как 70 x 5... Ты сам должен корректно заполнять этот заголовок, прежде чем скормишь его GetDIBits. И кстати, вместо GetDC(0) попробуй так: ![]() ![]() memDC := CreateCompatibleDC(0); GetDIBits(memDC, hBkgnd, 0, 0, nil, BMI, DIB_RGB_COLORS); DeleteDC(memDC); |
![]() |
Сообщ.
#19
,
|
|
Цитата AndNot @ А есть еще 24-х и 16-ти битные. На них твой пример и загнется Конечно, но для этого есть другая часть примера, я же сказал где посмотреть ![]() Цитата AndNot @ Там еще и маски есть Есть, но если ты знаешь формат, то можешь удивиться - с альфой они не используются ![]() Цитата AndNot @ И на основании этого ты и сделал вывод что в bmiColors[] хранится цвет точек? Этот пример совершенно не показывает структуру BMP Этот пример абсолютно наглядно показывает структуру 32-битных растров ![]() Что еще имеем сказать? ![]() |
Сообщ.
#20
,
|
|
|
Dmitry_177, вот загрузчик битмапов, по идее должен все загружать. Так проще разобраться, а то мы что то не в ту степь поперли
![]() ![]() ![]() Type PSprite = ^TSprite; TSprite = record Width : Integer; Height: Integer; Buffer: ^Byte; end; function ConvImage(ImgName: String): PSprite; var Bitmap: TBitmap; Buff : PSprite; Info : TBitmapInfo; MemDC : HDC; begin Bitmap := TBitmap.Create; Bitmap.LoadFromFile(ImgName); // формируем заголовок with Info.bmiHeader do begin FillChar(Info, SizeOf(TBitmapInfo), 0); biSize := SizeOf(TBitmapInfoHeader); biWidth := Bitmap.Width; // можешь поиграться с размерами biHeight := Bitmap.Height; // получаемого изображения biPlanes := 1; // всегда 1 biCompression := BI_RGB; // нет никакой компрессии данных biBitCount := 24; // пиксели будут в формате RGBTRIPLE // для RGBQUAD поставь 32 GetMem(Buff, SizeOf(TSprite)); Buff^.Width := biWidth; Buff^.Height:= biHeight; GetMem(Buff^.Buffer,(biWidth*biHeight) * (biBitCount shr 3)); MemDC := CreateCompatibleDC(0); GetDIBits(MemDC,Bitmap.Handle, 0, biHeight, Buff^.Buffer, Info, DIB_RGB_COLORS); DeleteDC(MemDC); end; Bitmap.Free; ConvImage := Buff; end. Возвращает именно растр. Его формат указан в biBitCount. Извини за возможные очепятки и некоторое несоответствие типов, дельфи в отказ пошел, похоже система последние дни доживает ![]() Цитата Rouse_ @ с альфой они не используются Да они вообще в принципе не нужны ![]() Цитата Rouse_ @ Этот пример абсолютно наглядно показывает структуру 32-битных растров Ладно завязываем. Разговор то поначалу пошел про поле bmiColors[]. |
![]() |
Сообщ.
#21
,
|
|
Цитата AndNot @ Ладно завязываем. Разговор то поначалу пошел про поле bmiColors Поддерживаю ![]() |
Сообщ.
#22
,
|
|
|
![]() ![]() Bitmap.LoadFromFile(ImgName); ... biWidth := Bitmap.Width; // можешь поиграться с размерами biHeight := Bitmap.Height; // получаемого изображения Это же битмап из модуля Graphics я как понял, а мне без него нужно... |
Сообщ.
#23
,
|
|
|
Цитата Dmitry_177 @ Это же битмап из модуля Graphics я как понял, а мне без него нужно... А это не важно. Главное получить хэндл загруженного в память битмапа. Например так: Замени ![]() ![]() Bitmap: TBitmap; на ![]() ![]() Bitmap: Handle; // или HWND Затем загрузи его с помощью какой либо функции: LoadBitmap - если из файла LoadResource - из ресурсов etc. И полученный хендл передаешь вместо Bitmap.Handle; |
Сообщ.
#24
,
|
|
|
а HBITMAP разве не хэндл? Загружаю его из файла:
hBkgnd := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); а как же быть с Bitmap.Width; Bitmap.Height;? |
Сообщ.
#25
,
|
|
|
Цитата Dmitry_177 @ а HBITMAP разве не хэндл? Извини, забыл сказать. Хэндлом может считаться любой DWORD. Цитата Dmitry_177 @ Загружаю его из файла: hBkgnd := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); Почему бы и нет? А почему не хочешь LoadBitmap использовать? Цитата Dmitry_177 @ а как же быть с Bitmap.Width; Bitmap.Height;? Для определения ширины и высоты исходного битмапа вроде подходит функция GetBitmapDimensionEx(Handle: HBITMAP; var p: TPoint); PS: Сообщи о результатах ![]() |
Сообщ.
#26
,
|
|
|
Так не работает почему-то...
![]() ![]() var BmpSize: SIZE; hBmp: HBITMAP; begin hBmp := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); GetBitmapDimensionEx(hBmp, BmpSize); BmpSize.cx и BmpSize.cy равны нулю... |
Сообщ.
#27
,
|
|
|
>GetBitmapDimensionEx(hBmp, BmpSize);
>BmpSize.cx и BmpSize.cy равны нулю... Так а какая ошибка возвращается от GetBitmapDimensionEx? И загружается ли сам Битмап? |
Сообщ.
#28
,
|
|
|
Битмап загружается, все правильно, потому что пробовал потом выводить его все выводится...
А вот так правильно определяются размеры, но только этот способ наверно медленнее чем с GetBitmapDimensionEx или нет? ![]() ![]() var DIBS: DIBSECTION; begin hBmp := LoadImage(0, '1.bmp', IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); GetObject(hBmp, SizeOf(DIBS), @DIBS); W := DIBS.dsBm.bmWidth; H := DIBS.dsBm.bmHeight; end; |
Сообщ.
#29
,
|
|
|
Цитата Dmitry_177 @ BmpSize.cx и BmpSize.cy равны нулю... Нда, в справе в самом конде есть замечательное примечание - она возвращает размер установленный с помощью SetBitmapDimensionEx. Так что не катит. Цитата Dmitry_177 @ А вот так правильно определяются размеры, но только этот способ наверно медленнее чем с GetBitmapDimensionEx или нет? Все равно ничего другого не остается ![]() |
Сообщ.
#30
,
|
|
|
Dmitry_177, верно, я именно так и делаю. Только не вздумай получать от туда BPP(bmBitsPixel)! Так как, как я уже писал она вернёт BPP текущего Device Context, а не то как записано в фаиле и не то, как вернётся из GetDIBits. Вот для этого уже придётся действительно читать Хеадер фаила.
Получив здесь не достающую мне информацию, я пришёл к выводу, что надо бы вообще написать отдельный модуль (свой) для работы с Битмапом. Как бы я не любил WinAPI, с битмапом там не всё так хорошо как хотелось бы.. (ИМХО). |