H
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