blackfxx 0 Жалоба Опубликовано December 9, 2010 Необходима функция для перевода HBITMAP to IplImage*. А то в данный момент я делаю скриншот экрана, получаю его в HBITMAP'e и сохраняю на диск а потом гружу cvLoadImage. Вприницпе не очень устраивает. Хотелось сразу в IplImage. смотрел топик http://www.compvision.ru/forum/index.php?showtopic=280 Сам тоже находил в инете вот эту функцию. IplImage* hBitmap2Ipl(HBITMAP hBmp) { BITMAP bmp; ::GetObject(hBmp,sizeof(BITMAP),&bmp); int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ; int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U; IplImage* img = cvCreateImageHeader( cvSize(bmp.bmWidth, bmp.bmHeight) , depth, nChannels ); img->imageData = (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char)); memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels); return img; } Но она прерывается на строчке memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels); Unhandled exception at 0x576fbe20 (msvcr100d.dll) in testApp.exe: 0xC0000005: Access violation reading location 0x00000000. Может кто сталкивался? или есть идеи что изменить? UPD> проблему решил. Это оказался только кусок процедуры. Пришлось хорошо поломать голову. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
blackfxx 0 Жалоба Опубликовано December 11, 2010 IplImage * GetIplImage(HBITMAP HBM) { BITMAP BM; LPBITMAPINFO BIP; HDC DC; DWORD DataSize; WORD BitCount; GetObject(HBM, sizeof(BITMAP), (LPSTR)&BM); BitCount = (WORD)BM.bmPlanes * BM.bmBitsPixel; DataSize = ((BM.bmWidth*BitCount+31) & ~31)/8*BM.bmHeight; BIP=(LPBITMAPINFO)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BITMAPINFOHEADER)); BIP->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); BIP->bmiHeader.biWidth = BM.bmWidth; BIP->bmiHeader.biHeight = BM.bmHeight; BIP->bmiHeader.biPlanes = 1; BIP->bmiHeader.biBitCount = BitCount; BIP->bmiHeader.biCompression = 0; BIP->bmiHeader.biSizeImage = DataSize; BIP->bmiHeader.biXPelsPerMeter = 0; BIP->bmiHeader.biYPelsPerMeter = 0; if (BitCount < 16) BIP->bmiHeader.biClrUsed = (1<<BitCount); BIP->bmiHeader.biClrImportant = 0; DC = GetDC(0); BYTE * bits; // массив для битов изображения long imgsize, pixels; // Различные размерности для записи файла pixels = BIP->bmiHeader.biWidth * BIP->bmiHeader.biHeight; switch(BIP->bmiHeader.biBitCount) { case 4: imgsize = pixels / 2; break; case 8: imgsize = pixels; break; case 16: imgsize = pixels * 2; break; case 24: imgsize = pixels * 3; break; case 32: imgsize = pixels * 4; break; default: break; } // выделяем память под биты изображения bits = (unsigned char*)GlobalAlloc(GMEM_FIXED,imgsize); //Заполняем массив битов изображения int i = GetDIBits( DC, // дескриптор контекста устройства HBM, // дескриптор изображения 0, // первая выбираемая линия для изображения назначения BIP->bmiHeader.biHeight, // количество выбираемых линий bits, // адрес массива битов изображения (BITMAPINFO*)&BIP->bmiHeader,// адрес структуры с данными изображения DIB_RGB_COLORS // RGB или индекс палитры ); // заполняем данные по изображению int nChannels = BM.bmBitsPixel == 1 ? 1 : BM.bmBitsPixel/8 ; int depth = BM.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U; IplImage* img = cvCreateImageHeader(cvSize(BM.bmWidth, BM.bmHeight), depth, nChannels); // выделяем память под биты img->imageData = (char*) malloc( BM.bmHeight * BM.bmWidth* nChannels * sizeof(char)); // копируем биты memcpy( img->imageData, (char*)(bits), BM.bmHeight * BM.bmWidth * nChannels); // изображение получается перевернутым IplImage * imgModified = cvCreateImage(cvSize(img->width,img->height),img->depth, 3); cvCvtColor(img, imgModified, CV_BGRA2BGR); // в img используеются 4 канала, мне необходимо только три IplImage * imgMirror = cvCreateImage(cvSize(img->width,img->height),img->depth, 3); cvMirror(imgModified, imgMirror); // приводим в нормальный вид // убираем мусор cvReleaseImage(&imgModified); free( img->imageData); cvReleaseImage(&img); ReleaseDC(0, DC); GlobalFree((HGLOBAL)bits); HeapFree(GetProcessHeap(),0,(LPVOID)BIP); return (imgMirror); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 11, 2010 я пишу так: IplImage* hBitmap2Ipl(HBITMAP hBmp) { BITMAP bmp; ::GetObject(hBmp,sizeof(BITMAP),&bmp); int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8; int depth = IPL_DEPTH_8U; IplImage* img = cvCreateImageHeader(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels ); cvCreateData(img); memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char)); return img; } HBITMAP hbm = Image2->Picture->Bitmap->Handle; img_load2 = hBitmap2Ipl(hbm); cvFlip(img_load2,img_load2); но.. при его отрисовки через APIDrawIpl отрисовывается черное окно. при этом изображение там есть.. проверял, писал cvsaveimage.. все сохранило.. дело видимо в самом APIDrawIpl.. если есть идеи.. помогите Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
blackfxx 0 Жалоба Опубликовано December 11, 2010 проблема скорее всего в memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char)); сдесь ты копируешь биты изображения(BITMAP) bmp.bmBits в imageData. Чтобы их получить тебе надо использовать DC(дескриптор контекста устройства) HDC DC; DC = GetDC(0); //Заполняем массив битов изображения int i = GetDIBits( DC, // дескриптор контекста устройства HBM, // дескриптор изображения 0, // первая выбираемая линия для изображения назначения BIP->bmiHeader.biHeight, // количество выбираемых линий bmp.bmBits, // адрес массива битов изображения (BITMAPINFO*)&BIP->bmiHeader,// адрес структуры с данными изображения DIB_RGB_COLORS // RGB или индекс палитры ); Наверное будет работать) Сам все пробовал методом тыка и интуицией Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 12, 2010 а как тогда объяснить что при cvsaveimage полученное изображение сохраняется полностью ??? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
blackfxx 0 Жалоба Опубликовано December 12, 2010 вот об этом подумал только после того, как написал ответ. Фиг знает Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 12, 2010 вообще это функция она работала нормально у меня в старом проекте.. что изменилось в новом я не знаю..(( да кст, она оперативку жрет еще (( не много но жрет.. может вы найдете где, и как исправить.. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 12, 2010 и еще а есть функция чтобы наоборот IplImage -> Hbitmap.. ?? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
blackfxx 0 Жалоба Опубликовано December 12, 2010 и еще а есть функция чтобы наоборот IplImage -> Hbitmap.. ?? Не знаю, по этому поводу не заморачивался. Память может утекать вот здесь: >>cvCreateData(img); наверняка надо использовать cvReleaseData(&img) помимо cvRelease(&img) при завершении работы с изображением. у меня во всяком случае было img->imageData = (char*) malloc( BM.bmHeight * BM.bmWidth* nChannels * sizeof(char)); free( img->imageData); Возможно тут: >>HBITMAP hbm = Image2->Picture->Bitmap->Handle; Я использую след функции для создания и удаления хбитмапа HBITMAP bm = CreateBitmap(..); DeleteObject(bm); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 12, 2010 С памятью я разобрался!.. Это дело не в этой функции она хорошая.. Там были мои косяки.. тупо про картинку забыл )) На счет после использования достаточно удалить как обычную картинку cvReleaseImage.. HBITMAP я удаляю также Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
tybik 0 Жалоба Опубликовано December 12, 2010 Не ужели никто не знает как нормально преобразовать Hbitmap в IplImage ?? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Dr.Hell 5 Жалоба Опубликовано May 17, 2011 Вот тут очень простой пример, как сохранить снимок экрана в IplImage через TBitmap: http://www.compvision.ru/forum/index.php?showtopic=538&view=findpost&p=3340 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано May 18, 2011 это работает только для борланда? и еще теоретический вопрос, когда производится запись\чтение через HBITMAP, то из буфера виндоус надо копировать в свой буфер, т.е. дополнительные накладные расходы на копирование или как то можно напрямую сделать. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
TroyashkA 12 Жалоба Опубликовано May 18, 2011 это работает только для борланда? Нет, ну конечно чуть чуть редактирования не помешает, но это совсем малость и еще теоретический вопрос, когда производится запись\чтение через HBITMAP, то из буфера виндоус надо копировать в свой буфер, т.е. дополнительные накладные расходы на копирование или как то можно напрямую сделать. cvSetImageData(dest, src->Scan0, dest->widthStep); // не тестил, но как-то так Но, помоему, если мы сделаем UnlockBits() раньше чем, к примеру, покажем картинку, то случится фейл (попробуйте сами). Видимо все зависит от того, как работает функция cvSetImageData() Гляньте сюда, впринципе тож самое http://www.compvisio...findpost&p=3140 Только заменить: Rect *region = new Rect(0, 0, dest->width, dest->height); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано May 18, 2011 я просто не очень понимаю сам смысл действий. допустим у нас есть IplImage* и чтобы его отрисовать, я выделяю память под HBITMAP и копирую все это в контекст устрйства? как то так? вообще с аппаратной точки зрения и по накладным расходам на копирование меня интересует. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах