Bmp



  • Hallo,

    ich erstelle eine Bmp mit dem unten aufgeführten code von einem hdc.
    Was muss ich ändern, um ein schwarz-weiss BMP zu erhalten?

    int dc2bitmap(HDC hdc, int width, int height,int swidth,int sheight, char *filename)		
    {	
        HDC hdc2;
        HBITMAP aBmp;
        BITMAPINFO bi;
        HGDIOBJ OldObj;
        void *dibvalues;
        HANDLE fileHandle;
    
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
            DWORD bytes_write;
        DWORD bytes_written;
    
        hdc2=CreateCompatibleDC(hdc);
    
        ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
        bmih.biSize=sizeof(BITMAPINFOHEADER);
          bmih.biHeight=height-sheight;
            bmih.biWidth=width-swidth;
            bmih.biPlanes=1;
            bmih.biBitCount=24; //24
        bmih.biCompression=BI_RGB;
        bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight;
            bmih.biXPelsPerMeter = 0;
            bmih.biYPelsPerMeter = 0;
            bmih.biClrImportant = 0;
    
        bi.bmiHeader=bmih;
    
        aBmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL)
        {
            OutputDebugString("CreateDIBSection failed!\n");
            return 0;
        }
    
        OldObj=SelectObject(hdc2,aBmp);
        BitBlt(hdc2,0,0,width-swidth,height-sheight,hdc,swidth,sheight,SRCCOPY);
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
        bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
            bmfh.bfType=0x4d42;
            bmfh.bfReserved1 = 0;
            bmfh.bfReserved2 = 0;
    
        fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,
                                                        CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
        if (fileHandle==INVALID_HANDLE_VALUE)
        {
            OutputDebugString("CreateFile failed!\n");
            return 0;
        }
    
            // Write the BITMAPFILEHEADER
            bytes_write=sizeof(BITMAPFILEHEADER);
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the BITMAPINFOHEADER
        bytes_write=sizeof(BITMAPINFOHEADER);
        if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the Color Index Array
            bytes_write=bmih.biSizeImage;
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
        CloseHandle(fileHandle);
    
        DeleteObject(SelectObject(hdc2,OldObj));
        DeleteDC(hdc2);
    
        return 1;
    }
    


  • bmih.biBitCount wird's wohl sein - aber wozu der ganze Umstand mit CreateDIBSection?
    Nimm einfach CreateCompatibleBitmap und übergib für hdc hdc2, denn der ist nach dem Erstellen automatisch monochrom (SW) 😉



  • Ich habe diese varianten ausprobiert:

    int dc2bitmap(HDC hdc, int width, int height,int swidth,int sheight, char *filename)		//das eigendliche erstellen der Bitmap
    {	
        HDC hdc2;
        HBITMAP aBmp;
        BITMAPINFO bi;
        HGDIOBJ OldObj;
        void *dibvalues;
        HANDLE fileHandle;
    
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
            DWORD bytes_write;
        DWORD bytes_written;
    
        hdc2=CreateCompatibleDC(hdc);
    
        aBmp=CreateCompatibleBitmap(hdc2,width,height);		//neu
    
    	CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL)
        {
            OutputDebugString("CreateDIBSection failed!\n");
            return 0;
        }
    
        OldObj=SelectObject(hdc2,aBmp);
        BitBlt(hdc2,0,0,width-swidth,height-sheight,hdc,swidth,sheight,SRCCOPY);
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
        bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
            bmfh.bfType=0x4d42;
            bmfh.bfReserved1 = 0;
            bmfh.bfReserved2 = 0;
    
        fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,
                                                        CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
        if (fileHandle==INVALID_HANDLE_VALUE)
        {
            OutputDebugString("CreateFile failed!\n");
            return 0;
        }
    
            // Write the BITMAPFILEHEADER
            bytes_write=sizeof(BITMAPFILEHEADER);
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the BITMAPINFOHEADER
        bytes_write=sizeof(BITMAPINFOHEADER);
        if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the Color Index Array
            bytes_write=bmih.biSizeImage;
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
        CloseHandle(fileHandle);
    
        DeleteObject(SelectObject(hdc2,OldObj));
        DeleteDC(hdc2);
    
        return 1;
    }
    

    Hier ist das Bild einfach nur schwarz!?

    int dc2bitmap(HDC hdc, int width, int height,int swidth,int sheight, char *filename)		//das eigendliche erstellen der Bitmap
    {	
        HDC hdc2;
        HBITMAP aBmp;
        BITMAPINFO bi;
        HGDIOBJ OldObj;
        void *dibvalues;
        HANDLE fileHandle;
    
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
            DWORD bytes_write;
        DWORD bytes_written;
    
        hdc2=CreateCompatibleDC(hdc);
    
        ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
        bmih.biSize=sizeof(BITMAPINFOHEADER);
          bmih.biHeight=height-sheight;
            bmih.biWidth=width-swidth;
            bmih.biPlanes=1;
            bmih.biBitCount=2; //Neu
        bmih.biCompression=BI_RGB;
        bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight;
            bmih.biXPelsPerMeter = 0;
            bmih.biYPelsPerMeter = 0;
            bmih.biClrImportant = 0;
    
        bi.bmiHeader=bmih;
    
        aBmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL)
        {
            OutputDebugString("CreateDIBSection failed!\n");
            return 0;
        }
    
        OldObj=SelectObject(hdc2,aBmp);
        BitBlt(hdc2,0,0,width-swidth,height-sheight,hdc,swidth,sheight,SRCCOPY);
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
        bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
            bmfh.bfType=0x4d42;
            bmfh.bfReserved1 = 0;
            bmfh.bfReserved2 = 0;
    
        fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,
                                                        CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
        if (fileHandle==INVALID_HANDLE_VALUE)
        {
            OutputDebugString("CreateFile failed!\n");
            return 0;
        }
    
            // Write the BITMAPFILEHEADER
            bytes_write=sizeof(BITMAPFILEHEADER);
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the BITMAPINFOHEADER
        bytes_write=sizeof(BITMAPINFOHEADER);
        if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
            //Write the Color Index Array
            bytes_write=bmih.biSizeImage;
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL))
        {
            OutputDebugString("WriteFile failed!\n");
            return 0;
        }
    
        CloseHandle(fileHandle);
    
        DeleteObject(SelectObject(hdc2,OldObj));
        DeleteDC(hdc2);
    
        return 1;
    }
    

    Hier ist das Format irgendwie zerstört und das bmp kann nicht angezeigt werden

    Was habe ich falsch gemacht?



  • Sorry, hatte mir den Code nicht genau angeschaut 🙄 - du musst natürlich schon bmih.biBitCount verwenden, aber natürlich nicht 2, sondern 1 (2 bit wären ja 4 Farben 😉 - aber das darf gar nicht angegeben werden). Also 1 angeben und dann noch bmiColors entsprechend füllen:

    The bitmap is monochrome, and the bmiColors member of BITMAPINFO contains two entries. Each bit in the bitmap array represents a pixel. If the bit is clear, the pixel is displayed with the color of the first entry in the bmiColors table; if the bit is set, the pixel has the color of the second entry in the table.



  • Hallo, das will einfach nich funzen!

    Kannst Du mir mal den veränderten Code posten, so dass es klappt? 😃



  • Ich poste mal nur den Ausschnitt: (ist allerdings nicht getestet - lässt sich aber wenigstens schonmal compilieren 😉 )

    hdc2=CreateCompatibleDC(hdc);
    
    LPBITMAPINFO lpbi;
    lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD))];
    ZeroMemory(&lpbi,sizeof(lpbi));
    
    lpbi->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth       = 56;
    lpbi->bmiHeader.biHeight      = 567;
    lpbi->bmiHeader.biPlanes      = 1;
    lpbi->bmiHeader.biBitCount    = 1;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->bmiHeader.biSizeImage   = ((((lpbi->bmiHeader.biWidth * lpbi->bmiHeader.biBitCount) + 31) & ~31) >> 3) * lpbi->bmiHeader.biHeight;
    
    lpbi->bmiColors[0].rgbRed   = 0;
    lpbi->bmiColors[0].rgbGreen = 0;
    lpbi->bmiColors[0].rgbBlue  = 0;
    
    lpbi->bmiColors[1].rgbRed   = 255;
    lpbi->bmiColors[1].rgbGreen = 255;
    lpbi->bmiColors[1].rgbBlue  = 255;
    
    aBmp = CreateDIBSection(hdc,lpbi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    


  • Hallo,

    ich habe das ausprobiert. Ja es lässt sich compilieren, aber das bild ist einfach nur schwarz.

    Ich habe nochmal darüber nachgedacht und meine das ganze hat möglicherweise einen Denkfehler.

    1. Ich wollte nur schwarz-weiss. Also müsste der Computer entscheiden,
    ab welchem "Helligkeitswert" der entsprechende Bildpunkt weiss und wann
    schwarz wird.(Dies fehlt ja) 😕
    Bitte schreiben wenn hier eine Denkfehler drin ist!

    2. Ich glaube es ist besser Grauabstufungen zuzulassen. Also 256 grautöne.
    Wie mache ich dass den?
    kannman mit BitBlt(...) irgendwie Buntes in Grauabstufungen kopieren?



  • Das hat mir keine Ruhe gelassen - jetzt klappt's endlich:

    int dc2bitmap(HDC hdc, int width, int height, char *filename) 
    { 
        HDC hdc2; 
        HBITMAP aBmp; 
        HGDIOBJ OldObj; 
        void *dibvalues; 
        HANDLE fileHandle; 
    
        BITMAPFILEHEADER bmfh; 
    
        DWORD bytes_write; 
        DWORD bytes_written; 
    
    	hdc2=CreateCompatibleDC(hdc); 
    
    	DWORD sizeBI = sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD));
    	LPBITMAPINFO lpbi = (LPBITMAPINFO) new char[sizeBI];
    	ZeroMemory(lpbi,sizeBI);
    
    	lpbi->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER); 
    	lpbi->bmiHeader.biWidth       = width; 
    	lpbi->bmiHeader.biHeight      = height; 
    	lpbi->bmiHeader.biPlanes      = 1; 
    	lpbi->bmiHeader.biBitCount    = 8; 
    	lpbi->bmiHeader.biCompression = BI_RGB; 
    	lpbi->bmiHeader.biSizeImage   = ((((lpbi->bmiHeader.biWidth * lpbi->bmiHeader.biBitCount) + 31) & ~31) >> 3) * lpbi->bmiHeader.biHeight; 
    
    	for(int i = 0; i < 256; i++)
    	{
    		lpbi->bmiColors[i].rgbRed   = i; 
    		lpbi->bmiColors[i].rgbGreen = i; 
    		lpbi->bmiColors[i].rgbBlue  = i; 
    	}
    	aBmp = CreateDIBSection(hdc,lpbi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL);
    
        if (aBmp==NULL) 
        { 
            OutputDebugString("CreateDIBSection failed!\n"); 
            return 0; 
        } 
    
        OldObj=SelectObject(hdc2,aBmp); 
        BitBlt(hdc2,0,0,width,height,hdc,0,0,SRCCOPY); 
    
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER)); 
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeBI; 
        bmfh.bfSize=(lpbi->bmiHeader.biHeight*lpbi->bmiHeader.biWidth)+sizeof(BITMAPFILEHEADER)+sizeBI; 
    	bmfh.bfType=0x4d42; 
    
        fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL); 
        if (fileHandle==INVALID_HANDLE_VALUE) 
        { 
            OutputDebugString("CreateFile failed!\n"); 
            return 0; 
        } 
    
        // Write the BITMAPFILEHEADER 
        bytes_write=sizeof(BITMAPFILEHEADER); 
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL)) 
        { 
            OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        //Write the BITMAPINFOHEADER 
        bytes_write=sizeBI; 
        if (!WriteFile(fileHandle,(void*)lpbi,bytes_write,&bytes_written,NULL)) 
        { 
            OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        //Write the Color Index Array??? 
        bytes_write=lpbi->bmiHeader.biSizeImage;//3*bmih.biHeight*bmih.biWidth; 
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL)) 
        { 
            OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        CloseHandle(fileHandle); 
    
        DeleteObject(SelectObject(hdc2,OldObj)); 
        DeleteDC(hdc2); 
    
        return 1; 
    }
    


  • Das gibt dann kein Schwarz/Weiss sondern eine Graustufen-Bitmap, oder ?



  • Ja, so wollte er es ja jetzt haben:

    Andreas XXL schrieb:

    Ich glaube es ist besser Grauabstufungen zuzulassen.

    Für SW sonst halt einfach entsprechend anpassen:

    DWORD sizeBI = sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD));
    // [...]
    lpbi->bmiHeader.biBitCount = 1;
    // [...]
    /*for(int i = 0; i < 256; i++)
    {
        lpbi->bmiColors[i].rgbRed   = i; 
        lpbi->bmiColors[i].rgbGreen = i; 
        lpbi->bmiColors[i].rgbBlue  = i; 
    }*/
    lpbi->bmiColors[1].rgbRed   = 255; 
    lpbi->bmiColors[1].rgbGreen = 255; 
    lpbi->bmiColors[1].rgbBlue  = 255;
    


  • k, wollte nur sicherstellen, dass ich den Quellcode richtig verstanden hab 😉



  • hallo, der code ballert hier immer ohne Fehlermeldung ab.

    for(int i = 0; i < 256; i++)
    {
    lpbi->bmiColors[i].rgbRed = i;
    lpbi->bmiColors[i].rgbGreen = i;
    lpbi->bmiColors[i].rgbBlue = i;
    }

    Wie soll das überhaupt gehen, wenn:

    typedef struct tagBITMAPINFO { // bmi
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD bmiColors[1];
    } BITMAPINFO;

    von "REGBQUAD bmiColors[1]" nur einer definiert ist?



  • Was meinst du mit "ballert hier immer ohne Fehlermeldung ab" 😕
    btw: bei mir läuft der Code 🙄



  • Andreas XXL schrieb:

    Wie soll das überhaupt gehen, wenn von "REGBQUAD bmiColors[1]" nur einer definiert ist?

    Laut Platform SDK, ist das ein Array, dass immer soviele Elemente hat, wie die Bitmap Farben hat (was auch logisch ist, da es ja die Farbpalette ist), wenn du also biBitCount=8 (also 1 Byte) setzt, hat die Palette 8 Bit Elemente, also 256 Stück.
    Unter der Voraussetzung dass ich aus dem PSDK jetzt nicht mumpitz gelesen hab 😉

    Das RGBQUAD bmiColors[1]; wundert mich allerdings auch irgendwie...



  • Ok,klappt jetzt! (Hatte in anderen Methoden ungültigen Dateinamen angegeben) 😃

    DANKE!



  • geeky schrieb:

    Das RGBQUAD bmiColors[1]; wundert mich allerdings auch irgendwie...

    Ich könnte mir das so erklären, dass die Daten eben zusammenhängend abgelegt werden sollten, deswegen nicht einfach ein Pointer! Da aber die Größe der Palette nicht fest vorgegeben sein soll hat man einfach mal 1 genommen. Ist zwar etwas unhandlig, aber da die Daten ja nachher direkt in eine Datei geschrieben werden sollen kann ich das Vorgehen eigentlich nachvollziehen - falls ich in meiner Annahme überhaupt richtig liege 😃


Log in to reply