000
28.07.2006, 15:39 Uhr
Yadgar
|
High!
...also, ist es denn normal, wenn man ständig brutal gegen die Grenzen seiner Fähigkeiten knallt - oder bin ich einfach völlig unbegabt zum Programmieren und sollte besser Treppenhäuser putzen oder bei McDonald's die Toiletten schrubben? Kann es denn sein, dass ich mir alle Naselang von Anderen Hilfe holen muss, weil offensichtlich mein eigenes bisschen Grips nicht ausreicht?
Das untenstehende Programm soll folgendes tun: eine TGA-Grafik (unkomprimiert, 24bit, Typ 2, siehe Dokumentation (http://www.gamers.org/dEngine/quake3/TGA.txt)) aus einer Grafikdatei einlesen und dann als Array von Pixeln innerhalb eines Objektes "Image" organisieren. Ich habe eine Methode von Image programmiert, die die Anzahl der Pixel einer Farbe ermittelt... und weil es bei Tests mit drei kleinen TGA-Files zu merkwürdigen Abweichungen kam, hatte ich zusätzlich noch Ausgaberoutinen 1. für die aus der Datei eingelesenen Pixeldaten und 2. für die Pixeldaten im Pixel-Array (also im Objekt Image) geschrieben. Die Daten in der Datei waren einwandfrei, bei denen in Pixel-Array kam es hingegen zu ganz seltsamen Verschiebungen, teilweise tauchten dort Werte auf, die gar nicht aus dem Datenbereich des TGAs stammen konnten (ich habe die Testdateien bewusst einfach gestaltet, mit maximal drei verschiedenen Farben, siehe auch mein Progger-Blog), sondern wohl dem Anhang hinter dem Datenbereich zuzurechnen sind.
Ich vermutete, dass der Fehler in der Funktion Image.setPixel und/oder bei den drei Farb-Settern in der Klasse Pixel lag, konnte dort aber beim besten Willen nicht Falsches finden!
Hier ist der Code:
C++: |
// YIP - Yadgar's Image Processor
#include <iostream> #include <fstream> using namespace std;
bool weiter(void);
class Pixel { friend class Image; private: unsigned char b; // da Farbwerte bei normaler 24bit-Grafik nur unsigned char g; // zwischen 0 und 255 liegen können, unsigned char r; // genügt hier ein 1 Byte langer Typ // Private Methoden zur Angabe von Farbwerten, wegen ihrer Kürze inline unsigned char blue(void) { return b; } unsigned char green(void) { return g; } unsigned char red(void) { return r; } // Private Methoden zum Setzen von Farbwerten, ebenfalls inline void setBlue(unsigned char b) { this->b=b; } void setGreen(unsigned char g) { this->g=g; } void setRed(unsigned char r) { this->r=r; } /* public: Pixel (unsigned char, unsigned char, unsigned char); // Konstruktor */ };
/* Pixel::Pixel (unsigned char bl, unsigned char gr, unsigned char rd) { b=bl; g=gr; r=rd; } */
class Image { private: unsigned short width; unsigned short height; Pixel* matrix; public: Image (unsigned short, unsigned short); // Konstruktor unsigned long cCount (unsigned char, unsigned char, unsigned char); // zählt Pixel der angegegebenen Farbe, wichtig: Farbwert- // reihenfolge ist Standard, also r, g, b! unsigned short getWidth() { return width; } unsigned short getHeight() { return height; } void setPixel(unsigned short, unsigned short, unsigned char, unsigned char, unsigned char); void pixelDisplay(void); // listet die Farbwerte der einzelnen Pixel auf };
Image::Image (unsigned short w, unsigned short h) { matrix = new Pixel[h*w]; width=w; height=h; }
unsigned long Image::cCount (unsigned char r, unsigned char g, unsigned char b) { unsigned long n=0; unsigned long x; unsigned long y; for (y=0; y<height; y++) { for (x=0; x<width; x++) { if ( (matrix[y*width+x].blue()==b) && (matrix[y*width+x].green()==g) && (matrix[y*width+x].red()==r) ) n++; // cout << (short)matrix[y*width+x].red() << ", " << (int)matrix[y*width+x].green() << ", " << (int)matrix[y*width+x].blue() << endl; } } return n; }
void Image::setPixel(unsigned short x, unsigned short y, unsigned char b, unsigned char g, unsigned char r) { matrix[y*width+x].setBlue(b); matrix[y*width+x].setGreen(g); matrix[y+width+x].setRed(r); } void Image::pixelDisplay(void) { unsigned short pn; bool flag; for (short i=0; i<height; i++) { for(short j=0; j<width; j++) { pn=i*width+j; cout << pn << "\t\t" << "<" << (unsigned short)matrix[pn].red() << ", " << (unsigned short)matrix[pn].green() << ", " << (unsigned short)matrix[pn].blue() << ">" << endl; if (pn>0 && !(pn%20)) flag=weiter(); if (!flag) goto ex; } } ex: ; } bool weiter(void) // global, Hilfsfunktion für die Ausgabe von Pixeldaten { char antwort; do { cout << "Ausgabe fortsetzen? "; cin >> antwort; if (antwort != 'n' && antwort != 'j') cout << "Bitte nur j oder n eingeben!" << endl; } while (antwort != 'n' && antwort != 'j'); if (antwort == 'j') return true; else return false; }
int main() { string name; ifstream input; char ch; unsigned char r, g, b; long int i=0, n, pn; unsigned short int xsize, ysize, x=0, y=0, rd, gr, bl; bool flag;
cout << "Bitte geben Sie den Namen der zu ladenden Grafikdatei ein: "; cin >> name; input.open(name.c_str()); while (input.get(ch) && i<17) { switch(i) { case 12: xsize=ch; break; case 13: xsize+=ch*256; break; case 14: ysize=ch; break; case 15: ysize+=ch*256; break; } i++; } Image picture(xsize, ysize); cout << "\nDas Bild ist " << picture.getWidth() << " Pixel breit und " << picture.getHeight() << " Pixel hoch." << endl; cout << "i = " << i << endl << endl; getchar(); while (input.get(ch)) { if (i >= 17) { n=i-17; pn=n/3; if (n>0 && !(n%3)) x++; if (n>0 && !(n%(xsize*3))) { x=0; y++; } switch(n%3) { case 0: b=ch; break; case 1: g=ch; break; case 2: r=ch; picture.setPixel(x, y, b, g, r); if (flag && pn<xsize*ysize) { cout << pn << "\t\t" << "<" << (unsigned short)r << ", " << (unsigned short)g << ", " << (unsigned short)b << ">" << endl; if (pn>0 && !(pn%20)) { flag=weiter(); } } break; } } i++; } picture.pixelDisplay();
cout << "\nNach welcher Farbe soll gesucht werden? " << endl; cout << "Rotwert: "; cin >> rd; cout << "Gr" << (char)129 << "nwert: "; cin >> gr; cout << "Blauwert: "; cin >> bl;
r=(unsigned char)rd; g=(unsigned char)gr; b=(unsigned char)bl; cout << "Die von ihnen gesuchte Farbe kommt im Bild " << picture.cCount(r, g, b) << " mal vor." << endl;
system("pause"); }
|
Bis bald im Khyberspace!
Yadgar -- Flagmaker - ein Programmier-Blog |