Problem beim Klassenaufbau



  • Hallo,

    ich schreibe zur Zeit an ein Grafikbearbeitungsprogramm und habe ein paar Schwierigkeiten, wie ich die Klassen sinnvoll aufbauen könnte.

    Das Problem ist, dass ich Bitmap Bilder von 1 bis 32 Bits habe.

    Nun habe ich also überlegt für jede Bitstufe eine Klasse zu machen:

    class Bitmap32
    {
    public:
       ctors();
    private:
       m_bilddaten;
    }
    class Bitmap24
    {
    public:
       ctors();
    private:
       m_bilddaten;
    }
    ...
    class Bitmap1
    {
    public:
       ctors();
    private:
       m_bilddaten;
    }
    

    Wenn ich dann später Bilder von einer Bitstufe in die andere umwandeln will, würde ich nun für jede Klasse einen Konstruktor erstellen:

    Bitmap32::Bitmap32(Bitmap24 bitmap)
    Bitmap32::Bitmap32(Bitmap16 bitmap)
    ...
    Bitmap32::Bitmap32(Bitmap1 bitmap)
    

    Dies müsste ich dann ebenfalls für alle anderen Klassen (Bitmap1 bis Bitmap 32) machen. (umständlich!)

    Darüberhinaus habe ich noch eine Oberklasse geplant, die einfach ein Bitmap1 bis Bitmap32 als Membervariable aufnehmen kann.
    Diese Klasse soll dann entsprechende Verarbeitungsroutinen besitzen, die egal um welchen Bitmap Typ es sich handelt, auf das Bitmap-Member angewendet werden kann:

    Class Bild
    {
    public:
       rotate();
       grayscale();
       ...
    private:
       Bitmap1-32 m_bitmap;
       long m_width;
       long m_height;
    }
    

    Irgendwie kommt mir dieses Konzept nicht ganz stimmig vor, fällt da jemanden vielleicht etwas besseres ein?



  • Warum übergibst du nicht die Farbtiefe im Ctor und stellst Konvertierungsmethoden zur Verfügung?



  • Also hier noch mal ein neuer Versuch, dieses Mal alles in einer Klasse:

    #ifndef _BITMAP_H
    #define _BITMAP_H
    typedef std::vector<unsigned char> ImageData
    
    class Bitmap
    {
    public:
    	Bitmap(BitmapType& bitmap);
    	~Bitmap() {}
    
    	ImageData& ConvertTo1();
    	ImageData& ConvertTo4();
    	ImageData& ConvertTo8();
    	ImageData& ConvertTo15();
    	ImageData& ConvertTo16();
    	ImageData& ConvertTo24();
    	ImageData& ConvertTo32();
    private:
    	ImageData m_data;
    	long m_width;
    	long m_height;	
    	long m_bpp;
    }
    
    Bitmap::Bitmap(const Bitmap& bitmap) : m_width(bitmap.m_width), m_height(bitmap.m_height), m_bpp(bitmap.m_bpp), m_data(bitmap.m_data)
    {
    }
    
    ImageData& Bitmap::ConvertTo32()
    {
    	if(m_bpp == 32)
    		return m_data;
    
    	ImageData temp(m_height * m_width * m_bpp);
    
    	switch(m_bpp)
    	{
    		case 1-24:
    			/*CODE*/
    			break;
    	}
    
    	m_bpp = 32;
    
    	return temp;
    }
    
    // Convert24-1 [...]
    

    Daran gefällt mir aber das Switch überhaupt nicht, ginge das nicht auch ohne?



  • wenn man wüsste, was in dem switch steht^^



  • Naja, was soll ich dazu jetzt sagen - die Umwandlungsroutinen halt.

    Eigentlich steht da immer etwas anderes, daher weiß ich nicht so genau, warum das so interessant ist...
    Wenn ich zum Beispiel ein 32 Bit Bitmap habe und mache ConvertTo24().

    ImageData& Bitmap::ConvertTo24()
    {
     ImageData temp(m_height * m_width * 3); // temporäres 24 Bit Image
    
     switch(m_bpp)
     {
      case 24:
       for(long y=0; y<m_height; y++)
       {
        for(long x=0; x<m_width; x++)
        {
           temp[3*(y*m_width+x)]   = m_data[4*(y*m_width+x)];
           temp[3*(y*m_width+x)+1] = m_data[4*(y*m_width+x)+1];
           temp[3*(y*m_width+x)+2] = m_data[4*(y*m_width+x)+2];
           // viertes Byte wird jetzt einfach mal ignoriert.
        }
      case...
     }
    
     m_bpp = 24;
    
     return temp;
    }
    
    void Bitmap::display(char* destBild, long screen_bpp)
    {
     switch(screen_bpp)
     {
       case 24:
          ImageData temp = (ConvertTo24());
          memcpy(&destBild[0], &temp[0], m_width*m_height*3);
          break;
     }
    }
    

    Ich halte das ganze aber nicht für richtig toll.

    Daher kommt auch meine Ursprüngliche Idee, wo man halt für jeden bpp Wert eine eigene Klasse hat Bitmap32, Bitmap24 ... Bitmap1, die dann alle von einer gemeinsamen Oberklasse BitmapType abgeleitet sind:

    class Bitmap
    {
    public:
      Bitmap(bilddaten);
      void display(char* destBild, long screen_bpp);
    private:
      BitmapType* m_pbitmaptype // irgendwie Zeiger auf BitmapType
    };
    
    // Bild kommt rein
    Bitmap::Bitmap(bilddaten)
    {
     m_pbitmaptype = new Bildtype(bilddaten); // m_pbitmaptype Zeiger soll nun auf BildType Zeigen, 
                                              // und ruft automatisch die richtige Klasse Bitmap32..1(bilddaten) auf.
    }
    
    // Bild ausgeben
    void Bitmap::display(char* destBild, long screen_bpp)
    {
     switch(screen_bpp)
     {
       case 24:
          ImageData temp = ConvertTo24(); // es soll automatisch das richtige virtuelle ConverTo() der Klassen Bitmap32-1 aufgerufen werden.
          memcpy(&destBild[0], &temp[0], m_bitmap.m_width * m_bitmap.m_height * 3);
          break;
     }
    }
    
    class BitmapType
    {
    public:
       BitmapType(Bilddaten bilddaten) {switch bilddaten.bpp}
    
       virtual void ConvertTo32();
       virtual void ConvertTo24();
       virtual void ConvertTo1();
    private:
       ZeigerAufBitmap32-1Klasse // keine Ahnung wie...
    };
    
    BitmapType::BitmapType(Bilddaten bilddaten)
    {
     switch(bilddaten.bpp)
     {
       case 32:
         ZeigerAufBitmap32-1Klasse = new Bitmap32(bildaten); break;
       case 24-1... break;
     }
    }
    
    class Bitmap32
    {
    public:
       Bitmap32(bildaten);
       virtual void ConvertTo32();
       virtual void ConvertTo24();
       ...
       virtual void ConvertTo1();
    private:
       ImageData m_data;
    };
    class Bitmap24
    {
       Bitmap24(bildaten);
       virtual void ConvertTo32();
       virtual void ConvertTo24();
       ...
       virtual void ConvertTo1();
    private:
       ImageData m_data;
    };
    ...
    class Bitmap1
    {
       Bitmap1(bildaten);
       virtual void ConvertTo32();
       virtual void ConvertTo24();
       ...
       virtual void ConvertTo1();
    private:
       ImageData m_data;
    };
    

    Die Klasse Bitmap weiß also nie was für eine Art von Bild sie hat, sondern ruft einfach die entsprechende ConvertTo() Funktion auf und den Rest übernimmt im Hintergrund die Klasse BitmapType.

    So etwa sehe mein Vorschlag aus, ich bin aber offen für andere Vorschläge oder Verbesserungen.


Anmelden zum Antworten