?
Danke, es funktioniert jetzt.
Das Auslesen der Bilddaten und das Speichern der Datei scheinen mir in meiner Version doch extrem umständlich. Ich benutze folgende 3 Methoden aus meiner "Bilder" Klasse. (Ich habe mir die Methoden größtenteils aus der MSDN zusammengesucht)
Gibt es eine einfachere Möglichkeit als diese:
PBITMAPINFO Bilder::CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
//Hole das Bitmap color (farb) format, Breite, und höhe.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
{}
// Convertiere das color (farb) Format zu einer Anzahl von Bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
//Belege Speicher für die BITMAPINFO Structur. (Diese Struktur
//enthält eine BITMAPINFOHEADER Struktur und ein Array von RGB QUAD
//Daten Structuren.)
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1<< cClrBits));
// Es ist kein RGBQUAD Array für das 24-bit-per-pixel Format vorhanden
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
// Initialisiere die Felder der BITMAPINFO Struktur.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24)
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
//Wenn die Bitmap nicht komprimiert ist, setze das BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
//Berechne die Anzahl von Bytes in dem Color indices Array
//und speichere das Ergebnis in biSizeImage.
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi->bmiHeader.biHeight;
// Sete biClrImportant auf 0, um anzuzeigen, dass alle device farben wichtig sind
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
void Bilder::CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
{
HANDLE hf; //file handle
BITMAPFILEHEADER hdr; //bitmap file-header
PBITMAPINFOHEADER pbih; //bitmap info-header
LPBYTE lpBits; //Speicher pointer
DWORD dwTotal; //totale Anzahl von bytes
DWORD cb; //Zusätzliche Anzahl von Bytes
BYTE *hp; //Byte pointer
DWORD dwTmp;
pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits)
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
//Holen der color table (RGBQUAD Array) und der Bits
//(array von palette indices) von der "DIB".
if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
DIB_RGB_COLORS))
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
//Erzeuge die .BMP Datei.
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
hdr.bfType = 0x4d42; //0x42 = "B" 0x4d = "M"
//berechne die Größe von der gesamten Datei.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Berechne den Offset des Arrays von Farb indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof (RGBQUAD);
//Kopiere die BITMAPFILEHEADER in die .BMP Datei.
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, NULL))
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
//Kopiere die BITMAPINFOHEADER und RGBQUAD Arrays in die datei.
if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, ( NULL)))
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
dwTotal = cb = pbih->biSizeImage; //kopiere das Array der color indices in die .BMP Datei.
hp = lpBits;
if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
if (!CloseHandle(hf)) //Schließe die .BMP Datei.
{} //// Hier fehlt noch eine Fehlermeldung /Fehlerbehandlung //
GlobalFree((HGLOBAL)lpBits); //gib den Speicher frei.
}
HBITMAP Bilder::erzeuge_Manipuliertes_Bild( LPCWSTR file) {
int width, height; //Variablen
HBITMAP bitmap;
HBITMAP newBitmap=NULL;
if(!file) return NULL; //Wenn der angegebene Pfad nicht existiert, liefere NULL als HBITMAP zurück
bitmap= (HBITMAP)LoadImage(0,file,IMAGE_BITMAP, 0, 0, //Lade das Bitmap in HBITMAP
LR_DEFAULTSIZE|LR_LOADFROMFILE|LR_CREATEDIBSECTION);
BITMAP bm;
GetObject(bitmap, sizeof(BITMAP), &bm); //Kopiert das BITMAP aus dem HBITMAP
width=bm.bmWidth; //Breite und hoehe auslesen
height=bm.bmHeight;
HDC SrcDC=CreateCompatibleDC(NULL); //Passenden HDC erzeugen
SelectObject(SrcDC,bitmap); //OBjekt selektieren
DWORD col1;
for(int y=0; y<height; y++) //Durchlaufe alle Pixel
{
for(int x=0; x<width; x++)
{
col1=GetPixel(SrcDC,x,y); //Pixelfarben auslesen
byte r,g,b;
r=GetRValue(col1);
g=GetGValue(col1);
b=GetBValue(col1);
int gesamt = r+g+b; //Wenn die Summe der Farben eines Pixels kleiner 72 ist
if(gesamt<72)
{
SetPixel(SrcDC,x,y,RGB(0,255,0)); //setzte ein braunes Pixel
}
else
{
SetPixel(SrcDC,x,y,RGB(139,69,19)); //sonst ein rotes
}
}
}
DeleteDC(SrcDC); //HDC freigeben
return bitmap; //HBITMAP zurückgeben
}
Ich rufe dies in der main Methode folgendermaßen auf:
int main()
{
HWND hWnd=GetConsoleWindow();
HDC hDC=GetDC(NULL);
Bilder b = Bilder();
HBITMAP h= b.erzeuge_Manipuliertes_Bild(L"1.bmp");
b.CreateBMPFile(hWnd,L"2.bmp",b.CreateBitmapInfoStruct(hWnd,h),h,hDC);
return 1;
}