Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Bei meinem Grafik-Projekt weiß ich auch nicht mehr weiter...

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
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
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
28.07.2006, 18:51 Uhr
stephanw
localhorst


Durch absoluten Zufall habe ich beim Überfliegen Deines Codes das hier gefunden:

C++:
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);         // <--- hier !
}




Dazu ein paar Tipps:
1.) Poste nicht soviel Quelltext. Wer soll sich das alles durchlesen ?
2.) Grenze den Fehler ein: Du hast eine Image-, eine Pixel-Klasse und etwas zum TGA-Laden. Außerdem sind Dir TGA-Daten offenbar nicht so geläufig, sonst müsstet Du nicht nachsehen (mir auch nicht, ist kein Manko ;-) ). Und Du hast die Testbilder mit einem Grafik-Programm gemalt ? Das sind fünf -in Worten: FÜNF- Unbekannte. Wie willst Du deren Integration fehlerfrei kriegen, wenn jede Einzelkomponente das Problem darstellen kann ?

Darum schreibst Du einen Test für Deine Pixelklasse, einen für die Image-Klasse. Dabei füllst Du jeden Pixel oder jede Zeile oder irgendwie so mit einer bestimmten Farbe. Anschließend vergleichst Du die Werte. Stimmt was nicht, liegt der Fehler beim Setzen oder Lesen der Pixel.
So kann man fortfahren mit der Lade-Routine und Du kannst auch die Grafik-Proggi-Daten testen, indem Du ein TGA erstellst, dass oben grün und unten rot ist. Dasselbe machst Du im Programm mit einem durch ein Testbild. Laden, vergleichen, gucken.

Stichwort für Google "Unit-Test".

Edit: noch kurz: Du schreibst zigmal "y*width+x" . Das ist Duplizierung von Wissen, nämlich dem Wissen um die Index-Berechnung. Mach eine Funktion draus, dann hast Du dieses Wissen nur an einer einzigen Stelle.

Grüße
--
Reden ist Schweigen und Silber ist Gold.

Dieser Post wurde am 28.07.2006 um 18:57 Uhr von stephanw editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.07.2006, 17:42 Uhr
(un)wissender
Niveauwart


Und natürlich fehlt der Destruktor von Image, der matrix löscht.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.07.2006, 19:30 Uhr
Yadgar



High!


Zitat von (un)wissender:
Und natürlich fehlt der Destruktor von Image, der matrix löscht.


Die Möglichkeit, dass eventuell über kurz oder lang mangels Destruktor der Speicher zumüllt und es deswegen zu diesen seltsamen Ergebnissen (und auch Abstürzen!) kommt habe ich auch schon in Erwägung gezogen... aber ich war davon ausgegangen, dass es wie bei Konstruktoren auch implizite Destruktoren gibt und ich mir deswegen keine Gedanken darum zu machen bräuchte...

Zum Thema "Big Endian vs. Little Endian" (siehe Thread "Deltatester gesucht"): das kann in diesem speziellen Fall keine Rolle spielen, denn ich suche nach Pixeln mit der Farbe rgb <0, 0, 0> - und das Bitmuster für "0" dürfte in Big Endian wie in Little Endian gleich aussehen, nämlich 00000000...

Bis bald im Khyberspace!

Yadgar

Now playing: Disruption in World Communications (Synergy)
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
30.07.2006, 19:44 Uhr
(un)wissender
Niveauwart


Das ist C++! Wo du new schreibst muss ein delete folgen. Immer!
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
30.07.2006, 21:08 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


auch in C muss auf ein malloc ein free folgen, einen garbage-collector wie in java gibt es nicht. D.h in deinem Fall muss in den Destruktor eben das delete von der matrix, der implizite destruktor wird zwar aufgerufen, nur macht der gar nix
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
30.07.2006, 21:27 Uhr
Yadgar



High!


Zitat von (un)wissender:
Das ist C++! Wo du new schreibst muss ein delete folgen. Immer!


Auch, wenn nach dem Einlesen der Matrix und dem Ausführen der Suchfunktion (cCount) das Programm sowieso zu Ende ist?

Bis bald im Khyberspace!

Yadgar

Now playing: Mouettes (Vangelis)
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
30.07.2006, 22:09 Uhr
Yadgar



High!


Zitat von FloSoft:
D.h in deinem Fall muss in den Destruktor eben das delete von der matrix, der implizite destruktor wird zwar aufgerufen, nur macht der gar nix


Das habe ich dann auch gemacht, also


C++:
Image::~Image()
{
   delete[] matrix;
}



...trotzdem änderte sich am Programmverhalten nichts - erster Versuch Absturz, zweiter Versuch unsinniger Wert! Fehlt noch was beim Destruktor? Fehlermeldungen gab es jedenfalls keine...

Bis bald im Khyberspace!

Yadgar

Now playing: Lotus (Ashra)
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
30.07.2006, 23:10 Uhr
(un)wissender
Niveauwart


Der Destruktor ist für die Abstürze sicherlich nicht verantwortlich.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
30.07.2006, 23:16 Uhr
kronos
Quotenfisch
(Operator)


Du solltest dir stephanws Vorschlag, Teile deines Codes Stück für Stück durchzutesten zu Herzen nehmen, sonst wird aus deiner Programmierkarriere wirklich nichts. Wir beantworten dir gerne Verständnisfragen, aber Debuggen musst du selbst, dass ist ein wichtiger Teil der Arbeit.
Erstell Testdateien mit wenigen Pixeln, lass dir an verschiedenen Stellen deine Variablen ausgeben, grenze ein, ab wo die Werte nicht mehr stimmen, schau dir den Code an und überleg dir was nicht stimmt. Wenn du eine bestimmte Zeile hast, die nicht macht was sie soll, kannst du gerne posten, aber doch nicht das komplette Programm!!
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: