HWND zu IplImage konvertieren


  • Mod

    Du musst die Bitmap Bits separat anfordern:
    http://msdn.microsoft.com/en-us/library/dd144850(v=vs.85).aspx



  • Ich habe das mitlerweile einmal so und so versucht, bin aber
    leider zu keinem Ergebnis gekommen. Sprich der Inhalt der
    Inhalt von bm.bmpBits ist immernoch 0x0000....

    //long x = GetBitmapBits(hbm, bmp.bmHeight * bmp.bmWidth * nChannels, bmp.bmBits);
    
    //GetDIBits( hdc,hbm,0,bmi.bmiHeader.biHeight,bmp.bmBits,&bmi,DIB_RGB_COLORS);
    

    Was bedeutet es denn wenn im Debugger, nach dem Inhalt einer Variable "{unused=???}" steht? Dies ist bei hbm, hdc, memDC und hbmOld der Fall.
    GetBitmapBits liefert nämlich einen richtigen Wert zurück.

    Falls es weiterhelfen sollte, so wird die Funktion aufgerufen:

    void CScreenshotDlg::OnLButtonDown(UINT nFlags, CPoint point)
    { ...
    GetCursorPos(&point); 
    pwindow = WindowFromPoint(point);
    ...
    test = HWNDtoIpl(pwindow);
    

    Schonmal Danke für die weitere Hilfe!
    MfG, Benni



  • Servus,

    sorry für denjenigen dem jetzt eventuell 10€ durch die Finger gehen (http://www.c-plusplus.net/forum/293454), aber hier wirst du gehelft:

    http://forum.openframeworks.cc/index.php?topic=1414.0

    Das sollte dein Problem lösen.

    gruß
    Hellsgore



  • Hey Hellsgore,
    vielen Dank für den Link.
    Ich habs jetzt nicht genaus so gemacht
    wie dort aber ich hab mir die Lösung ableiten können.

    Endlich hab ich das hinbekommen, vielen vielen Dank.

    MfG, Benni



  • Bitteschön,

    aber fein wäre es, wenn du jetzt noch die Lösung posten könntest. Ich denke mal, es könnte noch mehr Leute interessieren...

    gruß
    Hellsgore



  • OkiliDokili
    Soo diese Funktion macht aus einem *CWnd ein IplImage.

    IplImage *CWndtoIpl(CWnd *pWnd)
    {
    	CRect rect;
        HWND hWnd =  pwindow->GetSafeHwnd();
        pWnd     ->  GetClientRect(rect);
    
        int nWidth  = rect.right;
        int nHeight = rect.bottom;
    
    	HDC hDC = GetDC(hWnd);
    	HDC hMemDC = CreateCompatibleDC(hDC); 
    
    	IplImage *img;
    
    	HBITMAP hBitmap = CreateCompatibleBitmap( hDC, nWidth, nHeight);
    
    	BITMAPINFO bmi;
        ZeroMemory(&bmi, sizeof(bmi));
        bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth        = nWidth;
        bmi.bmiHeader.biHeight       = -(nHeight);        // Negativ damit das Bild von oben nach unten gemalt wird
        bmi.bmiHeader.biBitCount     = 32;                // Farbtiefe des Monitors
        bmi.bmiHeader.biPlanes       = 1;
        bmi.bmiHeader.biCompression  = BI_RGB;
        bmi.bmiHeader.biSizeImage    = 32 * nWidth * nHeight / 8;
    	BYTE *pbBits = new BYTE[bmi.bmiHeader.biSizeImage]; 
    
    	if( hBitmap)
    	{
    		HBITMAP	 hOld = (HBITMAP)SelectObject( hMemDC, hBitmap);
    		BitBlt( hMemDC, 0, 0, nWidth, nHeight, hDC, 0, 0, SRCCOPY);
    		SelectObject( hMemDC, hOld);
    
    		BITMAP bbmp;
    		GetObject( hBitmap, sizeof(BITMAP), &bbmp);
    
    		int nChannels = bbmp.bmBitsPixel == 1 ? 1 : bbmp.bmBitsPixel/8 ;
    		int depth = bbmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;8U;
    
    		GetDIBits(hDC, hBitmap, 0, nHeight, pbBits, &bmi,DIB_RGB_COLORS); 
    
    		DeleteObject(hBitmap); 
    
    		img = cvCreateImageHeader( cvSize(bbmp.bmWidth, bbmp.bmHeight), depth, nChannels );
    		img ->imageData = (char*)malloc(bbmp.bmHeight * bbmp.bmWidth * nChannels * sizeof(char));
    		memcpy( img->imageData,(char*)(pbBits), bbmp.bmHeight * bbmp.bmWidth * nChannels);
    	}
    
    	::DeleteDC(hDC);
        ::DeleteDC(hMemDC);
    	::DeleteObject(hWnd);
    
    	return img;
    }
    

    MfG,Benni


  • Mod

    👎

    Memory Leak von pbBits!



  • Statt manueller Speicherverwaltung bietet sich hier natürlich

    std::vector<BYTE> bits(bmi.bmiHeader.biSizeImage);
    

    an.
    Und den Cast

    HBITMAP     hOld = (HBITMAP)SelectObject( hMemDC, hBitmap);
    

    kannste dir sparen, wenn hOld ein HGDIOBJ ist.

    Und deklarier Variablen immer so spät wie möglich und initialisiere sie sofort, wann immer dies möglich ist.



  • Gut, ich hab mich jezt über diese Leaks
    informiert. Ist das Problem mit

    delete pbBits;
    

    gelöst?



  • Nein, pbBits zeigt ja nicht nur auf ein BYTE, sondern auf ein dynamisch reserviertes Array. Folglich müsste es

    delete[] pbBits;
    

    heißen.

    Aber spar dir doch diese Frickelei (sie ist in C++ unüblich und weist auf einen Codestil der 90er hin) und verwende Container der Standardbibliothek (hier in diesem Beispiel ist der std::vector die bessere Wahl).


Anmelden zum Antworten