Bitmap erstellen - Fehler - Keine Bildaten werden angezeigt



  • Hallo,

    der angefügte Code sollte eigentlich nen rotes Bitmap erzeugen, jedoch ist die Bilddatei korrupt. Die größe der Bmp sagt mir eigentlich das da was sein müsste. Kann jmd. den Fehler finden ?

    Danke 🙂

    #pragma once
    
    #include "stdafx.h"
    #include <windows.h>
    #include <fstream>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    int main(){
    
    	int x ,y; //declare variables
    
    	ofstream bmpdata("test.bmp", ios_base::out | ios_base::binary); //begin stream
    
    	if (!bmpdata) return 1;
    
    	BITMAPFILEHEADER bmpfile;	//Fileheader Data
    	bmpfile.bfType = 'BM';
    	bmpfile.bfSize = (300 * 200 * (32 / 8)) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    	bmpfile.bfReserved1 = 0;
    	bmpfile.bfReserved2 = 0;
    	bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
    	BITMAPINFOHEADER bmpinfo; //Infoheader Data
    	bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
    	bmpinfo.biWidth = 300;
    	bmpinfo.biHeight = 200;
    	bmpinfo.biPlanes = 1;
    	bmpinfo.biBitCount = 32;
    	bmpinfo.biCompression = BI_RGB;
    	bmpinfo.biSizeImage = 0;
    	bmpinfo.biXPelsPerMeter = 0;
    	bmpinfo.biYPelsPerMeter = 0;
    	bmpinfo.biClrUsed = 0;
    	bmpinfo.biClrImportant = 0;
    
    	bmpdata << (LPBITMAPFILEHEADER)&bmpfile;
    	bmpdata << (LPBITMAPINFOHEADER)&bmpinfo;
    
    	RGBQUAD bmp; //Image Data
    	bmp.rgbBlue=0;
    	bmp.rgbGreen=0;
    	bmp.rgbRed=255;
    	bmp.rgbReserved=0;
    
    	if(bmpinfo.biBitCount == 32) //fill image
    	{
    		for (x=0; x < bmpinfo.biHeight ; x++){
    			for (y=0; y < bmpinfo.biWidth; y++){
    				bmpdata << (char) 0 << (char) 0 << (char) 255;			
    			}
    		}
    		bmpdata.close();
    		return 0;
    	}
    
    	bmpdata.close();
    	return 1;
    }
    


  • bmpdata << (LPBITMAPFILEHEADER)&bmpfile;
    bmpdata << (LPBITMAPINFOHEADER)&bmpinfo;
    

    1. du schreibst damit die addressen in die datei und nicht den inhalt
    2. << ist für textdateien, für binäre nimmst du besser write

    bmpdata.write(&bmpfile, sizeof(bmpfile));
    

    hier dasselbe

    long pix = 255;
    for (x=0; x < bmpinfo.biHeight ; x++)
        for (y=0; y < bmpinfo.biWidth; y++)
            bmpdata.write(&pix, sizeof(long));           
    bmpdata.close();
    return 0;
    

    oder besser

    long *pixel = new long[bmpinfo.biHeight * bmpinfo.biWidth];
    for (unsigned i = 0; i < bmpinfo.biHeight * bmpinfo.biWidth; ++i)
        pixel[i] = 255;
    bmpdata.write(pixel, bmpinfo.biHeight * bmpinfo.biWidth * sizeof(long));
    delete[] pixel;
    

    habs nicht getestet, sollte aber klappen

    wo lernt man eigentlich die klammern immer hinter das if zu packen ?? 🙄



  • Leider wird immernoch kein Bild dargestellt 😞

    #pragma once
    
    #include "stdafx.h"
    #include <windows.h>
    #include <fstream>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    int main(){
    
    	ofstream bmpdata("bitmap24.bmp", ios_base::out | ios_base::binary); //begin stream
    
    	if (!bmpdata) return 1;
    
    	BITMAPFILEHEADER bmpfile;	//Fileheader Data
    	bmpfile.bfType = 'BM';
    	bmpfile.bfSize = (300 * 200 * (24 / 8)) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //aggregate - bmpfile
    	bmpfile.bfReserved1 = 0;
    	bmpfile.bfReserved2 = 0;
    	bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
    	BITMAPINFOHEADER bmpinfo; //Infoheader Data
    	bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
    	bmpinfo.biWidth = 300;
    	bmpinfo.biHeight = 200;
    	bmpinfo.biPlanes = 1;
    	bmpinfo.biBitCount = 24;															
    	bmpinfo.biCompression = BI_RGB;
    	bmpinfo.biSizeImage = 0;
    	bmpinfo.biXPelsPerMeter = 0;
    	bmpinfo.biYPelsPerMeter = 0;
    	bmpinfo.biClrUsed = 0;
    	bmpinfo.biClrImportant = 0;
    
    	bmpdata.write((char*)&bmpfile, sizeof(bmpfile));
    	bmpdata.write((char*)&bmpfile, sizeof(bmpinfo));
    
    	RGBQUAD bmp; //Image Data
    	bmp.rgbBlue=0;
    	bmp.rgbGreen=0;
    	bmp.rgbRed=255;
    	bmp.rgbReserved=0;
    
    	if(bmpinfo.biBitCount == 24) //fill image
    	{
    		long *pixel = new long[bmpinfo.biHeight * bmpinfo.biWidth];
    			for (unsigned i = 0; i < bmpinfo.biHeight * bmpinfo.biWidth; ++i)
    			 pixel[i] = 255;
    		bmpdata.write((char*)pixel, bmpinfo.biHeight * bmpinfo.biWidth * sizeof(long));
    		delete[] pixel; 
    	}
    
    	bmpdata.close();
    	return 1;
    }
    

    Ich weiß auch gerade wirklich nicht wo der Fehler sein soll 😕



  • Falls es Leute interessiert wie man letztendlich ein Bitmap erstellt der schau sich bitte folgenden Code von mir an 🙂

    // Bitmap.cpp : Defines the entry point for the console application.
    //
    #pragma once
    
    #include "stdafx.h"
    #include <windows.h>
    #include <fstream>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    void wait (){
        std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
        std::cin.get();
    }
    void success(){
    	cout << "Bitmap created successfully " <<
    		"\t" << __DATE__ << "\t" << __TIME__ << 
    		"\nOpen Bitmap..." << endl;
    }
    void fail(){
    	cout << "Creation aborted" << endl;
    }
    int _tmain(int argc, _TCHAR* argv[]){
    
    	int i,j;
    
        ofstream bmpdata("BITMAP.bmp", ios::out|ios::binary); //begin stream
    
        if (!bmpdata) fail();
    
        BITMAPINFOHEADER bmpinfo; //Infoheader Data
        bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
        bmpinfo.biWidth = 256;
        bmpinfo.biHeight = 256;
        bmpinfo.biPlanes = 1;
        bmpinfo.biBitCount = 24;                                                           
        bmpinfo.biCompression = BI_RGB;
        bmpinfo.biSizeImage = 0;
        bmpinfo.biXPelsPerMeter = 0;
        bmpinfo.biYPelsPerMeter = 0;
        bmpinfo.biClrUsed = 0;
    
        bmpinfo.biClrImportant = 0;	BITMAPFILEHEADER bmpfile;   //Fileheader Data
    	bmpfile.bfType = 'MB';
    	bmpfile.bfSize = (bmpinfo.biWidth * bmpinfo.biHeight * (bmpinfo.biBitCount / 8)) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //aggregate - bmpfile
    	bmpfile.bfReserved1 = 0;
    	bmpfile.bfReserved2 = 0;
    	bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
    	bmpdata.write((char*)&bmpfile, sizeof(bmpfile));	//do not change the order
    	bmpdata.write((char*)&bmpinfo, sizeof(bmpinfo));
    
    	RGBQUAD bmp;		//define color
    	bmp.rgbBlue = 255;
    	bmp.rgbGreen = 0;
    	bmp.rgbRed = 255;
    
    	if(bmpinfo.biBitCount == 24){ //fill image pixel by pixel
    		for (i=0; i < bmpinfo.biHeight ; i++){
    			for (j=0; j < bmpinfo.biWidth; j++){
    				bmpdata.write((char*)&bmp, 3);           
    			}
    		}
    	}
    	else{		//exception
    		fail();
    		cout << "biBitCount dissimilar > sould be " << bmpinfo.biBitCount << endl;
    		wait();
    	return 0;
    	}
    
    	bmpdata.close();	//stream end, bmp created
    
    	success();
    	system("BITMAP.bmp");
    	wait();
    	return 1;
    }
    

    Paar Fehler haben sich bei mir eingeschlichen gehabt. Man muss beachten das zuerst der Fileheader und dann erst der Infoheader beschrieben wird. sizeof(bmp) sollte 3 und nicht 4 sein. Sonst kriegt man nen schönen Streifen, weil er den Reserved Wert auch als Farbwert übernimmt. Der bfType muss MB sein und nicht BM...

    dann sollte eigentlich alles klappen.



  • das Paint von w2k kann es nur mit "BM" öffnen.
    Bei der Vorschau im Explorer funktioniert es auch mit "MB".



  • Hi,

    ich versuche das Beispiel von 0_saya_0 zu verstehen.
    Woher kommt das char*-Feld? Wo wurde es deklariert?

    Beste Grüße



  • das ist kein feld, das ist ein cast nach char*, weil write
    http://www.cplusplus.com/reference/iostream/ostream/write/
    nen char* erwartet.



  • Ok, Danke!

    Und wozu dienen die Laufvariablen i und j, wenn sie nicht in

    bmpdata.write((char*)&bmp, 3);
    

    vorkommen?

    Verstehe ich das richtig, werden jedesmal an "write" die drei Farbintensitäten übergeben und deshalb ist der zweite Wert drei?

    Wie kann man dann jedem Pixel eine eigne Farbe zuweisen? (http://www.c-plusplus.net/forum/290425)

    Vielen Dank im Voraus für eure Hilfe!!!
    Gruß



  • Und wozu dienen die Laufvariablen i und j, wenn sie nicht in

    bmpdata.write((char*)&bmp, 3);
    

    vorkommen?

    das sind bloß zählvariable.
    es wird bmpinfo.biHeight*bmpinfo.biWidth mal der gleiche rgb-wert von je 3 byte in die datei geschrieben.
    du kannst statt der zwei for-schleifen auch eine nehmen,

    for (int n=0; n < bmpinfo.biHeight*bmpinfo.biWidth; n++)
    	        bmpdata.write((char*)&bmp, 3);
    

    die dasselbe resultat liefert.

    Verstehe ich das richtig, werden jedesmal an "write" die drei Farbintensitäten übergeben und deshalb ist der zweite Wert drei?

    so ist es. hier besteht ein pixel aus je drei bytes und es wird jeder pixel einzeln in die datei geschrieben.

    Wie kann man dann jedem Pixel eine eigne Farbe zuweisen?

    indem du jedem pixel eine struktur vom typ RGBQUAD spendierst
    und den membern die farben zuweist.
    einfacher ist es hier mit direkten farbwerten ( 0x00bbggrr ) zu arbeiten, als mit strukturen.

    i.d.r reserviert man ein array von pixeln, das die bitmap als tabelle mit spalten und zeilen repräsentiert und adressiert jedes pixel mit x/y koordinaten.
    jede zeile muss durch 4 teilbar sein, damit gafikprogramme die bitmap lesen können.



  • Danke,

    und wie kann ich aus einem 24-bit Bitmap ein 4-bit Bitmap machen?
    Soweit ich weis brauche ich dafür einen Farbtabelle, wie sieht so etwas aus?

    Gruß



  • jeder 24bit pixel wird in einen 4bit pixel umgerechnet, dabei können farbinformationen verloren gehen.
    es gibt haufenweise seiten im web, wo das bitmap-format erklärt wird, u.a. hier
    http://de.wikipedia.org/wiki/Windows_Bitmap#Farbtabelle

    da findest du auch wertvolle infos über die farbtabelle

    1, 4 oder 8 bpp:
    Die Daten jedes Pixels bestehen aus einem 0-basierten Index auf den Eintrag in der Farbtabelle.

    Jeder Eintrag der Farbtabelle ist 4 Byte groß und enthält jeweils ein Byte für den Blau-, Grün- und Rotanteil, sowie ein auf 0 gesetztes Byte (in dieser Reihenfolge!).


Log in to reply