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 nichtCONST 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 weissdwOffset
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