Bonjour

Je poste pour la première fois ici

Je développe toutes sortes de petits programmes et aussi un projet de réalité virtuelle en C/C++ avec SDL/OpenGL et d'autres librairies que j'ajouterais par la suite. J'ai l'intention de poster des codes-sources sur ce site, mais avant j'aimerais vous les montrer et en discuter via ce forum, pour respecter le principe de ce site.
Aujourd'hui, je souhaite avoir votre avis sur un système d'images et de masques binaires codé en objet. Je voulais mettre une capture du résultat, mais je ne sais pas me servir de tout ça

Le système contient :
- un objet Image qui contient une SDL_Surface avec canal alpha, et un pointeur vers un masque binaire aux mêmes dimensions
- un objet Ecran qui hérite de Image et initialise l'écran (en tant qu'Image) et la fenêtre SDL
- un objet MasqueBin qui est constitué d'un tableau dynamique de booléens (binaire
) et ses dimensions
Je ne vous montre pas les objets Ecran et MasqueBin parce que leurs détails ne sont pas indispensables pour la partie dont je souhaite votre avis.
(Je ne sais pas mettre du code sur le forum)
Méthodes de Image :static const Uint32 r_mask = 0x00FF0000;
static const Uint32 g_mask = 0x0000FF00;
static const Uint32 b_mask = 0x000000FF;
static const Uint32 a_mask = 0xFF000000;
/* Classe Image */
/* Constructeur d'Image avec paramètres */
Image::Image(char* fichier, int x, int y, int w, int h, MasqueBin *Masque)
{
// Chargement de l'image du fichier dans temp (en RAM)
SDL_Surface* temp = SDL_LoadBMP(fichier);
// Attribution d'une taille par défaut si valeur à 0
if ( w == 0 )
w = temp->w;
if ( h == 0 )
h = temp->w;
// Création de la surface final en VRAM ou en RAM
image = NULL;
image = SDL_CreateRGBSurface(SDL_HWSURFACE, w, h, 32, r_mask, g_mask, b_mask, a_mask); // en VRAM
if ( image == NULL ) // Si la mémoire video était saturée
image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, r_mask, g_mask, b_mask, a_mask); // en RAM
SDL_Rect R = {x,y,w,h};
// Copie de temp (en RAM) dans image (en VRAM ou en RAM)
SDL_BlitSurface(temp, &R, image, NULL);
// Suppression de temp : liberation de RAM
SDL_FreeSurface(temp);
// Attribution du masque, uniquement de mêmes dimensions
if ( Masque != NULL )
{
if ( Masque->w == w && Masque->h == h )
masque = Masque;
#ifdef _DEBUG
else
{
printf("ERREUR : Une image n'a pas pu recevoir le masque désiré,\n");
printf(" car ce dernier n'a pas les mêmes dimensions !\n");
printf(" image : %dx%d != masque : %dx%d\n",w, h, Masque->w, Masque->h);
}
#endif
}
}
/* Rendre invisible une couleur */
void Image::CouleurInvisible(int R, int V, int B)
{
Uint8 *imp = NULL;
// SDL_LockSurface(image);
#ifdef _DEBUG
if ( R <= 255 && R >= 0 && V <= 255 && V >= 0 && B <= 255 && B >= 0 )
{
#endif
for ( int y=0 ; y<image->h ; y++ )
{
imp = (Uint8 *)image->pixels + y * image->pitch;
for ( int x=0 ; x<image->w ; x++ )
{
if ( imp[0] == R && imp[1] == V && imp[2] == B )
imp[3] = 0;
imp += 4;
}
}
#ifdef _DEBUG
}
else
{
printf("ERREUR : Une image n'a pas pu recevoir de transparence,\n");
printf(" car la couleur spécifié %d:%d:%d n'existe pas !\n", R, V, B);
}
#endif
// SDL_UnlockSurface(image);
}
/* Effacer à la couleur et l'alpha désirés */
void Image::Effacer(int R, int V, int B, int A)
{
Uint8 *imp = NULL;
// SDL_LockSurface(image);
#ifdef _DEBUG
if ( R <= 255 && R >= 0 && V <= 255 && V >= 0 && B <= 255 && B >= 0 && A <= 255 && A >= 0 )
{
#endif
for ( int y=0 ; y<image->h ; y++ )
{
imp = (Uint8 *)image->pixels + y * image->pitch;
for ( int x=0 ; x<image->w ; x++ )
{
imp[0] = R;
imp[1] = V;
imp[2] = B;
imp[3] = A;
imp += 4;
}
}
#ifdef _DEBUG
}
else
{
printf("ERREUR : Une image n'a pas pu être effacé,\n");
printf(" car la couleur spécifié %d:%d:%d:%d n'existe pas !\n", R, V, B, A);
}
#endif
// SDL_UnlockSurface(image);
}
/* Dessiner l'image sur une autre */
// Optimisé ( environ 0.23 ms au dernier test, pas pu faire mieux)
void Image::Dessiner(Image* dest, int X, int Y, int W, int H)
{
Uint8 *dep = NULL, *imp = NULL;
int Xim = 0, Yim = 0;
// Ajustement des limites de la destination
if ( X < 0 )
{
Xim = -X;
X = 0;
}
if ( Y < 0 )
{
Yim = -Y;
Y = 0;
}
if ( X+W > dest->image->w ) W = dest->image->w - X;
if ( Y+H > dest->image->h ) H = dest->image->h - Y;
W -= Xim;
H -= Yim;
bool mask = true;
int i = 0;
// Dessin de l'image sur la destination
// SDL_LockSurface(dest->image);
for ( int y=0 ; y<H ; y++ )
{
dep = (Uint8 *)dest->image->pixels + (Y+y) * dest->image->pitch + X * 4;
imp = (Uint8 *)image->pixels + (Yim+y) * image->pitch + Xim * 4;
for ( int x=0 ; x<W ; x++ )
{
if ( dep[3] == 0 )
{
if ( masque != NULL )
mask = masque->b[i];
if ( mask )
{
if ( imp[3] != 0 )
{
dep[0] = imp[0];
dep[1] = imp[1];
dep[2] = imp[2];
dep[3] = imp[3];
}
}
dep += 4;
imp += 4;
}
i++;
}
}
// SDL_UnlockSurface(dest->image);
}
Je n'utilise pas les fonctions de dessin de SDL, je réécris les miennes sous formes de méthodes. Le dessin ne ce fait pas de l'écran vers l'utilisateur, mais à l'inverse. C'est à dire que l'ordinateur teste les du support sur lequel il doit dessiner et vérifie que son alpha est à 0. Si ce n'est pas le cas, c'est qu'il y a déjà quelque chose à cette endroit là, donc on ne dessine rien. Ce qui veut dire qu'on dessine d'abord les images devant et progressivement ceux qui suivent jusqu'au plus en arrière. Si une image est partiellement recouverte, elle sera partiellement dessiné, voir ignorée si totalement cachée.
J'ai tester la vitesse d'exécution de cette méthode et, à moins d'une erreur, c'est plus rapide que dessiner chaque images les unes sur les autres. Je pensais que tester les pixels était plus lent que directement dessiner sans rien vérifier, mais mes tests me disent l'inverse
Si mes tests sont exacts alors je suis content, car mon but est d'optimiser la vitesse de calcul le plus possible, sans non plus trop mordre sur la mémoire.
Parcontre niveau gestion des images par rapport à la mémoire video. Je mets les images en mémoire video et après mes méthodes travaille dessus. J'ai mis en commentaire SDL_LockSurface() et SDL_UnlockSurface() parce que je ne suis pas sûr qu'ils soient utiles. Sans, ça fonctionne très bien, mais les images devrait être théoriquement en VRAM, à moins que ce ne soit pas le cas. Je ne comprends pas trop les Lock et Unlock dans SDL.