CreateDIBSection



  • hallo,

    ich möchte gern Ein DI Bitmap aus einem BYTE Array erstellen. Alles was ich dafür hab ist ein BYTE Pointer mit den RGB Daten (im 24Bit Format) und die Größe des Bildes.

    Nun verlangt die Funktion CreateDIBSection einige Parameter, bei denen ich nicht so richtig weiss, wo ich die herbekommen soll...

    Fangen wir also an:

    HDC hdc
    Wo bekomme ich so ein Handle her? ich möchte das Bitmap am ende auf meinem Dialog darstellen, ich hab schon versucht den this zeiger zu benutzen ... ging natürlich nicht

    CONST BITMAPINFO
    in der MSDN steht dass sich Bitmapinfo aus BITMAPINFOHEADER und RGBQUAD zusammensetzt. Eine Variable für den BITMAPINFOHEADER habe ich mir bereits erstellt, und meine Daten dieser Variable zugewiesen.

    BITMAPINFOHEADER BmpInfoHdr;  //Struktur für Bitmap-Infoheader 
    		BmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER); 
    		BmpInfoHdr.biWidth = nWidth; 
    		BmpInfoHdr.biHeight = nHeight; 
    		BmpInfoHdr.biPlanes = 1; 
    		BmpInfoHdr.biBitCount = 24; 
    		BmpInfoHdr.biCompression    = BI_RGB; 
    		BmpInfoHdr.biSizeImage        = nWidth*nHeight*3;
    

    aber was ist mit RGBQUAD? müsste ich dort irgendwie meinen BYTE Pointer reinbeokmmen? Wenn ja wie?

    UINT iUsage
    hier hab ich einfach mal DIB_RGB_COLORS eingetragen ...

    ppvBits
    hier weiss ich gar nicht so recht was die MSDN da von mir will. Zeigt auf eine Variable die auf die Stelle der DI Bitmap bits zeigt ... muss hier irgendwie mein BYTE Pointer rein?

    hSection
    hab ich einfach auf NULL gesetzt ... wollte nicht noch einen Parameter mehr, mit dem ich nix anzufangen weiss 😃

    dwOffset
    wird laut MSDN ignoriert wenn hsection NULL ist ...

    ich hoffe mir kann jmd weiterhelfen

    mfg, TFTS



  • Google: site:msdn.microsoft.com CreateDIBSection
    hdc wird offenbar nur gebraucht, wenn du iUsage auf DIB_PAL_COLORS setzt, du kannst es dir z.B. mit GetDC besorgen.
    pbmi besteht aus dem Header (den du schon vernünftig gefüllt hast - nur in biSizeImage sollte die Länge des BYTE-Bereiches stehen) und der Farbpalette (für 24-Bit-Bilder muß dort NULL rein).
    iUsage ist entweder PAL (holt die Farbinformationen aus dem hdc) oder RGB (holt die Farbinformationen aus der Farbpalette bzw. dem Bild).
    ppvBits erhält einen Pointer auf die Variable, die die Daten verwaltet.
    hSection und dwOffset kannst du imho ignorieren.

    PS: wenn hSection NULL ist, reserviert die Funktion selber den nötigen Speicher und gibt dir seine Adresse in ppvBits zurück -> dort mußt du anschließend mit memcpy deine Daten eintragen.



  • den MSDN eintrag kenne ich natürlich schon.

    pbmi besteht aus dem Header (den du schon vernünftig gefüllt hast - nur in biSizeImage sollte die Länge des BYTE-Bereiches stehen)

    nWidth*nHeight*3 ist doch die länge meines byte arrays...

    hdc wird offenbar nur gebraucht, wenn du iUsage auf DIB_PAL_COLORS setzt, du kannst es dir z.B. mit GetDC besorgen.

    wie denn? ich kann mir unter diesen handles immer gar nicht so richtiges vorstellen, haben die was mit meinem Dialog zu tun?

    HDC hdc = GetDC(NULL);
    

    funktioniert nicht

    BmpInfo.bmiColors=NULL;
    

    funktioniert ebenfalls nicht



  • BitmapDIBUncompressed32Bit.h:

    //------------------------------------------------------------------------------
    // Last Change: 8-10-2005
    // Author: Julian Amann (vertexwahn@gmx.de)
    //
    // Brief description: simple class to handle 32 bit uncompressed bitmaps for 
    // windows
    //------------------------------------------------------------------------------
    
    #ifndef BitmapDIBUncompressed32Bit_h
    #define BitmapDIBUncompressed32Bit_h
    
    #include <windows.h>
    #include <stdio.h>
    
    #ifdef _MSC_VER
    	#pragma pack(push,packing)
    	#pragma pack(1)
    	#define PACK_STRUCT
    #else
    	#error you must byte-align these structures with appropriate compiler directives
    #endif
    
    //------------------------------------------------------------------------------------
    // a class for an uncompressed bitmap
    class BitmapDIBUncompressed32Bit
    {
    public:
    
    	BitmapDIBUncompressed32Bit(char * filename);
    	BitmapDIBUncompressed32Bit(HDC hdc, int width, int height);
    	int getWidth() const;
    	int getHeight() const;
    
    	void Save(char * filename);
    
    	virtual ~BitmapDIBUncompressed32Bit();
    
    	void Release();
    
    	HDC getHDC();
    
    	UINT * getBytes() const;
    	void setBytes(UINT * data)
    	{
    		BitmapBytes = data;
    	}
    
    private:
    	BitmapDIBUncompressed32Bit(const BitmapDIBUncompressed32Bit &src) {};
    
    	UINT					*BitmapBytes;
    	BITMAPINFO				BitmapInfo;
    	BITMAPINFOHEADER		BitmapInfoHeader;
    	HDC						BitmapHDC;
    	HBITMAP					BitmapHandle;
    };
    
    void CaptureScreen(BitmapDIBUncompressed32Bit &bitmap);
    
    // force default byte alignment
    #ifdef _MSC_VER
    	#pragma pack(pop, packing)
    #endif
    
    #undef PACK_STRUCT
    
    #endif
    

    BitmapDIBUncompressed32Bit.cpp:

    //------------------------------------------------------------------------------
    // Last Change: 8-10-2005
    // Author: Julian Amann (vertexwahn@gmx.de)
    //
    // Brief description: simple class to handle 32 bit uncompressed bitmaps for 
    // windows
    //------------------------------------------------------------------------------
    
    #include <windows.h>
    #include <stdio.h>
    #include "BitmapDIBUncompressed32Bit.h"
    
    #ifdef _MSC_VER
    	#pragma pack(push,packing)
    	#pragma pack(1)
    	#define PACK_STRUCT
    #else
    	#error you must byte-align these structures with appropriate compiler directives
    #endif
    
    BitmapDIBUncompressed32Bit::BitmapDIBUncompressed32Bit(char * filename)
    {
    	HBITMAP hBitmap =
    	(HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
        LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    
    	if(hBitmap==0)
    		MessageBox(NULL,"","",MB_OK);
    
    	BITMAP Bitmap;
    	GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
    	HDC tmpBitmapHDC = CreateCompatibleDC(0);
    	SelectObject(tmpBitmapHDC, hBitmap);
    
    	BitmapInfoHeader.biSize = sizeof(BitmapInfo);
    	BitmapInfoHeader.biWidth = Bitmap.bmWidth;
    	BitmapInfoHeader.biHeight = Bitmap.bmHeight;
    	BitmapInfoHeader.biCompression = BI_RGB;
    	BitmapInfoHeader.biBitCount = 32;
    	BitmapInfoHeader.biPlanes = 1;
    	BitmapInfoHeader.biSizeImage = 0;
    	BitmapInfoHeader.biClrImportant = 0;
    	BitmapInfoHeader.biClrUsed = 0;
    	BitmapInfoHeader.biSizeImage = 0;
    	BitmapInfoHeader.biXPelsPerMeter = 0;
    	BitmapInfoHeader.biYPelsPerMeter = 0;
    
    	BitmapInfo.bmiHeader = BitmapInfoHeader;
    
    	BitmapHDC	 = CreateCompatibleDC(0); 
    
    	BitmapHandle = CreateDIBSection(0, &BitmapInfo, 
    									0, (void**)&BitmapBytes, NULL, 0);
    
    	SelectObject(BitmapHDC, BitmapHandle);
    
    	BitBlt(BitmapHDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, tmpBitmapHDC, 0, 0, SRCCOPY);
    
    	DeleteObject(hBitmap);
    }
    
    BitmapDIBUncompressed32Bit::BitmapDIBUncompressed32Bit(HDC hdc, int width, int height)
    {
    	BitmapInfoHeader.biSize = sizeof(BitmapInfo);
    	BitmapInfoHeader.biWidth = width;
    	BitmapInfoHeader.biHeight = height;
    	BitmapInfoHeader.biCompression = BI_RGB;
    	BitmapInfoHeader.biBitCount = 32;
    	BitmapInfoHeader.biPlanes = 1;
    	BitmapInfoHeader.biSizeImage = 0;
    	BitmapInfoHeader.biClrImportant = 0;
    	BitmapInfoHeader.biClrUsed = 0;
    	BitmapInfoHeader.biSizeImage = 0;
    	BitmapInfoHeader.biXPelsPerMeter = 0;
    	BitmapInfoHeader.biYPelsPerMeter = 0;
    
    	BitmapInfo.bmiHeader = BitmapInfoHeader;
    
    	BitmapHDC	 = CreateCompatibleDC(hdc); 
    
    	BitmapHandle = CreateDIBSection(hdc, &BitmapInfo, 
    									0, (void**)&BitmapBytes, NULL, 0);
    
    	SelectObject(BitmapHDC, BitmapHandle);
    }
    
    int BitmapDIBUncompressed32Bit::getWidth() const
    {
    	return BitmapInfoHeader.biWidth;
    }
    
    int BitmapDIBUncompressed32Bit::getHeight() const
    {
    	return BitmapInfoHeader.biHeight;
    }
    
    void BitmapDIBUncompressed32Bit::Save(char * filename)
    {
    	int imagesize = getWidth() * getHeight() * 4;	
    
    	BITMAPFILEHEADER BitmapFileHeader;						    // File Header
    	BitmapFileHeader.bfType		 = 0x4D42;						// Signatur 0x4D42 (="BM")
    	BitmapFileHeader.bfSize		 = sizeof(BITMAPFILEHEADER) +   // Gesamtgröße der Datei in Bytes
    		                           sizeof(BITMAPINFOHEADER) + 
    							       imagesize; 
    	BitmapFileHeader.bfReserved1 = 0;							// immer 0
    	BitmapFileHeader.bfReserved2 = 0;							// immer 0
    	BitmapFileHeader.bfOffBits   = 54;							// Offset der Pixeldaten innerhalb der Datei (bei uncompressed 32 bit immer 54 Bytes)
    
    	BITMAPINFOHEADER BitmapInfoHeader;							// Bitmap Info Header
    	BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);			// Größe der Struktur in Bytes (40)
    	BitmapInfoHeader.biWidth = getWidth();						// Breite des Bildes in Pixel
    	BitmapInfoHeader.biHeight = getHeight();					// Höhe des Bildes in Pixel
    	BitmapInfoHeader.biPlanes = 1;								// = 1
    	BitmapInfoHeader.biBitCount = 32;							// 32 Bits Pro Pixel
    	BitmapInfoHeader.biCompression = BI_RGB;					// Komprimierung (0 = keine)
    	BitmapInfoHeader.biSizeImage = imagesize;					// Umfang der Pixeldaten in Bytes
    	BitmapInfoHeader.biXPelsPerMeter = 0;						// horizontale Auflösung (Pixel pro Meter)
    	BitmapInfoHeader.biYPelsPerMeter = 0;						// vertikale Aufläsung (Pixel pro Meter)
    	BitmapInfoHeader.biClrUsed       = 0;						// Zahl der verwendeten Farben
    	BitmapInfoHeader.biClrImportant  = 0;						// Zahl der wichtigen Farben
    
    	FILE *ptrFile = NULL;	
    	ptrFile = fopen(filename, "wb");
    	fwrite(&BitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, ptrFile);		
    	fwrite(&BitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, ptrFile);
    
    	fwrite(BitmapBytes, getWidth() * getHeight() * 4, 1, ptrFile);
    
    	fclose(ptrFile);
    }
    
    BitmapDIBUncompressed32Bit::~BitmapDIBUncompressed32Bit()
    {
    	Release();
    }
    
    void BitmapDIBUncompressed32Bit::Release()
    {
    	DeleteObject(BitmapHandle);
    }
    
    HDC BitmapDIBUncompressed32Bit::getHDC()
    {
    	return BitmapHDC;
    }
    
    UINT * BitmapDIBUncompressed32Bit::getBytes() const
    {
    	return BitmapBytes;
    }
    
    void CaptureScreen(BitmapDIBUncompressed32Bit &bitmap)
    {
    	HDC hdcDesktop = GetWindowDC(GetDesktopWindow());
    	BitBlt(bitmap.getHDC(), 0, 0, bitmap.getWidth(), bitmap.getHeight(),
    		   hdcDesktop, 0, 0, SRCCOPY);
    }
    
    // force default byte alignment
    #ifdef _MSC_VER
    	#pragma pack(pop, packing)
    #endif
    
    #undef PACK_STRUCT
    


  • HBITMAP hBitmap;
    	BITMAP Bitmap;
    	HDC tmpBitmapHDC;
    
    	BYTE                    *pBGRData; 
        BITMAPINFO                BitmapInfo; 
        BITMAPINFOHEADER        BitmapInfoHeader; 
        HDC                        BitmapHDC; 
        HBITMAP                    BitmapHandle; 
    
    	hBitmap = (HBITMAP)LoadImage(NULL,m_csCurrentDir+m_csCurrentFile, IMAGE_BITMAP, 0, 0, 
        LR_LOADFROMFILE|LR_CREATEDIBSECTION); 
    
        GetObject(hBitmap, sizeof(BITMAP), &Bitmap); 
        tmpBitmapHDC = CreateCompatibleDC(0); 
        SelectObject(tmpBitmapHDC, hBitmap); 
    
        BitmapInfoHeader.biSize = sizeof(BitmapInfo); 
        BitmapInfoHeader.biWidth = Bitmap.bmWidth; 
        BitmapInfoHeader.biHeight = Bitmap.bmHeight; 
        BitmapInfoHeader.biCompression = BI_RGB; 
        BitmapInfoHeader.biBitCount = 24; 
        BitmapInfoHeader.biPlanes = 1; 
        BitmapInfoHeader.biSizeImage = 0; 
        BitmapInfoHeader.biClrImportant = 0; 
        BitmapInfoHeader.biClrUsed = 0; 
        BitmapInfoHeader.biSizeImage = 0; 
        BitmapInfoHeader.biXPelsPerMeter = 0; 
        BitmapInfoHeader.biYPelsPerMeter = 0; 
    
        BitmapInfo.bmiHeader = BitmapInfoHeader; 
    
        BitmapHDC     = CreateCompatibleDC(0); 
    
        BitmapHandle = CreateDIBSection(0, &BitmapInfo,0, (void**)&pBGRData, NULL, 0);
    

    müsste nach dem ich diesen code abarbeite, nicht eigentlich die BGR-Farbdaten in meinem pBGRData liegen? es scheint nicht so ... wie bekomm ich die dort rein? vielleicht irgendwie mit GetDIBits(...)

    mfg, TFTS



  • UINT * BitmapDIBUncompressed32Bit::getBytes() const 
    { 
        return BitmapBytes; 
    }
    

    wenn du ein Pixel ändern willst gehst du wie folgt vor:

    UINT data =BMP.getBytes();
    data[x+y*BMP.getHeight()] = 0xFFFF0000;  // Setzt Pixel auf rot
    


  • müsste nach dem ich diesen code abarbeite, nicht eigentlich die BGR-Farbdaten in meinem pBGRData liegen?

    yup - das tuen sie auch!
    einfach mal pBGRData[0] = 43545; schon hast du die Farbe des ersten Pixels verändert



  • ah moment...vielleicht liegt es daran, warum es nicht bei mir funktioniert:
    ich hab es ja jetzt als BYTE Pointer definiert, ein BYTE hat natürlich nur 256 Werte... werden die pixel etwa nicht als RGB zurückgegeben, also jeder kanal einzeln sondern als ein Farbwert zwischen 0 und 65535? ... ich bräuchte es ja als RGB ...

    mfg, TFTS

    noch etwas... ich möchte die bilder gern auf meinem Dialog darstellen. Bis jetzt hab ich das über ein CBitmap Objekt gemacht. Kann ich denn irgendwie diese ganzen variablen in ein CBitmap Objekt packen? ich hab es mit FromHandle(hBitmap) und mit FromHandle(BitmapHandle) versucht ... ging beides nich

    und so verwende ich dann das CBitmap zum zeichnen... die Daten werden an ein CDC Pointer übergeben. In der OnPaint Fkt wird dann der CDC pointer per BitBlt bzw. StretchBlt auf den Dialog gebracht

    m_pVirtualDC->SelectObject(pCBitmap);
    	//m_pBitmap=pCBitmap;
    	pCBitmap->DeleteObject();
    
    	m_bDrawPicture = true;
    	CPicConvert::GetStretchDimension(m_nCurrentWidth,m_nCurrentHeight,m_nMaxWidth,m_nMaxHeight,&m_nStretchedWidth,&m_nStretchedHeight);
    //Aufruf der OnPaint...
    	//this->Invalidate();
    	CRect crPicRect;
    
    	if(((m_bScale && m_bScaleNeeded) || !m_bScaleNeeded) && m_bStretchToMax)
    		crPicRect.SetRect(m_nHScrollPos+m_nXPicOffset,m_nVScrollPos+m_nYPicOffset,m_nHScrollPos+m_nXPicOffset+m_nStretchedWidth,m_nVScrollPos+m_nYPicOffset+m_nStretchedHeight);
    	else
    		crPicRect.SetRect(m_nHScrollPos+m_nXPicOffset,m_nVScrollPos+m_nYPicOffset,m_nHScrollPos+m_nXPicOffset+m_nCurrentWidth, m_nVScrollPos+m_nYPicOffset+m_nCurrentHeight);
    
    	this->InvalidateRect(crPicRect,true);
    


  • BitmapInfoHeader.biBitCount = 32;                            // 32 Bits Pro Pixel
    

    hier lege ich fest, das ich eine Farbtiefe von 32 Bit Benutzen möchte

    folgende anordnung:

    0xAARRGGBB
    


  • bei den MFC spezifischen Sachen solltest du vielleicht mal im MFC Forum nachfragen



  • meine erste frage war eigentlich nicht mfc spezifisch. wie bekomme ich denn aus dem UINT die einzelnen Farbwerte (Rot Grün Blau) auf meinen BYTE Vektor ... der byte vektor müsste ja dann die 3-fache länge des UINT Vektors haben, oder?

    also was ich eigentlich wissen will ist, ob das hier funktioniert,

    BitmapHandle = CreateDIBSection(0, &BitmapInfo,0, (void**)&pBGRData, NULL, 0);
    

    wenn es sich bei pBGRData um einen BYTE Pointer handelt.

    mfg, TFTS



  • wie bekomme ich denn aus dem UINT die einzelnen Farbwerte (Rot Grün Blau) auf meinen BYTE Vektor ...

    durch Bitmasken

    vielleicht hilft dir auch folgendes:
    Tutorial über das BMP Format:
    http://turing.fh-landshut.de/~jamann/Das BMP Format.html
    Demoprogramm, das DibCreateSection verwendet:
    http://turing.fh-landshut.de/~jamann/Tunnel Effect.zip


Anmelden zum Antworten