Also, die Aufgabe ist, dass man eine Bitmap durch Veränderung der binären-Datei verdoppelt. Das Programm sollte unter Linux in der Konsole laufen, ich habe jedoch aus Faulheit beim Fehlersuchen auf den BCB 2007 zurück gegriffen.
Das Verhalten von diesem Stück Quellcode verblüfft mich aber leider ziemlich. Die Werte in dem pos-Array werden nämlich kleiner, was schließlich bedeuten würde, dass der Dateizeiger nach vorne geschoben wird.
Desweiteren wird einer der beiden fwrite-Befehle nicht wirklich ausgeführt, weil die Werte sich immer nur um 3 Byte ändern.
Unter Linux erhalte ich noch einen Segmantation fault, aber dass ist jetzt nicht so relevant, auch wenn es interessant ist, dass ich unter LInux einen Speicherzugriffsfehler bekomme, der unter Windows nicht auftaucht.
Vielen Dank für eure Hilfe,
benediktibk
Vollständig:
Code:
//Verdoppeln der Bildgroesse
bool CDoppelBitmap::Verdoppeln()
{ unsigned char temp_byte [3];
int anzahl_byte=0;
long alte_pos;
long pos [2];
int bearbeitete_elemente;
//nach Farbtiefe unterscheiden
switch(quelle->bit_pro_pixel)
{ case 8: anzahl_byte=1; break;
case 24: anzahl_byte=3; break;
default: return false;
}
//Header und Farbdefinitionen kopieren
*ziel=*quelle;
fseek(quelle->datei,quelle->offset,SEEK_SET);
fseek(ziel->datei,ziel->offset,SEEK_SET);
//Bild verdoppeln (in x- und y-Richtung)
for (int i=0; i<quelle->hoehe; ++i)
{ alte_pos=ftell(ziel->datei);
//In der Zeile die Pixel verdoppeln
for (int j=0; j<quelle->breite; ++j)
{ pos[0]=ftell(ziel->datei);
bearbeitete_elemente=fread(temp_byte,sizeof(char),anzahl_byte,quelle->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
}
//Quell-Dateizeiger auf den Anfang der Zeile zurücksetzen
fseek(quelle->datei,alte_pos,SEEK_SET);
//Zeile ein zweites Mal schreiben
for (int j=0; j<quelle->breite; ++j)
{ pos[1]=ftell(ziel->datei);
bearbeitete_elemente=fread(temp_byte,sizeof(char),anzahl_byte,quelle->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
}
}
//Header anpassen
ziel->breite*=2;
ziel->hoehe*=2;
ziel->datei_laenge+=ziel->datei_laenge-ziel->offset;
ziel->groesse_pixeldaten*=4;
return true;
}
Desweiteren wird einer der beiden fwrite-Befehle nicht wirklich ausgeführt, weil die Werte sich immer nur um 3 Byte ändern.
Unter Linux erhalte ich noch einen Segmantation fault, aber dass ist jetzt nicht so relevant, auch wenn es interessant ist, dass ich unter LInux einen Speicherzugriffsfehler bekomme, der unter Windows nicht auftaucht.
Vielen Dank für eure Hilfe,
benediktibk
Vollständig:
Code:
#ifndef BITMAP
#define BITMAP
class CBitmap
{ public:
int datei_laenge;
int reserviert;
int offset;
int header_groesse;
int breite;
int hoehe;
short anzahl_bildebenen;
short bit_pro_pixel;
int kompression;
int groesse_pixeldaten;
int xdpm;
int ydpm;
int anzahl_farben_genutzt;
int anzahl_farben_wichtig;
FILE *datei;
CBitmap(char verzeichnis [], char modus []);
~CBitmap();
CBitmap(CBitmap const& rechte_seite);
};
class CDoppelBitmap
{ private:
CBitmap *quelle;
CBitmap *ziel;
bool fehler;
public:
CDoppelBitmap(char ziel_verzeichnis [],char quell_verzeichnis []);
~CDoppelBitmap();
bool Verdoppeln();
bool get_fehler();
};
//Konstruktor von CBitmap
CBitmap::CBitmap(char verzeichnis [], char modus [])
{ datei=NULL;
char temp_byte [2];
//Oeffnen der Datei
datei=fopen(verzeichnis,modus);
//Fehler beim Oeffnen abfangen
if (datei==NULL)
return;
rewind(datei);
//char Ueberspringen
fread(temp_byte,sizeof(char),2,datei);
//Einlesen des Headers
fread(&datei_laenge,sizeof(int),1,datei);
fread(&reserviert,sizeof(int),1,datei);
fread(&offset,sizeof(int),1,datei);
fread(&header_groesse,sizeof(int),1,datei);
fread(&breite,sizeof(int),1,datei);
fread(&hoehe,sizeof(int),1,datei);
fread(&anzahl_bildebenen,sizeof(short),1,datei);
fread(&bit_pro_pixel,sizeof(short),1,datei);
fread(&kompression,sizeof(int),1,datei);
fread(&groesse_pixeldaten,sizeof(int),1,datei);
fread(&xdpm,sizeof(int),1,datei);
fread(&ydpm,sizeof(int),1,datei);
fread(&anzahl_farben_genutzt,sizeof(int),1,datei);
fread(&anzahl_farben_wichtig,sizeof(int),1,datei);
rewind(datei);
}
//Destruktor von CBitmap
CBitmap::~CBitmap()
{ char temp_byte[]="BM";
rewind(datei);
//BM-String schreiben
fwrite(temp_byte,sizeof(char),2,datei);
//Schreiben des Headers
fwrite(&datei_laenge,sizeof(int),1,datei);
fwrite(&reserviert,sizeof(int),1,datei);
fwrite(&offset,sizeof(int),1,datei);
fwrite(&header_groesse,sizeof(int),1,datei);
fwrite(&breite,sizeof(int),1,datei);
fwrite(&hoehe,sizeof(int),1,datei);
fwrite(&anzahl_bildebenen,sizeof(short),1,datei);
fwrite(&bit_pro_pixel,sizeof(short),1,datei);
fwrite(&kompression,sizeof(int),1,datei);
fwrite(&groesse_pixeldaten,sizeof(int),1,datei);
fwrite(&xdpm,sizeof(int),1,datei);
fwrite(&ydpm,sizeof(int),1,datei);
fwrite(&anzahl_farben_genutzt,sizeof(int),1,datei);
fwrite(&anzahl_farben_wichtig,sizeof(int),1,datei);
fflush(datei);
fclose(datei);
}
//Kopierkonstruktor von CBitmap
CBitmap::CBitmap(CBitmap const& rechte_seite)
{ char temp_byte;
//Header kopieren
datei_laenge=rechte_seite.datei_laenge;
reserviert=rechte_seite.reserviert;
offset=rechte_seite.offset;
header_groesse=rechte_seite.header_groesse;
breite=rechte_seite.breite;
hoehe=rechte_seite.hoehe;
anzahl_bildebenen=rechte_seite.anzahl_bildebenen;
bit_pro_pixel=rechte_seite.bit_pro_pixel;
kompression=rechte_seite.kompression;
groesse_pixeldaten=rechte_seite.groesse_pixeldaten;
xdpm=rechte_seite.xdpm;
ydpm=rechte_seite.ydpm;
anzahl_farben_genutzt=rechte_seite.anzahl_farben_genutzt;
anzahl_farben_wichtig=rechte_seite.anzahl_farben_wichtig;
//Farbdefinitionen kopieren
fseek(datei,13L*sizeof(int),SEEK_SET);
fseek(rechte_seite.datei,13L*sizeof(int),SEEK_SET);
while(ftell(rechte_seite.datei)<offset)
{ fread(&temp_byte,sizeof(char),1,rechte_seite.datei);
fwrite(&temp_byte,sizeof(char),1,datei);
}
}
//Konstruktor von CDoppelBitmap
CDoppelBitmap::CDoppelBitmap(char ziel_verzeichnis [], char quell_verzeichnis [])
{ fehler=false;
quelle=new CBitmap(quell_verzeichnis,"rb");
ziel=new CBitmap(ziel_verzeichnis,"wb");
//Fehler beim Oeffnen abfangen
if (quelle->datei==NULL || ziel->datei==NULL)
{ fehler=true;
return;
}
}
//Destruktor von CDoppelBitmap
CDoppelBitmap::~CDoppelBitmap()
{ delete quelle;
delete ziel;
}
//get_fehler von CDoppelBitmap
bool CDoppelBitmap::get_fehler()
{ return fehler;
}
//Verdoppeln der Bildgroesse
bool CDoppelBitmap::Verdoppeln()
{ unsigned char temp_byte [3];
int anzahl_byte=0;
long alte_pos;
long pos [2];
int bearbeitete_elemente;
//nach Farbtiefe unterscheiden
switch(quelle->bit_pro_pixel)
{ case 8: anzahl_byte=1; break;
case 24: anzahl_byte=3; break;
default: return false;
}
//Header und Farbdefinitionen kopieren
*ziel=*quelle;
fseek(quelle->datei,quelle->offset,SEEK_SET);
fseek(ziel->datei,ziel->offset,SEEK_SET);
//Bild verdoppeln (in x- und y-Richtung)
for (int i=0; i<quelle->hoehe; ++i)
{ alte_pos=ftell(ziel->datei);
//In der Zeile die Pixel verdoppeln
for (int j=0; j<quelle->breite; ++j)
{ pos[0]=ftell(ziel->datei);
bearbeitete_elemente=fread(temp_byte,sizeof(char),anzahl_byte,quelle->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
}
//Quell-Dateizeiger auf den Anfang der Zeile zurücksetzen
fseek(quelle->datei,alte_pos,SEEK_SET);
//Zeile ein zweites Mal schreiben
for (int j=0; j<quelle->breite; ++j)
{ pos[1]=ftell(ziel->datei);
bearbeitete_elemente=fread(temp_byte,sizeof(char),anzahl_byte,quelle->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
bearbeitete_elemente=fwrite(temp_byte,sizeof(char),anzahl_byte,ziel->datei);
}
}
//Header anpassen
ziel->breite*=2;
ziel->hoehe*=2;
ziel->datei_laenge+=ziel->datei_laenge-ziel->offset;
ziel->groesse_pixeldaten*=4;
return true;
}
#endif
Code:
#include <stdio.h>
#include <iostream.h>
//#include <conio.h>
#include "bitmap_klasse.h"
int main()
{ CDoppelBitmap *bitmap;
bitmap=new CDoppelBitmap ("bildx4.bmp","bild.bmp");
if (!bitmap->get_fehler())
bitmap->Verdoppeln();
else
printf("Dateien konnten nicht geöffnet werden");
//getch();
delete bitmap;
return 0;
}