Danke für die klasse Zusammenarbeit!



  • Guten Tag!

    Also ich hab mal noch rumprobiert und hab mit Hilfe deiner Stichworte die Malloc-Geschichte auf jeden Fall verstanden! 💡

    So weit wir jetzt sind:

    #include<stdio.h>
    #include<windows.h>

    int main(void)

    {

    int*Speicher;

    HBITMAP hBmp =
    (HBITMAP)LoadImage(NULL,"C:\\Desktop\\Spiegeln.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

    if(!hBmp)
    { printf("Fehler beim Ladevorgang\n");
    }
    else
    {printf("Laden war erfolgreich\n");
    }

    Speicher=malloc(sizeof(int));

    GetBitmapBits(HBITMAP hBmp,LONG cSize, void * lpvBits);

    free(Speicher);

    return 0;

    }

    Also das Laden der Bmp funktioniert ganz gut!

    Fragen:

    1. Muss ich bei sizeof(int) nicht irgendwie vorher sagen, dass des Bild eben 100 Pixel lang und 200 Pixel breit ist? Dazu habe ich leider nichts gefunden. Aber so gibt malloc ja nur für "int" Speicher frei. Oder war das richtig?

    Da du nicht in den Farbkanälen rumpfuschen willst, kann das ruhig direkt ein int-Puffer sein.

    2. GetBitmapBits Fehlermeldung:
    Nicht genügend Argumente für Aufruf
    Die Funktion habe ich aber vom Aufbau her auch noch nicht begriffen!

    Grüße aus dem sonnigen Stuttgart



  • Bitte benutze in Zukunft cpp-Tags, um deinen Code schön leserlich mit Syntaxhighlighting darzustellen. Dazu umschließt du deinen Code mit [cpp] und [/cpp].

    Stuttgart schrieb:

    Speicher=malloc(sizeof(int));
    

    Hier reservierst du nur 4 Bytes (unter einem 32-Bit-OS). malloc nimmt einfach einen Zahlenwert, der die Anzahl an zu allozierenden Bytes darstellt. Wenn du also für jeden Pixel 4 Bytes anfordern willst, dann musst du einfach sizeof(int)*Breite*Höhe übergeben ("Speicher=malloc(sizeof(int)*width*height)").

    Ich finde es sogar besser, wenn man hier 4 statt sizeof(int) übergibt (vielleicht in Form einer Präprozessor-Konstante oder in einem weiter fortgeschrittenen Programm als zuweisbaren Member einer Struktur oder Klasse). Vielleicht ändert sich sizeof(int) ja unter einem anderen OS/Compiler, du willst aber weiterhin 32 Bit pro Pixel verarbeiten. Aber egal...

    Übrigens gut, dass du auch ans free gedacht hast. Sonst hättest du direkt ein Speicherleck...

    Stuttgart schrieb:

    2. GetBitmapBits Fehlermeldung:
    Nicht genügend Argumente für Aufruf
    Die Funktion habe ich aber vom Aufbau her auch noch nicht begriffen!

    Du übergibst ja hier auch nix, das ist einfach der Kopf der Funktion aus der Hilfe kopiert. Also...

    1. Parameter: Dein Bitmap-Handle, dass von LoadImage kommt.
    2. Parameter: Anzahl zu kopierender Bytes (also hier wieder Breite*Höhe*4, eben soviel Speicher wie du angefordert hast und im Bitmap an Daten vorhanden ist).
    3. Parameter: void-Pointer auf den Puffer, in den die Daten reinkopiert werden sollen. Speicher ist ein int-Pointer, der muss gecastet werden. Das wäre wohl "(void*)Speicher".

    Wenn das ganze Vorgeplänkel dann passt, bist du kurz davor, endlich mal im Bildspeicher rumpfuschen zu können... 🙂



  • Super vielen Dank für die schnelle Antwort!

    Mein Problem ist noch, dass ich nicht weiß wie ich die Höhe und Breite des Bildes auslesen kann? Gibt es da sowas in C wie getimagesize() ?

    Grüße



  • Stuttgart schrieb:

    GetBitmapBits(HBITMAP hBmp,Speicher, void * Speicher);
    

    Nein! Du musst einen void-Pointer auf Speicher übergeben (also den int-Pointer Speicher nach void* casten). "void * Speicher" ist aber eine Deklaration! Die hat da nix verloren. Ich habe ja bereits geschrieben, dass das so aussehen muss:

    (void*)Speicher
    

    Ok, da ich sehe, dass das noch ewig dauern wird, bis du dich mal mit dem eigentlichen Problem (Spiegeln) beschäftigen kannst (da deine C-Kenntnisse noch recht bescheiden sind), habe ich mal schnell was zusammengebastelt. Dabei habe ich selbst mal wieder gemerkt, was für ein unheiliges Gefrickel Bitmaps mit WinAPI-Funktionen doch sind. Ich bin froh, dass das mit OpenCV+IPL (und vor allem dem vorzüglichen, firmeninternen Wrapper dafür) alles irgendwie besser geht. Der Code ist teilweise aus dem Internet, da ich für's Speichern (dafür sind die 2 großen Funktionen) spontan keinen Ansatz hatte. Überhaupt ist alles ziemlich gefrickelt, aber das soll dich nicht weiter stören.

    Hier wird ein Bild C:\Spiegeln.bmp geladen. Dann wird eine blaue, vertikale Linie gezeichnet, um dir zu zeigen, wie du auf den Bildspeicher zugreifen musst. Da setzt du deine Spiegelung ein (ist mit einem dicken Kommentar markiert, unten in der main-Funktion). Am Ende wird das Bild in C:\Spiegeln_Ergebnis.bmp gespeichert. Die Dateinamen kannst du natürlich anpassen, das sind String-Literale, die am Anfang der main-Funktion deklariert werden.

    So, dann spiegel mal, was das Zeug hält! 😉

    Übrigens ist mathematisch das Rotieren ja viel interessanter. Vielleicht kannst du dich ja im Anschluss auch mal daran versuchen, wenn dann noch Interesse besteht. Das Grundgerüst dazu hast du ja jetzt.

    #include <stdio.h>
    #include <windows.h>
    
    void errhandler(char *szErrString) {
    	printf("ERROR: %s",szErrString);
    	exit(9);
    }
    
    PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
    { 
    	BITMAP bmp; 
    	PBITMAPINFO pbmi; 
    	WORD    cClrBits; 
    
    	// Retrieve the bitmap color format, width, and height. 
    	if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
    		errhandler("GetObject"); 
    
    	// Convert the color format to a count of 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; 
    
    	// Allocate memory for the BITMAPINFO structure. (This structure 
    	// contains a BITMAPINFOHEADER structure and an array of RGBQUAD 
    	// data structures.) 
    
    	if (cClrBits != 24) 
    		pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
    		sizeof(BITMAPINFOHEADER) + 
    		sizeof(RGBQUAD) * (1<< cClrBits)); 
    
    	// There is no RGBQUAD array for the 24-bit-per-pixel format. 
    
    	else 
    		pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
    		sizeof(BITMAPINFOHEADER)); 
    
    	// Initialize the fields in the BITMAPINFO structure. 
    
    	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); 
    
    	// If the bitmap is not compressed, set the BI_RGB flag. 
    	pbmi->bmiHeader.biCompression = BI_RGB; 
    
    	// Compute the number of bytes in the array of color 
    	// indices and store the result in biSizeImage. 
    	// For Windows NT, the width must be DWORD aligned unless 
    	// the bitmap is RLE compressed. This example shows this. 
    	// For Windows 95/98/Me, the width must be WORD aligned unless the 
    	// bitmap is RLE compressed.
    	pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
    		* pbmi->bmiHeader.biHeight; 
    	// Set biClrImportant to 0, indicating that all of the 
    	// device colors are important. 
    	pbmi->bmiHeader.biClrImportant = 0; 
    	return pbmi; 
    } 
    
    void 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;              // memory pointer 
    	DWORD dwTotal;              // total count of bytes 
    	DWORD cb;                   // incremental count of bytes 
    	BYTE *hp;                   // byte pointer 
    	DWORD dwTmp; 
    
    	pbih = (PBITMAPINFOHEADER) pbi; 
    	lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
    
    	if (!lpBits) 
    		errhandler("GlobalAlloc"); 
    
    	// Retrieve the color table (RGBQUAD array) and the bits 
    	// (array of palette indices) from the DIB. 
    	if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
    		DIB_RGB_COLORS)) 
    	{
    		errhandler("GetDIBits"); 
    	}
    
    	// Create the .BMP file. 
    	hf = CreateFile(pszFile, 
    		GENERIC_READ | GENERIC_WRITE, 
    		(DWORD) 0, 
    		NULL, 
    		CREATE_ALWAYS, 
    		FILE_ATTRIBUTE_NORMAL, 
    		(HANDLE) NULL); 
    	if (hf == INVALID_HANDLE_VALUE) 
    		errhandler("CreateFile"); 
    	hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M" 
    	// Compute the size of the entire file. 
    	hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
    		pbih->biSize + pbih->biClrUsed 
    		* sizeof(RGBQUAD) + pbih->biSizeImage); 
    	hdr.bfReserved1 = 0; 
    	hdr.bfReserved2 = 0; 
    
    	// Compute the offset to the array of color indices. 
    	hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
    		pbih->biSize + pbih->biClrUsed 
    		* sizeof (RGBQUAD); 
    
    	// Copy the BITMAPFILEHEADER into the .BMP file. 
    	if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
    		(LPDWORD) &dwTmp,  NULL)) 
    	{
    		errhandler("WriteFile"); 
    	}
    
    	// Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
    	if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
    		+ pbih->biClrUsed * sizeof (RGBQUAD), 
    		(LPDWORD) &dwTmp, ( NULL)))
    		errhandler("WriteFile"); 
    
    	// Copy the array of color indices into the .BMP file. 
    	dwTotal = cb = pbih->biSizeImage; 
    	hp = lpBits; 
    	if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
    		errhandler("WriteFile"); 
    
    	// Close the .BMP file. 
    	if (!CloseHandle(hf)) 
    		errhandler("CloseHandle"); 
    
    	// Free memory. 
    	GlobalFree((HGLOBAL)lpBits);
    }
    
    int main() 
    {
    	int*Speicher; 
    	unsigned int sizeInBytes;
    	BITMAP tagbmp;
    	int y;
    	BITMAPINFO *pbi;
    	char *sSourceImagePath="C:\\Spiegeln.bmp";
    	char *sDestinationImagePath="C:\\Spiegeln_Ergebnis.bmp";
    
    	HBITMAP hBmp=(HBITMAP)LoadImage(NULL,sSourceImagePath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); 
    	if(!hBmp) { 
    		printf("Fehler beim Ladevorgang\n"); 
    		return 1;
    	} 
    	else {
    		printf("Laden war erfolgreich\n"); 
    	}
    
    	GetObject(hBmp,sizeof(BITMAP),&tagbmp);
    
    	sizeInBytes=tagbmp.bmWidthBytes*tagbmp.bmHeight;
    
    	Speicher=malloc(sizeInBytes);
    	if(!Speicher) {
    		printf("malloc fehlgeschlagen! Kein Speicher mehr frei?\n");
    		return 2;
    	}
    
    	GetBitmapBits(hBmp,sizeInBytes,(void*)Speicher); 
    
    	//!!!
    	//Hier zwischen GetBitmapBits und SetBitmapBits kannst du deine Spiegelung vornehmen.
    	//Ich habe mal exemplarisch einfach eine blaue Linie von Position 10,0 bis 10,[Höhe des Bildes] gezeichnet (die folgende for-Schleife).
    	//Daran siehst du, dass es auch funktioniert. ;)
    	//Zugriff auf einen Pixel x,y funktioniert mit Index y*tagbmp.bmWidth+x.
    	//!!!
    
    	for(y=0;y<tagbmp.bmHeight;y++) {
    		Speicher[y*tagbmp.bmWidth+10]=0x000000ff;
    	}
    
    	SetBitmapBits(hBmp,sizeInBytes,(void*)Speicher);
    
    	pbi=CreateBitmapInfoStruct(NULL,hBmp);
    	CreateBMPFile(NULL,sDestinationImagePath,pbi,hBmp,GetDC(0));
    
    	free(Speicher);
    	DeleteObject(hBmp);
    	printf("\nFertig! Ergebnisbild: %s\n",sDestinationImagePath);
    	getchar();
    }
    


  • Wow Matze, Ich danke dir von ganzem Herzen! Was das für eine Arbeit gewesen sein muss 😮 !

    Und ja ... ich gebe es zu: Mit meiner C-Kenntniss kann ich nicht wirklich prahlen.

    Also ich bin grad am Durchgehen des Quellcodes. Und was ich noch nicht ganz verstanden habe ist, wie ich dann wirklich ein Bild "spiegel". Ich versteh wie die blaue Linie zu stande kommt aber wie kann ich dann wirklich jedes einzelne Pixel spiegeln? Im Internet hab ich leider nix weiteres gefunden.

    (Das mit (void*) Speicher hab ich übrigens jetzt verstanden)

    Herzliche Grüße



  • Stuttgart schrieb:

    Wow Matze, Ich danke dir von ganzem Herzen! Was das für eine Arbeit gewesen sein muss 😮 !

    Geht so, wir reden von vielleicht 20 Minuten. Ich hab meine Ziele für heute locker erreicht (und überschritten), daher war das vertretbar. 😉

    Stuttgart schrieb:

    Also ich bin grad am Durchgehen des Quellcodes. Und was ich noch nicht ganz verstanden habe ist, wie ich dann wirklich ein Bild "spiegel". Ich versteh wie die blaue Linie zu stande kommt aber wie kann ich dann wirklich jedes einzelne Pixel spiegeln? Im Internet hab ich leider nix weiteres gefunden.

    Na ja, du musst einfach auf der Horizontalen Pixel 0 und Pixel [breite-1] tauschen. Dazu musst du natürlich eine temporäre Variable deklarieren, die einen der Werte speichert. Dann gehts weiter mit Pixel 1 und Pixel [breite-2] usw... Für die vertikale Spiegelung (so du sie denn vorhast) musst du das natürlich entsprechend umdrehen.

    Pseudeocode:

    for(x=0;x<breite/2;x++) {  //Breite sollte durch 2 teilbar sein
      temp=zeile[x];
      zeile[x]=zeile[breite-x-1];
      zeile[breite-x-1]=temp;
    }
    


  • Was würde ich ohne dich nur machen! Und wenn ich das schon hör

    Geht so, wir reden von vielleicht 20 Minuten
    

    ! Da kann ich nur "Oha" sagen 😉

    Also ich mach mal auf die Suche wie man temporäre Variablen deklarieren kann.



  • Stuttgart schrieb:

    Also ich mach mal auf die Suche wie man temporäre Variablen deklarieren kann.

    😃

    Na wie normale Variablen auch! Das temporär bezieht sich nur auf die Anwendung, da gibts kein Schlüsselwort 'temporary' oder so. 😉

    int MyTempVar;
    


  • Ja sorry matze 😃

    Also ich hab das mal probiert:

    int MyTempVar; //Temporäre Variable
    int x;         //Auswahl
    
    for(x=0;x<width/2;x++) { //kennt er die "Variable" width oder muss man die  noch  auslesen?
    
      MyTempVar=zeile[x];    //Zeile[x] ist ja praktisch die Nummer! Muss ich da ein Array anlegen?
      zeile[x]=zeile[width-x-1];
      zeile[width-x-1]=MyTempVar;
    }
    

    Noch mal Danke für deine Bemühungen.
    Ich kenn das aus anderen Erfahrungen, dass das ganz schön stressig sein kann wenn jemand es gar nicht versteht :p .

    Also bis dann



  • Stuttgart schrieb:

    for(x=0;x<width/2;x++) { //kennt er die "Variable" width oder muss man die  noch  auslesen?
    }
    

    Na die Breite (so wie die Höhe auch) ist schon bekannt. Guck mal genauer in den Code.

    Stuttgart schrieb:

    for(x=0;x<width/2;x++) { //kennt er die "Variable" width oder muss man die  noch  auslesen?
      
      MyTempVar=zeile[x];    //Zeile[x] ist ja praktisch die Nummer! Muss ich da ein Array anlegen?
    }
    

    Wie Array?? Du möchtest 2 Pixel tauschen. Sobald du den Wert von Pixel 2 Pixrl 1 zugewiesen hast, ist der Wert von Pixel 1 nicht mehr da. Also speicherst du diesen zwischen und weist ihn dann Pixel 2 zu. Vielleicht war meine Namensgebung nicht optimal...

    Ich denke, dass du den letzten Rest selbst schaffen müsstest. Du siehst im Code, wie du bestimmte Pixel addressieren (und ihnen einen Wert zuweisen) kannst, also solltest du sie auch tauschen können. Probier einfach mal ein bisschen rum.



  • Hi,

    ich hab jetzt den Ablauf verstanden! Man muss das auf die Variable übertragen weil sonst die Pixel "verloren" gehen würden. Man lagert sie praktisch zwischen.

    Ich hab es jetzt noch mal selber probiert und stell mir das so vor:

    }
    
        GetBitmapBits(hBmp,sizeInBytes,(void*)Speicher);
    
    for(x=0;x<width/2;x++) { 
      int x;
      int MyTempVar;
    
      Speicher[y*tagbmp.bmWidth+x]=Zeile;                 //Ausgangszeile
      Speicher[y*tagbmp.bmWidth+(width-x-1)]=MyTempVar;  //Spiegelzeile
    
    Zeile=Speicher[y*tagbmp.bmWidth+(width-x-1)];      //Zeile wird auf Spiegelzeile gebracht
      MyTempVar=Speicher[y*tagbmp.bmWidth+x];             //Zeile wird Spiegelzeile zugewiesen
    
    }
    

    Fehlermeldungen die kommen:

    x nicht deklarierter Bezeichner
    width nicht deklarierter Bezeichner
    Zeile nicht deklarierter Bezeichner

    Vielleicht bin auch komplett auf dem Holzweg. ⚠ Wäre ja nicht das
    erste Mal.

    Grüße



  • Du solltest dringend mal ein C-Grundlagen-Tutorial 'reinziehen. Du kannst eine Variable nicht benutzen, wenn du sie nicht vorher deklariert hast. Sonst existiert sie einfach nicht. Hier versuchst du aber, die Variablen x, width und Zeile zu benutzeen. Die gibt es nicht! Bei x machst du es ganz kurios. Du willst sie verwenden (im Kopf der for-Schleife), deklarierst sie aber erst in der Schleife, also darunter...

    Eine Variable deklariert man so:

    int x;  //es gibt jetzt eine Variable x
    
    x=5;  //x wird der Wert 5 zugewiesen, x ist jetzt 5!
    

    Zur Variable x: die brauchst du, da du zwei verschachtelte Schleifen benutzen musst. Eine, die die Zeile 👍 repräsentiert, und eine für die Spalte (x). y habe ich schon deklariert (am Anfang der main), auf die gleiche Art erzeugst du jetzt eine Variable x.

    Zur Variable width: die brauchst du nicht erzeugen. Du hast die Breite des Bildes doch schon! Die steht in "tagbmp.bmWidth".

    Zur Variable Zeile: Keine Ahnung, was du damit willst. Meinen Pseudocode von vorhin solltest du nicht so wörtlich nehmen. 😉

    Der Ablauf muss so sein:

    for(y=0;y<tagbmp.bmHeight;y++) {  //gehe durch jede Zeile des Bildes
      for(x=0;x<tagbmp.bmWidth/2;x++) {  //gehe in der aktuellen Zeile durch jeden Pixel bis zur Hälfte des Bildes (denn an dem Punkt hast du bereits alle Pixel der Zeile getauscht
        //das hier sollst du schon selbst machen (wenigstens ein bisschen Lerneffekt muss sein
        //- linken Pixel in eine temporäre int-Variable speichern
        //- den Wert vom rechten Pixel in den linken speichern
        //- den Wert der temporären Variable in den rechten Pixel speichern
      }
    }
    

    Nochmal: in diesen Schleifen kannst du einen Pixel addressieren mit Speicher[y*tagbmp.bmWidth+x]. Diese Formel musst du anwenden, da Speicher kein zweidimensionales Array ist (wie es bei einem 2D-Bild eigentlich logischer wäre), sondern ein eindimensionales (eine einfache Aneinanderreihung der Pixel). Um zur zweiten Zeile und dem dritten Pixel zu hüpfen, musst du zur Nullposition einmal die Breite einer Zeile addieren (1*tagbmp.bmWidth) und eben die Spalte 3 (+3) => Speicher[1*tagbmp.bmWidth+3]. Klar?



  • Abend Matze,

    ja das mit Grundkurs hast du Recht. Das Problem ist, dass wir in der Schule jemanden haben der es einfach zu gut drauf hat! (Fast so wie du, nur du erklärst super) Natürlich sind nicht immer die Lehrer schuld aber sie tragen dazu bei :p

    Um deinen Nerven den Rest zu geben hab ich mir mal Gedanken gemacht!

    Ich hab bei main nochmal die Variablen die wir zur Spiegelung brauchen aufgeführt

    int y;
    	int x;
    	int Temp;
    

    Und das eigentliche Spiegeln hab ich mir jetzt mal so überlegt (so wie du gesagt hast)

    for(y=0;y<tagbmp.bmHeight;y++) {													  //gehe durch jede Zeile des Bildes
        for(x=0;x<tagbmp.bmWidth/2;x++) {													 //gehe in der aktuellen Zeile durch jeden Pixel bis zur Hälfte des Bildes (denn an dem Punkt hast du bereits alle Pixel der Zeile getauscht
        Speicher[y*tagbmp.bmWidth+x]=Temp;													//- linken Pixel in eine temporäre int-Variable speichern
        Speicher[y*tagbmp.bmWidth+x]=Speicher[y*tagbmp.bmWidth-x-1];                //- den Wert vom rechten Pixel in den linken speichern
    	Temp=Speicher[y*tagbmp.bmWidth-x-1];									  //- den Wert der temporären Variable in den rechten Pixel speichern
    

    Wenn ich das Programm ausführe, kommt erstmal "Laden erfolgreich" und dann "Wegen eines schwerwiegenden Fehlers..musste das Programm beendet werden".

    Na ja vielleicht findest du ja wenigstens eine richtige Zeile.

    Grüße und schönen Abend noch



  • Ist ja schonmal ein Fortschritt, aber...

    Stuttgart schrieb:

    Speicher[y*tagbmp.bmWidth+x]=Temp;
    

    Du vertauschst immer die Zuweisung. Hier würdest du den Wert von Temp (und Temp wurde ja zu dem Zeitpunkt noch gar nichts zugewiesen) in den Pixel x,y speichern. Das muss ja genau umgekehrt sein.

    Temp=Speicher[y*tagbmp.bmWidth+x];  //so wird der Wert des Pixels x,y in Temp gespeichert
    

    Ich denke aber nicht, dass hier das Problem mit dem Absturz liegt. Zeig bitte mal deine komplette main-Funktion.



  • Ach maaaan!

    Das weiß ich doch. Ich bin so hohl! Das hatten wir schon!

    Klar muss Temp=... heißen. Sorry

    Hab jetzt nochmal unseren gesamten Quellcode hier:

    #include <stdio.h>
    #include <windows.h>
    
    void errhandler(char *szErrString) {
        printf("ERROR: %s",szErrString);
        exit(9);
    }
    
    PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
    {
        BITMAP bmp;
        PBITMAPINFO pbmi;
        WORD    cClrBits;
    
        // Retrieve the bitmap color format, width, and height.
        if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
            errhandler("GetObject");
    
        // Convert the color format to a count of 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;
    
        // Allocate memory for the BITMAPINFO structure. (This structure
        // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
        // data structures.)
    
        if (cClrBits != 24)
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
            sizeof(BITMAPINFOHEADER) +
            sizeof(RGBQUAD) * (1<< cClrBits));
    
        // There is no RGBQUAD array for the 24-bit-per-pixel format.
    
        else
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
            sizeof(BITMAPINFOHEADER));
    
        // Initialize the fields in the BITMAPINFO structure.
    
        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);
    
        // If the bitmap is not compressed, set the BI_RGB flag.
        pbmi->bmiHeader.biCompression = BI_RGB;
    
        // Compute the number of bytes in the array of color
        // indices and store the result in biSizeImage.
        // For Windows NT, the width must be DWORD aligned unless
        // the bitmap is RLE compressed. This example shows this.
        // For Windows 95/98/Me, the width must be WORD aligned unless the
        // bitmap is RLE compressed.
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
            * pbmi->bmiHeader.biHeight;
        // Set biClrImportant to 0, indicating that all of the
        // device colors are important.
        pbmi->bmiHeader.biClrImportant = 0;
        return pbmi;
    }
    
    void 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;              // memory pointer
        DWORD dwTotal;              // total count of bytes
        DWORD cb;                   // incremental count of bytes
        BYTE *hp;                   // byte pointer
        DWORD dwTmp;
    
        pbih = (PBITMAPINFOHEADER) pbi;
        lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
    
        if (!lpBits)
            errhandler("GlobalAlloc");
    
        // Retrieve the color table (RGBQUAD array) and the bits
        // (array of palette indices) from the DIB.
        if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
            DIB_RGB_COLORS))
        {
            errhandler("GetDIBits");
        }
    
        // Create the .BMP file.
        hf = CreateFile(pszFile,
            GENERIC_READ | GENERIC_WRITE,
            (DWORD) 0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            (HANDLE) NULL);
        if (hf == INVALID_HANDLE_VALUE)
            errhandler("CreateFile");
        hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"
        // Compute the size of the entire file.
        hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
            pbih->biSize + pbih->biClrUsed
            * sizeof(RGBQUAD) + pbih->biSizeImage);
        hdr.bfReserved1 = 0;
        hdr.bfReserved2 = 0;
    
        // Compute the offset to the array of color indices.
        hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
            pbih->biSize + pbih->biClrUsed
            * sizeof (RGBQUAD);
    
        // Copy the BITMAPFILEHEADER into the .BMP file.
        if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
            (LPDWORD) &dwTmp,  NULL))
        {
            errhandler("WriteFile");
        }
    
        // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
        if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
            + pbih->biClrUsed * sizeof (RGBQUAD),
            (LPDWORD) &dwTmp, ( NULL)))
            errhandler("WriteFile");
    
        // Copy the array of color indices into the .BMP file.
        dwTotal = cb = pbih->biSizeImage;
        hp = lpBits;
        if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
            errhandler("WriteFile");
    
        // Close the .BMP file.
        if (!CloseHandle(hf))
            errhandler("CloseHandle");
    
        // Free memory.
        GlobalFree((HGLOBAL)lpBits);
    }
    
    int main()
    {
        int*Speicher;
        unsigned int sizeInBytes;
        BITMAP tagbmp;
    	int y;
    	int x;
    	int Temp;
        BITMAPINFO *pbi;
        char *sSourceImagePath="C:\\Spiegeln.bmp";
        char *sDestinationImagePath="C:\\Spiegeln_Ergebnis.bmp";
    
        HBITMAP hBmp=(HBITMAP)LoadImage(NULL,sSourceImagePath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
        if(!hBmp) {
            printf("Fehler beim Ladevorgang\n");
            return 1;
        }
        else {
            printf("Laden war erfolgreich\n");
        }
    
        GetObject(hBmp,sizeof(BITMAP),&tagbmp);
    
        sizeInBytes=tagbmp.bmWidthBytes*tagbmp.bmHeight;
    
        Speicher=malloc(sizeInBytes);
        if(!Speicher) {
            printf("malloc fehlgeschlagen! Kein Speicher mehr frei?\n");
            return 2;
        }
    
        GetBitmapBits(hBmp,sizeInBytes,(void*)Speicher);
    
        for(y=0;y<tagbmp.bmHeight;y++) {													  //gehe durch jede Zeile des Bildes
        for(x=0;x<tagbmp.bmWidth/2;x++) {													 //gehe in der aktuellen Zeile durch jeden Pixel bis zur Hälfte des Bildes (denn an dem Punkt hast du bereits alle Pixel der Zeile getauscht
        Temp=Speicher[y*tagbmp.bmWidth+x];													//- linken Pixel in eine temporäre int-Variable speichern
        Speicher[y*tagbmp.bmWidth+x]=Speicher[y*tagbmp.bmWidth-x-1];                //- den Wert vom rechten Pixel in den linken speichern
    	Speicher[y*tagbmp.bmWidth-x-1]=Temp;									  //- den Wert der temporären Variable in den rechten Pixel speichern
      }
    }
    
        SetBitmapBits(hBmp,sizeInBytes,(void*)Speicher);
    
        pbi=CreateBitmapInfoStruct(NULL,hBmp);
        CreateBMPFile(NULL,sDestinationImagePath,pbi,hBmp,GetDC(0));
    
        free(Speicher);
        DeleteObject(hBmp);
        printf("\nFertig! Ergebnisbild: %s\n",sDestinationImagePath);
        getchar();
    }
    

    Passt der Teil mit Spiegelung jetzt einigermaßen?
    Grüße



  • Sieht gut aus, denke ich. Abgesehen vielleicht von der Einrückung, aber na ja. Klappt es denn oder kriegst du noch einen Absturz? Ich kann's grad ncht ausprobieren.



  • Abend!

    Ich bekomm leider immer noch eine Fehlermeldung. Es wird alles schön gestartet (Visual Studio gibt mir keine Fehlermeldung) und dann gibts die Fehlermeldung!

    Grüße



  • Was denn, in der Fehlermeldung steht bloss "Fehlermeldung!" drin!?!
    So eine Frechheit.
    Normalerweise schreiben Entwickler was sinnvolles in so eine Fehlermeldung rein, womit man auch was anfangen kann. z.B. wenn man in einem Forum Hilfe sucht.
    So eine Frechheit!!!einself



  • Programm.exe hat ein Problem festgestellt und muss beendet werden.

    <?xml version="1.0" encoding="UTF-16"?>
    <DATABASE>
    <EXE NAME="Programm.exe" FILTER="GRABMI_FILTER_PRIVACY">
    <MATCHING_FILE NAME="Programm.exe" SIZE="30720" CHECKSUM="0xC5343328" MODULE_TYPE="WIN32" PE_CHECKSUM="0x10E5E" LINKER_VERSION="0x0" LINK_DATE="05/29/2009 21:19:13" UPTO_LINK_DATE="05/29/2009 21:19:13" />
    </EXE>
    <EXE NAME="kernel32.dll" FILTER="GRABMI_FILTER_THISFILEONLY">
    <MATCHING_FILE NAME="kernel32.dll" SIZE="1063424" CHECKSUM="0x2E7379C2" BIN_FILE_VERSION="5.1.2600.5512" BIN_PRODUCT_VERSION="5.1.2600.5512" PRODUCT_VERSION="5.1.2600.5512" FILE_DESCRIPTION="Client-DLL für Windows NT-Basis-API" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Betriebssystem Microsoft® Windows®" FILE_VERSION="5.1.2600.5512 (xpsp.080413-2111)" ORIGINAL_FILENAME="kernel32" INTERNAL_NAME="kernel32" LEGAL_COPYRIGHT="© Microsoft Corporation. Alle Rechte vorbehalten." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x106523" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.5512" UPTO_BIN_PRODUCT_VERSION="5.1.2600.5512" LINK_DATE="04/14/2008 02:21:52" UPTO_LINK_DATE="04/14/2008 02:21:52" VER_LANGUAGE="Deutsch (Deutschland) [0x407]" />
    </EXE>
    </DATABASE>

    Das ist der Fehlerbericht den Windows gibt.
    Meines Wissens ist Kernel32.dll für Vergabe im RAM und soweiter zuständig? Dann gibts da irgendwie Probleme aber wie kann man das lösen?

    Grüße



  • Setz doch mal einen Haltepunkt, geh schrittweise durch das Programm und überprüfe den ganzen Ablauf Stück für Stück.

    P.S.: Du erstellst doch hoffentlich die Debug-Version deines Projekts, ja (nicht Release)? Bei der Größe würde ich fast schätzen, dass es die Release-Version ist. Das ist fürs Debuggen natürlich schlecht, also stell es um, falls ich Recht habe...


Anmelden zum Antworten