Bitmap einlesen und Pixmap_Portable ausgeben erfolgt Ausgabe gespiegelt an der y-Achse



  • Hallo Leute,
    ich habe hier ein C++ - Programm geschrieben, das eine Bitmap-Datei ausliest, auf Fehler überprüft und zu Testzwecken als Portable_Pixmap-Datei ausgibt. Die Padding Probleme habe ich schon gelöst, jedoch gibt das Programm das erzeugte Bild an der y-Achse gespiegelt wieder aus. Leider habe ich keine Ahnung warum das so ist, kann mir auch nicht vorstellen, woran das liegt.

    Hier mal das Programm
    Header:

    /*
     * Bitmap.h
     *
     *  Created on: 18.11.2011
     *      Author: heiko
     */
    
    typedef struct{
    	unsigned short fileType;
    	unsigned int fileSize;
    	unsigned short reserved1,reserved2;
    	unsigned int offset;
    } Header;
    
    typedef struct{
    	unsigned int infoheaderSize;
    	int width, height;
    	unsigned short numberOfPlanes;
    	unsigned short bitsPerPixel;
    	unsigned int compression;
    	unsigned int imageSize;
    	int xresolutionPerMeter, yresolutionPerMeter;
    	unsigned int numberOfColours;
    	unsigned int importantColours;
    }Infoheader;
    
    typedef struct{
    	unsigned char blueValue;
    	unsigned char greenValue;
    	unsigned char redValue;
    	unsigned char rgbReserved;
    }RgbQuad;
    

    Source-Datei:

    /*
     * Bitmap.cpp
     *
     *  Created on: 18.11.2011
     *      Author: heiko
     */
    
    // Probleme beim Übersetzen über die Shell -> Seitenlange Fehlermeldung
    // Die Ausgabe der Bilder erfolgt korrekt, jedoch gespiegelt an der y-Achse
    
    #include "Bitmap.h"
    #include <fstream>
    #include <iostream>
    #include <ostream>
    //#include <stdio.h>
    //#include <stdlib.h>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    int main(int argc, char * argv[]){
    	ifstream bmpInput;
    	bmpInput.open(argv[1], ifstream::in);
    	if(!bmpInput){
    			cerr << "could not open file" << endl;
    			bmpInput.close();
    	}
    	bool padding = false;
    	unsigned int posGetPointer = 0;
    
    	//Header einlesen
    	Header header;
    	bmpInput.read((char*)(&header.fileType), sizeof(header.fileType));
    	if(bmpInput.eof()) return 0;
    	posGetPointer += sizeof(header.fileType);
    	bmpInput.seekg(posGetPointer);
    
    //testen ob richtiges Format
    	unsigned short M = 'M';
    	unsigned short B = 'B';
    	unsigned short MB = (M<<8) + B;
    	if(header.fileType != MB){
    		cerr << "Falsches Format von FileType" << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&header.fileSize), sizeof(header.fileSize));
    	posGetPointer += sizeof(header.fileSize);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&header.reserved1), sizeof(header.reserved1));
    	posGetPointer += sizeof(header.reserved1);
    	bmpInput.seekg(posGetPointer);
    
    //testen ob reserved1 != 0
    	if(header.reserved1 != 0){
    		cerr << "reserved1 != 0" << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&header.reserved2), sizeof(header.reserved2));
    	posGetPointer += sizeof(header.reserved2);
    	bmpInput.seekg(posGetPointer);
    
    //testen ob reserved2 != 0
    	if(header.reserved2 != 0){
    		cerr << "reserved2 != 0" << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&header.offset), sizeof(header.offset));
    	posGetPointer += sizeof(header.offset);
    	bmpInput.seekg(posGetPointer);
    
    //Infoheader einlesen
    	Infoheader infheader;
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.infoheaderSize), sizeof(infheader.infoheaderSize));
    	posGetPointer += sizeof(infheader.infoheaderSize);
    	bmpInput.seekg(posGetPointer);
    
    //testen ob infoheaderSize != 40
    	if(infheader.infoheaderSize != 40){
    		cerr << "InfoheaderSize != 40" << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.width), sizeof(infheader.width));
    	posGetPointer += sizeof(infheader.width);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.height), sizeof(infheader.height));
    	posGetPointer += sizeof(infheader.height);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.numberOfPlanes), sizeof(infheader.numberOfPlanes));
    	posGetPointer += sizeof(infheader.numberOfPlanes);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.bitsPerPixel), sizeof(infheader.bitsPerPixel));
    	posGetPointer += sizeof(infheader.bitsPerPixel);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.compression), sizeof(infheader.compression));
    	posGetPointer += sizeof(infheader.compression);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.imageSize), sizeof(infheader.imageSize));
    	posGetPointer += sizeof(infheader.imageSize);
    	bmpInput.seekg(posGetPointer);
    
    //testen ob filesize = imageSize + offset
    	if(header.fileSize > header.offset + infheader.imageSize){
    		cerr << "fileSize zu groß. Erwartet: " << header.offset + infheader.imageSize
    				<< ", tatsächlich: " << header.fileSize << endl;
    		bmpInput.close();
    		return 0;
    	}
    	else if(header.fileSize < header.offset + infheader.imageSize){
    		cerr << "fileSize zu klein. Erwartet: " << header.offset + infheader.imageSize
    				<< ", tatsächlich: " << header.fileSize << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.xresolutionPerMeter), sizeof(infheader.xresolutionPerMeter));
    	posGetPointer += sizeof(infheader.xresolutionPerMeter);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.yresolutionPerMeter), sizeof(infheader.yresolutionPerMeter));
    	posGetPointer += sizeof(infheader.yresolutionPerMeter);
    	bmpInput.seekg(posGetPointer);
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.numberOfColours), sizeof(infheader.numberOfColours));
    	posGetPointer += sizeof(infheader.numberOfColours);
    	bmpInput.seekg(posGetPointer);
    
    //offset-Größe testen
    	if(header.offset > 54 + infheader.numberOfColours*4){
    		cerr << "Offset zu groß. Erwartet:" << 54 + infheader.numberOfColours*4
    			<< ", tatsächlich: " << header.offset << endl;
    		bmpInput.close();
    		return 0;
    	}
    	else if(header.offset < 54 + infheader.numberOfColours*4){
    		cerr << "Offset zu klein. Erwartet:" << 54 + infheader.numberOfColours*4
    		<< ", tatsächlich: " << header.offset << endl;
    		bmpInput.close();
    		return 0;
    	}
    
    	if(bmpInput.eof()) return 0;
    	bmpInput.read((char*)(&infheader.importantColours), sizeof(infheader.importantColours));
    	posGetPointer += sizeof(infheader.importantColours);
    	bmpInput.seekg(posGetPointer);
    
    	RgbQuad colours[16];
    
    	for(int i = 0; i < 16; ++i){
    
    		if(bmpInput.eof()) return 0;
    		bmpInput.read((char*)(&colours[i].blueValue), sizeof(char));
    		posGetPointer += sizeof(char);
    		bmpInput.seekg(posGetPointer);
    
    		if(bmpInput.eof()) return 0;
    		bmpInput.read((char*)(&colours[i].greenValue), sizeof(char));
    		posGetPointer += sizeof(char);
    		bmpInput.seekg(posGetPointer);
    
    		if(bmpInput.eof()) return 0;
    		bmpInput.read((char*)(&colours[i].redValue), sizeof(char));
    		posGetPointer += sizeof(char);
    		bmpInput.seekg(posGetPointer);
    
    		if(bmpInput.eof()) return 0;
    		bmpInput.read((char*)(&colours[i].rgbReserved), sizeof(char));
    		posGetPointer += sizeof(char);
    		bmpInput.seekg(posGetPointer);
    	}
    
    //festellen ob padding notwendig ist
    	if((infheader.width/2 + infheader.width%2)%4 != 0)
    			padding = true;
    
    //Pixel-Daten werden im Vektor imageData gespeichert 
    	std::vector<unsigned char> imageData;
    	unsigned char imgDat;
    
    //Anzahl der zu entfernenden Leerbytes festlegen	
    	int toRemove = 0;
    	if(padding){
    		toRemove = 4 - (infheader.width/2 + infheader.width%2)%4;
    	}
    	for(int height = 0; height < infheader.height; ++height){
    		for(int width = 0; width < (infheader.width/2 + infheader.width%2 + toRemove); ++width){
    			if(bmpInput.eof()){
    				cerr << "es konnten nicht alle images gelesen werden" << endl;
    				return 0;
    			}
    			bmpInput.read((char*)(&imgDat), sizeof(char));
    			imageData.push_back(imgDat);
    			posGetPointer += sizeof(char);
    			bmpInput.seekg(posGetPointer);
    		}
    		if(padding){
    			for(int i = 0; i < toRemove; ++i){
    				imageData.pop_back();
    			}
    		}
    	}
    
    	cout << "statistische Daten: " << endl << "Dateigröße: " << header.fileSize << " Byte" << endl
    			<< "Auflösung: " << infheader.width << "x" << infheader.height << " in Megapixel: "
    			<< (double)(infheader.width*infheader.height)/1000000 << endl << "Padding benötigt: ";
    	if(padding)
    		cout << "ja" << endl;
    	else
    		cout << "nein" << endl;
    
    	bmpInput.close();
    
    //Ausgaben in Portable_Pixmap-Datei (.ppm)
    	fstream bmpOutput("./smiley.ppm", fstream::in|fstream::out|fstream::trunc);
    	if(!bmpOutput){
    			cerr << "could not open file" << endl;
    			bmpOutput.close();
    	}
    
    	bool oddWidth;
    	if(infheader.width%2 != 0) oddWidth = true;
    	bmpOutput << "P6"<<  " " << infheader.width << " "<< infheader.height<< " " << 255;
    
    	for(unsigned int i = imageData.size() - 1; i >= 0; --i){
    		unsigned char upper, lower;
    		upper = ((imageData[i])& 0xf0)>>4;
    		lower = (imageData[i])& 0x0f;
    		if(oddWidth && (i % (infheader.width/2 + 1) == 0)){
    			bmpOutput << (unsigned char) colours[upper].blueValue
    					<< (unsigned char)colours[upper].redValue
    					<< (unsigned char)colours[upper].greenValue;
    		}
    		else{
    			bmpOutput << (unsigned char) colours[lower].blueValue
    				<< (unsigned char)colours[lower].redValue
    				<< (unsigned char)colours[lower].greenValue
    				<< (unsigned char)colours[upper].blueValue
    				<< (unsigned char)colours[upper].redValue
    				<< (unsigned char)colours[upper].greenValue;
    		}
    	}
    
    	bmpOutput.close();
    }
    

    Weiteres Problem:
    das Programm lässt sich nur in Eclipse kompilieren und ausführen. Wenn ich versuche das Programm auf der Shell mit gcc zu übersetzen, gibt der Compiler eine Seitenlange Fehlermeldung aus

    Danke schon mal für eure Hilfe


Anmelden zum Antworten