GetDIBits

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

GetDIBits

Сообщение alibek » 21.09.2004 (Вт) 10:03

Народ, подскажите, у меня уже соображалка не работает.
Есть следующий код:
Код: Выделить всё
...
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
...
Private Enum BitmapColorUsage
  DIB_RGB_COLORS = 0
  DIB_PAL_COLORS = 1
End Enum
Private Type RGBQuad
  rgbBlue As Byte
  rgbGreen As Byte
  rgbRed As Byte
  rgbReserved As Byte
End Type
Private Type BitmapInfoHeader
  biSize As Long
  biWidth As Long
  biHeight As Long
  biPlanes As Integer
  biBitCount As Integer
  biCompression As Long
  biSizeImage As Long
  biXPelsPerMeter As Long
  biYPelsPerMeter As Long
  biClrUsed As Long
  biClrImportant As Long
End Type
Private Type BitmapInfo
  bmiHeader As BitmapInfoHeader
  bmiColors As RGBQuad
End Type
Private Declare Function GetDIBits Lib "gdi32" (ByVal hDC As Long, ByVal hBitmap As Long, ByVal StartScan As Long, ByVal NumScans As Long, pBits As Any, pBitmapInfo As BitmapInfo, ByVal ColorUsage As BitmapColorUsage) As Long
...

Private Function PictureToString(pImage As StdPicture) As String
If pImage Is Nothing Then Exit Function
Dim A() As Byte, BI As BitmapInfo, I As Long, hDC As Long
hDC = CreateCompatibleDC(0&)
SelectObject hDC, pImage.Handle
BI.bmiHeader.biSize = Len(BI.bmiHeader)
I = GetDIBits(hDC, pImage.Handle, 0&, 0&, ByVal 0&, BI, DIB_RGB_COLORS)
If BI.bmiHeader.biSizeImage = 0 Then
  I = BI.bmiHeader.biHeight * BI.bmiHeader.biWidth * BI.bmiHeader.biBitCount / 8
Else
  I = BI.bmiHeader.biSizeImage
End If
I = (CLng(I + 3) \ 4) * 4
ReDim A(0 To I - 1)
I = GetDIBits(hDC, pImage.Handle, 0&, BI.bmiHeader.biHeight, A(0), BI, DIB_RGB_COLORS)
DeleteDC hDC
...
End Function

И эта сволочь падает при выборке битов в массив (вторая I = GetDIBits...). Пример из API-Guide работает на ура. Вся разница в том, что в API-Guide hBitmap создается API, а у меня используется StdPicture.Handle. Но в MSDN сказано, что .Handle является hBitmap. Это я гоню или MSDN обманывает?

Причем, в первый раз GetDIBits отрабатывает (когда вместо буфера передается NULL, то функция заполняет BITMAPINFO, причем заполняет правильно). Но при втором вызове вылетает.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 21.09.2004 (Вт) 13:39

Молчит-молчит, а потом как спросит... :)

Во-первых, почему работает пример из Api-Guide, я и сам не знаю. В MSDN чётко сказано: картинка не должна быть выбрана в DC.
Во-вторых, ты же не изменяешь desired image format :) У тебя, к примеру, картинка с палитрой. А ты ей передаёшь структуру BI, содержающую место для одной palette entry. Результат - переполнение буфера и вылет даже без сообщения об ошибке :) И это сделал человек, читавший Книжку :wink:

Алгоритм.
hdc=GetDC(0)
getdibits (узнаём размеры)
BI.bmiHeader.biBitCount = 24 'хотим без палитры
redim 'исходя из того, что 24 bpp
getdibits (теперь уже полностью)
ReleaseDC 0, hdc
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.09.2004 (Вт) 13:58

Картинка точно не с палитрой :)
Более того, BitmapInfo я вообще не заполняю, его заполняет сама GetDIBits при первом вызове. Во-всяком случае, BI.bmiHeader.biBitCount заполняется правильно (как и высота, ширина, размер и пр.).
SelectObject я добавил вообще от безысходности -- API-Guide работает, у меня не работает, весь вечер мучал, так и не удалось запустить. Вот и добавил, чтобы отличий стало меньше, но не помогло. Фактически, сейчас отличие я вижу только одно -- у меня используется не честный HBITMAP, а StdPicture.Handle. И остается только думать, что MSDN меня обманул.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.09.2004 (Вт) 14:00

З.Ы. После первого вызова имеем .biBitCount=32. Уж не знаю, почему, WINGDIAPI виднее. Видимо из-за того, что у меня на десктопе режим цветности 32 бита.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.09.2004 (Вт) 14:02

З.З.Ы. Чудеса в решете... Насильно влепил .biBitCount=24 и прога не слетела, только зависла намертво. Слишком большой буфер тоже плохо?
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 21.09.2004 (Вт) 14:58

Мдя...
Нет, слишком большой буфер ничего.

:?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 21.09.2004 (Вт) 15:20

Берём картинку цветов так на 8. Получаем её инфу, указывая dc рабочего стола. Возвращается 8! Как и должно быть. Значит, у тебя и правда 32 bpp.
Теперича, делаем буфер...
И получаем.
И всё работает.

Кстати, ты учитываешь, что высота бывает отрицательной у картинок с обратной ориентацией?

Код: Выделить всё
Private Function PictureToString(ByVal pImage As IPictureDisp) As String
  If pImage Is Nothing Then Exit Function
 
  Dim a() As Byte, BI As BitmapInfo, i As Long, hd As Long
 
  hd = GetDC(0)
  BI.bmiHeader.biSize = Len(BI.bmiHeader)
 
  i = GetDIBits(hdc, pImage.Handle, 0, 0, ByVal 0&, BI, DIB_RGB_COLORS)
  ReDim a(1 To Abs(BI.bmiHeader.biHeight) * (BI.bmiHeader.biWidth * 4 + 3))
  BI.bmiHeader.biBitCount = 32
 
  i = GetDIBits(hd, pImage.Handle, 0, BI.bmiHeader.biHeight, a(LBound(a)), BI, DIB_RGB_COLORS)
 
  ReleaseDC 0, hd
End Function

Private Sub Form_Load()
  Dim p As IPictureDisp
 
  Set p = LoadPicture("C:\Program Files\Microsoft Visual Studio\Common\Graphics\Bitmaps\OffCtlBr\Large\Color\Cut.bmp")
  PictureToString p
 
  Set p = Nothing
End Sub
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.09.2004 (Вт) 15:42

Нет, картинка правильная, я структуру в отладчике просмотрел. Когда четко указываю, что bpp 24, то все работает. Теперь бы только сообразить, почему он говорит мне, что 32, если с 32 не работает, а работает с 24... У кого-то из нас глюки, либо у меня, либо у XP.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 21.09.2004 (Вт) 16:08

А кинь картинку эту.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.09.2004 (Вт) 16:24

Ну вот, к примеру.
Помучаю еще, если не выйдет, плюну на LoadPicture и буду через API загружать.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 21.09.2004 (Вт) 17:33

alibek, твой комп меня удивляет.
Это обыкновеннейший 24 bpp. 24 и возвращается. В массив дампится и при 24, и при 32. Массив у меня гарантировано больше, чем нужно.
Всё отлично! :?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 22.09.2004 (Ср) 9:39

А как он удивляет меня :)
Я вот проверил, что мне возвращают, массив из нулей состоит. Буду пытать дальше.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 22.09.2004 (Ср) 12:31

Раз массив из нулей, значит ничего не возвращено.
А значит буфер мал. Хотя я и уверен, что ты объявил бы правильно. Странно.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList