Patron de classe et identification du type du parametre

Le
frank
Bonjour,

J'ai une classe template Bmp qui contient une image bitmap. Cette
classe peut être instanciée
avec un type ou un type RBG24_t Gray_t.

Le RGB24_t contient:
un champ de 8 bits pour le rouge
un champ de 8 bits pour le vert
un champ de 8 bits pour le bleu

Le Gray_t contient:
-un champ de 8 bits pour l'intensité de gris

Je tiens à ajouter une méthode pour calculer l'intensité moyenne.
mais elle doit travailler différemment
selon le paramètre:

Pour RGB24_t:

averageRed = somme de la composante rouge / nb pixels
averageGreen = somme des composante verte / nb pixels
averageBlue = somme des composante bleue / nb pixels


Pour Gray_t:

moyenne = somme de l'intensité de gris / nb pixels


La déclaration devrait ressembler a:

ComputeAverageIntensity int (composant char); / / le composant est
«r», «g», «b», «a», où a est pour le gris.

Mais comment la méthode peut-elle connaître le type d'instanciation?
Elle doit verifier que le «a» est utilisé uniquement quand Gray_t est
utilisé, aucun r, g, b lorsque Gray_t est utilisé, seul r, g, b
lorsque RBG24_t.

Vous pouvez proposer une autre mise en œuvre de la méthode, mais je
ne peux pas changer le fait que la classe est un template.

je vous remercie!
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #23030871
On Mon, 17 Jan 2011 07:28:33 -0800 (PST), frank

J'ai une classe template Bmp qui contient une image bitmap. Cette
classe peut être instanciée
avec un type ou un type RBG24_t Gray_t.



Tu as donc :

template <typename T> class Bmp;

et

Bmp<RBG24_t> et Bmp<Gray_t>

C'est bien ça ?


Je tiens à ajouter une méthode pour calculer l'intensité moyenne.



Es-tu absolument sûr de vouloir une fonction membre ?
S'il est possible de calculer cette intensité moyenne sans accéder aux
membres privés, tu peux en faire une fonction libre.
Ou plutôt, deux fonctions :

int ComputeAverageIntensity
(Bmp<RBG24_t> const& bitmap, char composant);
int ComputeAverageIntensity
(Bmp<Gray_t> const& bitmap, char composant);


S'il faut vraiment que cette fonction soit membre, tu peux soit
utiliser des spécialisations partielles, soit ruser un peu :

private:
static int DoComputeAverageIntensity
(Bmp<RBG24_t> const& bitmap, char composant);
static int DoComputeAverageIntensity
(Bmp<Gray_t> const& bitmap, char composant);

public:
int ComputeAverageIntensity (char composant) const
{ DoComputeAverageIntensity (*this, composant); }
Fabien LE LEZ
Le #23030861
J'avais écrit :

tu peux soit utiliser des spécialisations partielles,



J'ai l'esprit un peu nébuleux cette nuit. Il me semble fort que le mot
"partielles" est en trop ici.
Michael Doubez
Le #23031331
On 18 jan, 03:07, Fabien LE LEZ
On Mon, 17 Jan 2011 07:28:33 -0800 (PST), frank

> J'ai une classe template Bmp qui contient une image bitmap. Cette
>classe peut tre instanci e
> avec un type ou un type RBG24_t Gray_t.

Tu as donc :

template <typename T> class Bmp;

et

Bmp<RBG24_t> et Bmp<Gray_t>

C'est bien a ?

>Je tiens ajouter une m thode pour calculer l'intensit moyenne.

Es-tu absolument s r de vouloir une fonction membre ?
S'il est possible de calculer cette intensit moyenne sans acc der aux
membres priv s, tu peux en faire une fonction libre.
Ou plut t, deux fonctions :

int ComputeAverageIntensity
        (Bmp<RBG24_t> const& bitmap, char composant);
int ComputeAverageIntensity
        (Bmp<Gray_t> const& bitmap, char composant);

S'il faut vraiment que cette fonction soit membre, tu peux soit
utiliser des sp cialisations partielles, soit ruser un peu :

private:
  static int DoComputeAverageIntensity
        (Bmp<RBG24_t> const& bitmap, char composant);
  static int DoComputeAverageIntensity
        (Bmp<Gray_t> const& bitmap, char composant);

public:
  int ComputeAverageIntensity (char composant) const
    { DoComputeAverageIntensity (*this, composant); }



Une autre solution consiste à utiliser une classe de trait.
Quelque chose comme:

// La repésentation des pixels
struct RGB24_t
{
char red,green,blue,alpha;
};
struct Gray_t
{
char gray;
};

// les couleurs
namespace color {
// type name for each field
struct red_t{};
struct green_t{};
struct blue_t{};
struct alpha_t{};
struct gray_t{};
// ....
}

// Classe de traits pour extraite la valeur d'une couleur:
template<class T> class ColorTraits;

template<> struct ColorTraits<RGB24_t>
{
template<class TColor> static char value(RGB24_t const & rgba);
};

template<> struct ColorTraits<Gray_t>
{
template<class TColor> static char value(RGB24_t const & gray);
};

// Puis les spécialisations

template<> char
ColorTraits<RGB24_t>::value<color::red_t>(RGB24_t const & rgba)
{ return rgba.red; }

template<> char
ColorTraits<RGB24_t>::value<color::green_t>(RGB24_t const & rgba)
{ return rgba.green; }

template<> char
ColorTraits<RGB24_t>::value<color::blue_t>(RGB24_t const & rgba)
{ return rgba.blue; }

template<> char
ColorTraits<Gray_t>::value<color::gray_t>(Gray_t const & gray)
{ return gray.gray; }

Il y a peut être plus simple pour générer les traits mais là c'est à
l'huile de coude.

Ensuite tu definis ta fonction de calcul de l'intensité comme suit:

template<class TPixelColor, class TColorTrait =
ColorTraits<TPixelColor> >
class BMP
{
// ...
template<class TColor>
int ComputeAverageIntensity (TColor /* color */)
{
int intensity = 0;
for( all pixel )
{
intensity += TColorTrait::template value<TColor >(pixel);
}
return intensity;
}

};

Pour l'appel c'est du genre:
intensity = image.ComputeAverageIntensity(color::red_t());

Maintenant, comme tu passes un char, c'est un peu plus compliqué parce
que tu ne peux pas te permettre de générer toutes les fonctions en
faisant ça:

int ComputeAverageIntensity (char colorId)
{
switch(colorId)
{
case 'r': return ComputeAverageIntensity(color::red_t());
// ....
case 'g': return ComputeAverageIntensity(color::gray_t());
}
}

A la limite, tu peux utiliser une classe de trait par défaut:
template<class T> struct ColorTraits
{
template<class TColor, class TPixel>
static char value(TPixel)
{ assert( false && "unsupported color for pixel"); }
};

Ça te permettra de compiler mais tu n'aura l'erreur de mismatch qu'à
l'exécution.

Cette technique est inspiré de Boost.GIL. Si tu le peux, il sera peut
être plus rapide d'utiliser directement la bibliothèque (elle est en
HeaderOnly IIRC).

--
Michael
frank
Le #23031941
Fabien, tu as bien compris la situation:

template <typename T> class Bmp;


et


Bmp<RBG24_t> et Bmp<Gray_t>


C'est bien a ?



C'est preferable que la fonction soit membre parce qu'elle doit
acceder a chaque pixel. Dans le cas d'une image grise, elle doit
acceder a l'intensite du pixel et
dans le cas d'une image couleur aux trois composants red, green et
blue (dans la structure RGB24_t). Donc je retiens ta deuxieme
suggestion:

S'il faut vraiment que cette fonction soit membre, tu peux soit
utiliser des sp cialisations partielles, soit ruser un peu :

private:
static int DoComputeAverageIntensity
(Bmp<RBG24_t> const& bitmap, char composant);
static int DoComputeAverageIntensity
(Bmp<Gray_t> const& bitmap, char composant);

public:
int ComputeAverageIntensity (char composant) const
{ DoComputeAverageIntensity (*this, composant); }



Mais elle ne me contente pas completement. A l'interieur de la
fonction publique
ComputeAverageIntensity, comment savoir celle des 2 fonctions privees
appeler?
On peut y arriver en lisant le parametre composant. Mais si l'usager
s'est trompe (ex: il passe 'r' sur une image grise)
on ne peut pas l'empecher de deraper. J'aimerais que la fonction
publique sache si RGB24_t ou Gray_t a ete utilisee sans que l'usager
ait a lui dire.


frank
pasdespam
Le #23031931
frank
Mais elle ne me contente pas completement. A l'interieur de la
fonction publique
ComputeAverageIntensity, comment savoir celle des 2 fonctions privees
appeler?
On peut y arriver en lisant le parametre composant. Mais si l'usager
s'est trompe (ex: il passe 'r' sur une image grise)
on ne peut pas l'empecher de deraper. J'aimerais que la fonction
publique sache si RGB24_t ou Gray_t a ete utilisee sans que l'usager
ait a lui dire.



tu n'as rien a lui dire, il trouve seul la methode privée a appeller en
fonction de leurs signatures.
Fabien LE LEZ
Le #23033451
On Tue, 18 Jan 2011 06:11:20 -0800 (PST), frank

C'est preferable que la fonction soit membre parce qu'elle doit
acceder a chaque pixel.



Dans une classe "bitmap", je m'attendrais à trouver une fonction
membre publique qui permet de lire les pixels.

Cf http://www.gotw.ca/gotw/084.htm

A l'interieur de la
fonction publique
ComputeAverageIntensity, comment savoir celle des 2 fonctions privees
appeler?



Je t'ai donné l'intégralité du corps de ComputeAverageIntensity(), tu
n'as rien à changer. Laisse le compilo s'occuper des détails.
frank
Le #23034601
Je vous remercie les gars!
Publicité
Poster une réponse
Anonyme