Templates automatisieren

Hallo Leute,

Diesmal hab ich folgendes Problem:
Ich hab eine 8-Bit S/W-Bitmap(Pattern) und will aus einer Orginal-Bitmap
(8,16,24, oder 32 BitsperPixel (BPP)) alle Pixel, die in Pattern gesetzt sind in eine neue BM kopieren.
Gibt es nun irgendeine Möglichkeit mittels Casting od Templates eine allgemeingültige Funktion zu schreiben die den entsprechenden Typen nur aufgrund der Information BPP erkennt.

also in etwa so:

template void f(T dst,T org,LPBYTE pat,int size)
{ for (int i=0;ibpp);
// das hier will ich aber verallgemeinern
 if (Dst-\>bpp==24) f((LPTRIPLE)Dst-\>Data,(LPTRIPLE)Org-\>Data,Data,Area);
 else if (Dst-\>bpp==32) f((LPQUAD)Dst-\>Data,(LPQUAD)Org-\>Data,Data,Area);
 else if (Dst-\>bpp==16) f((LPWORD)Dst-\>Data,(LPWORD)Org-\>Data,Data,Area);
 else f((LPBYTE)Dst-\>Data,(LPBYTE)Org-\>Data,Data,Area);
// in so etwas wie: 
// BPP\>T;
// f((T)Dst-\>Data,Data,(T)Org-\>Data); 
 return Dst;
}

Dieses Problem taucht in meiner Klasse an diversen Stellen auf. Ich habe ein und die selben Daten, muß sie aber je nach BPP unterschiedlich interpretieren.
Ich würde das gerne eleganter formulieren, bzw. möchte generell wissen, wie ich eine solche Problematik angehen kann. (Wenn es überhaupt geht)

Danke schon mal für eure Hilfe
Ciao,
husky

Hallo Husky,

Gibt es nun irgendeine Möglichkeit mittels Casting od
Templates eine allgemeingültige Funktion zu schreiben die den
entsprechenden Typen nur aufgrund der Information BPP erkennt.

also in etwa so:

template void f(T dst,T org,LPBYTE pat,int
size)
{ for (int i=0;i

Was spricht gegen

 template 
 void f(T1 dst,T1 org, T2 pat, int count)
{ 
 for (int i=0;iIch fürchte, ich habe Dein Problem nicht richtig 
verstanden. Du willst also template-Instantiierung 
anhand von 2 oder mehr verschiedenen Pixeldatentypen haben?

Grüße

CMБ

Was spricht gegen

template
void f(T1 dst,T1 org, T2 pat, int count)
{
for (int i=0;iIch fürchte, ich habe Dein Problem nicht richtig
verstanden. Du willst also template-Instantiierung
anhand von 2 oder mehr verschiedenen Pixeldatentypen haben?

Hallo,
Genau!.
Wenn ich es so wie du meinst mache, habe ich ja immer noch das selbe Problem. Das Template f() wird zur Compile-Zeit übersetzt und kann nur reagieren, wenn ich den entsprechenden Typ übergebe. Dafür muss ich dann wieder die Abfrage machen, da der Typ der Orginalbitmap ja immer LPBYTE ist und nur entsprechend interpretiert (bzw. gecastet) wird.
Gruß
husky

Hallo Husky,

Ich fürchte, ich habe Dein Problem nicht richtig
verstanden. Du willst also template-Instantiierung
anhand von 2 oder mehr verschiedenen Pixeldatentypen haben?

Wenn ich es so wie du meinst mache, habe ich ja immer noch das
selbe Problem. Das Template f() wird zur Compile-Zeit
übersetzt und kann nur reagieren, wenn ich den entsprechenden
Typ übergebe. Dafür muss ich dann wieder die Abfrage machen,
da der Typ der Orginalbitmap ja immer LPBYTE ist und nur
entsprechend interpretiert (bzw. gecastet) wird.

Jaaa, das kannst Du mit den Templates imho so
nicht lösen, da es keine „Laufzeit-Spezialisierung“
von Templates gibt. Ich finde, es geht aber schöner
mit einem anderen Ansatz. Du „erzwingst“ eine „compile-
time“-Instantiierung, trägst diese Funktionen in eine
Tabelle ein und rufst sie per Index auf, den Du ja
aus Deinem Element „bpp“ entnehmen kannst (bpp/8).

Das sähe dann für Dein Snippet „grob“ so aus:

 // (1) Template für alle Faelle daklarieren 
 template
 void f\_proc(LPBYTE dst, LPBYTE org, LPBYTE pat, int n\_pix)
 { 
 T d=T(dst), o=T(org), p=T(pat);
 for (int i=0; i, // Index 1, bpp=8
 f\_proc, // Index 2, bpp=16
 f\_proc, // Index 3, bpp=24
 f\_proc // Index 3, bpp=32
 };

Dein Quelltext vereinfacht sich dadurch
auf den simplen Aufruf der Tabellenfunktion:

 ... 
 DSTIMG IMG::open\_mouth:rgImg (...)
{
 DSTIMG Dst = DstImg(0, Org-\>bpp);

 // Aufruf der bpp-Funktion anhand des
 // Feldindexes 1 (bpp=8), 2 (bpp=16), 3 (bpp=24), 4 (bpp==32)
 **proctable[Dst-\>bpp/8]**(Dst-\>Data, Org-\>Data, Data, Area);

 ... 

Das ist doch „elegant“, oder? :wink:
Grüße

CMБ

1 Like

Hallo Semjon,

Danke erst mal für deine Antwort! So ganz 100%ig ist es auch nicht das, was ich suchte, da ich ja für jede Funktion wieder eine eigene Funktionstabelle anlegen müßte. (das mit dem Pattern kopieren, war ja nur ein einfaches Beispiel aus einer komplexen Library)
Aber die Idee dahinter ist genial. Mir ging es ja auch erst nur mal drum, wie ich so ein Problem generell lösen kann. Ich denke, mit diesem Ansatz komm ich erst mal ein ganzes Stückchen weiter.
Also danke noch mal,
husky

Spoiler
Ich denke, ich hab jetzt eine einfache und elegante Lösung gefunden.
Warum einfach, wenns auch kompliziert geht:smile: Damit sind alle Möglichkeiten
mit max. 4 Variablen und einer veränderlichen Klasse abgedeckt. Die Abfrage
selbst läuft zur Compile-Zeit.

//im Header

#define FP4(f,bpp,Par1,Par2,Par3,Par4)\ 
(bpp==24)?f(Par1,Par2,Par3,Par4):frowning:bpp==32)?f(Par1,Par2,Par3,Par4):\
(bpp==8)?f(Par1,Par2,Par3,Par4):f(Par1,Par2,Par3,Par4)

#define FP3(f,bpp,Par1,Par2,Par3)\
(bpp==24)?f(Par1,Par2,Par3):frowning:bpp==32)?f(Par1,Par2,Par3):\
(bpp==8)?f(Par1,Par2,Par3):f(Par1,Par2,Par3)

.... Analog für alle Fälle FP2, FP1 und FP 
.


// in der .cpp-Datei

template void T\_OrgImg (void\* Dst,void\* Org,LPBYTE Pat,int size)
{ for (int i=0;ibpp); // Erstellt ein leeres Image wie Org
**FP4(T\_OrgImg,Org-\>bpp,Dst-\>Data,Org-\>Data,Data,Area)**; //Template-Aufruf
 return Dst;
}


Auch z.B. ein Flip ist dann für alle Varianten schnell implementiert:

void CImg::Flip (int type)
{ 
 if ((type&FLIP\_BOTH)==FLIP\_BOTH) FP2(Reverse,bpp,Data,Area);
 int y,pitch=GetPitch(),pos1=0,pos2=Size-pitch;
 else if ((type&FLIP\_VERT)==FLIP\_VERT) 
 for (int i=0;iFP2(Reverse,bpp,Data+i\*pitch,Dx);
 else if ((type&FLIP\_HORZ)==FLIP\_HORZ) {
 LPBYTE Tmp = new BYTE[Size];
 memcpy (Tmp,Data,Size);
 for (y=0;y
Das Template muss nicht im Header stehen, da es nur intern aufgerufen wird.
Die Definition der Klassenfunktion ist kurz und bündig und alles ist paletti!

Grüße,
husky