IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SDL Discussion :

codage image 8bits


Sujet :

SDL

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut codage image 8bits
    Bonjour à tous
    Je code en ce moment avec openGL un petit générateur de carte en 3D à partir d'une heighmap générée sous forme de SDL_Surface ayant 8 bits de profondeur (1 bytePerPixel).

    Lorsque j'essaie de récupérer les composantes de la surface, j'obtiens des valeurs vraiment bizarres et totalement différentes suivant la taille de l'image et certains éléments rajoutés : je m'explique : pour tester ma fonction j'utilise une surface présentant un dégradé du blanc vers le noir, donc dont les composantes sont sensées aller de 255 à 0. Cependant, suivant la taille de la surface, les composantes varient de 0 à une valeur me paraissant totalement aléatoire (toujours inférieure à 255) et variant en fonction de la taille de l'image et de l'image elle même (par exemple si je rajoute un cercle blanc sur l'image la valeur de la composante correspondant au blanc sera changée), tout en conservant une diminution liée au dégradé. Je dois avouer que je ne comprends vraiment pas la raison de ce maximum aléatoire correspondant au la couleur blanc qui me bloque totalement pour la suite, même si je pourrai toujours passer par des images 32 ou 24 bits qui elles sont correctement décomposées par la fonction.

    J'espère avoir été suffisamment clair pour être compris , je souhaiterais en gros obtenir la méthode de codage sur 8 bits des images afin de pouvoir récupérer des composantes comprises entre 0 et 255 correspondant au noir et au blanc, et non des composantes comprises entre 0 et une valeur imprévisible

    Si vous voulez des bouts de code, n'hésitez pas, j'avoue que je poste ça un peu a la hâte mais je peux vous fournir les parties concernées si vous le souhaitez

  2. #2
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    En général avec la SDL il faut utiliser certaine fonction pour modifier pixel par pixel et pas modifier le tableau directement.

    voici un exemple :http://www.libsdl.org/docs/html/guidevideo.html
    il faut utiliser putpixel et getpixel pour récupérer puis modifier le pixel.

    Apres y a la méthode 'bourrin' c'est de créer ces propre structure image et loader (c'est je que je fais sur opengl).

  3. #3
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut
    Effectivement j'avais déjà utilisé ces méthodes auparavant sans les comprendre ce qui n'est plus le cas aujourd'hui mais je ne comprends pas pourquoi j'obtiens quelque chose de faux alors que mon code revient exactement au même (la première composante est déjà fausse alors qu'il s'agit de celle pointée par le pointeur (Uint8*)surface->pixels).
    Parfois je n'y comprends rien

    Ps : je voulais juste aussi savoir à quoi correspondait le pitch d'une SDL_Surface, en regardant la doc je n'ai pas bien saisi

    Edit : je viens de tester la fonction fournie par la sdl (après avoir appelé lock_surface évidemment et celle-ci fournit les mêmes résultats faux que la mienne )

    Edit (encore) : nouvelle précision avec certaines images les composantes fournies sont correctes à 8 unités près (la véritable composante est égale à celle lue augmentée de 8)

    Edit (encore bis) : en fait en changeant l'image en mettant du blanc (255) du gris clair(200) du gris foncé(100) et du noir(0) on obtient a nouveau des résultats aberrants (174 pour 255, 167 pour 200, 0 pour 0 (correct ^^) et 99 pour 100)

  4. #4
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Je trouve ça étrange que ces fonction ne marche pas ,il faudra donner un peu de code je pense.
    pitch correspond a la longueur en octet , donc on gros w*format (rvb = 3 , mono = 1 , rvba = 4).

  5. #5
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut
    Merci pour la signification du pitch

    Pour quelques morceaux de code pas de problème :

    Voici la fonction complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    template <typename T>
    std::vector<std::vector<unsigned char> > AlwaysUseful<T>::convertSurfaceToVector(SDL_Surface *surface, int flag)
    {
        std::vector<std::vector<unsigned char> > toReturn;
     
        if(flag == NO_FLAG || surface == NULL)
            return toReturn;
     
        int numberComponent = 0;
        if(flag&0x08)
            numberComponent++;
        if(flag&0x04)
            numberComponent++;
        if(flag&0x02)
            numberComponent++;
        if(flag&0x01)
            numberComponent++;
     
        toReturn.resize(surface->h);
        std::vector<unsigned char> temp(numberComponent*surface->w);
     
        SDL_LockSurface(surface);
     
        int tempComponent;
        Uint8 *p = (Uint8*)surface->pixels;
     
        for(int i=0;i<surface->h;i++)
        {
            for(int j=0;j<surface->w;j++)
            {
                tempComponent = 0;
                if(flag&0x08&&surface->format->BytesPerPixel==4)
                {
                    temp[j*numberComponent+tempComponent] = *(p+i*surface->w*surface->format->BytesPerPixel+j*surface->format->BytesPerPixel+3);
                    tempComponent++;
                }
                if(flag&0x04&&surface->format->BytesPerPixel>2)
                {
                    temp[j*numberComponent+tempComponent] = *(p+i*surface->w*surface->format->BytesPerPixel+j*surface->format->BytesPerPixel+2);
                    tempComponent++;
                }
                if(flag&0x02&&surface->format->BytesPerPixel>1)
                {
                    temp[j*numberComponent+tempComponent] = *(p+i*surface->w*surface->format->BytesPerPixel+j*surface->format->BytesPerPixel+1);
                    tempComponent++;
                }
                if(flag&0x01&&surface->format->BytesPerPixel>0)
                    temp[j*numberComponent+tempComponent] = *(p+i*surface->w*surface->format->BytesPerPixel+j*surface->format->BytesPerPixel);
            }
            toReturn[i] = temp;
        }
     
        SDL_UnlockSurface(surface);
     
        return toReturn;
    }
    La fonction prend en paramètre une image (SDL_Surface) et un Flag que j'ai indiqué dans une enum déterminant les composantes de l'image à prendre en compte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enum FLAG{NO_FLAG = 0, R_FLAG = 1, G_FLAG = 2, B_FLAG = 4, A_FLAG = 8};
    Elle retourne un tableau (de tableau) de char non signés (sinon on a aussi des valeurs négatives). Je pense que le code parle de lui même, mais si vous voulez plus d'explication n'hésitez pas !

    J'ai oublié de préciser qu'il s'agissait d'une fonction statique d'une classe templatée ce qui a peut être une influence sur le résultat obtenu, ce que je ne pense pas cependant puisque d'autres fonctions de la classe fonctionnent parfaitement.

  6. #6
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Je vois je dirais que ça devrait marcher mais j'ai pas le temps de vraiment me pencher dessus pour voir ce qui cloche ,pour modifier les pixel avec la SDL , il faut faire comme cela (un exemple de fonction qui transforme image en Noir et blanc) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    void gris(SDL_Surface *image)
    {
     
        int x,y;
        Uint32 pixel;
        Uint8 r,v,b,a,g;
     
     
        SDL_LockSurface(image);
     
        for (y=0;y<image->h;y++)
        {
            for (x=0;x<image->w;x++)
            {
                pixel = getpixel(image,x,y);
     
                SDL_GetRGBA(pixel, image->format, &r, &v, &b,&a);
                g = (r+v+b)/3;
                r = v = b = g;
                //ou on modifie les pixel
     
                pixel =SDL_MapRGBA(image->format, r, v, b, a);
     
                putpixel(image, x, y, pixel);
            }
        }
     
        SDL_UnlockSurface(image);
    }

  7. #7
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut
    Je viens de réaliser une expérience intéressante qui prouve que le problème ne vient pas de la fonction mais bien de la manière dont les images 8 bits sont enregistrées et compressées.

    En effet, j'ai reconverti le tableau de char obtenu en une autre surface que j'ai sauvegardé, devant logiquement aboutir à la même image qu'au départ. La ressemblance entre les 2 images est frappante, mais il subsiste une légère ombre au tableau : moins il y a de niveau de gris et de couleurs différentes dans la première et plus la "blancheur" de l'image sauvegardée est faible : la luminosité de la seconde image augmente "proportionnellement" (ce n'est sans doute pas proportionnel au sens strict du terme) avec le nombre de couleurs différentes sur la première image.

    Ainsi, un dégradé linéaire sur une image de 30*30 sera plus assombri sur la deuxieme image que le même dégradé sur une image de 256*256 présentant tous les niveaux de gris de 0 à 256

    Avez-vous une explication ?
    Images attachées Images attachées   

  8. #8
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut
    Je viens de trouver une piste très intéressante concernant l'attribut surface->format->palette->colors[...]
    Je vous tient au courant

  9. #9
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Hello,

    l'image est sûrement codée au moyen de couleurs indexées, ce qui veut dire que ce qui est codé pour chaque pixel ne correspond pas à la couleur elle-même, mais à un index.

    Cet index est stocké dans une table de correspondance où pour chaque index correspond une couleur bien définie (d'après ton dernier post, ça s'appelle 'palette' dans ton environnement).
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  10. #10
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Points : 176
    Points
    176
    Par défaut
    Oui c'est exactement ça je viens de m'en apercevoir à l'instant la couleur comprise entre 0 et 255 est stockée dans la palette et, pour une image codée sur 8 bits, lorsqu'on souhaite accéder à une composante via surface->pixels on accède en fait au niveau de gris de la composante, et non à sa "véritable" couleur.

    Merci à tous, sujet résolu donc

    Ps : pour ceux qui seront éventuellement confronté au même problème, voici le code fonctionnel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    template <typename T>
    std::vector<std::vector<unsigned char> > AlwaysUseful<T>::convertSurfaceToVector(SDL_Surface *surface, int flag)
    {
        std::vector<std::vector<unsigned char> > toReturn;
     
        if(flag == NO_FLAG || surface == NULL)
            return toReturn;
     
        int numberComponent = 0;
        if(flag&0x08)
            numberComponent++;
        if(flag&0x04)
            numberComponent++;
        if(flag&0x02)
            numberComponent++;
        if(flag&0x01)
            numberComponent++;
     
        toReturn.resize(surface->h);
        std::vector<unsigned char> temp(numberComponent*surface->w);
     
        SDL_LockSurface(surface);
     
        int tempComponent;
        Uint8 *p = (Uint8*)surface->pixels;
        for(int i=0;i<surface->h;i++)
        {
            for(int j=0;j<surface->w;j++)
            {
                tempComponent = 0;
                if(flag&0x08&&surface->format->BytesPerPixel==4)
                {
                    temp[j*numberComponent+tempComponent] = surface->format->palette->colors[*(p+i*surface->pitch+j*surface->format->BytesPerPixel+3)].unused;
                    tempComponent++;
                }
                if(flag&0x04&&surface->format->BytesPerPixel>2)
                {
                    temp[j*numberComponent+tempComponent] = surface->format->palette->colors[*(p+i*surface->pitch+j*surface->format->BytesPerPixel+2)].b;
                    tempComponent++;
                }
                if(flag&0x02&&surface->format->BytesPerPixel>1)
                {
                    temp[j*numberComponent+tempComponent] = surface->format->palette->colors[*(p+i*surface->pitch+j*surface->format->BytesPerPixel+1)].g;
                    tempComponent++;
                }
                if(flag&0x01&&surface->format->BytesPerPixel>0)
                    temp[j*numberComponent+tempComponent] = surface->format->palette->colors[*(p+i*surface->pitch+j*surface->format->BytesPerPixel)].r;
            }
            toReturn[i] = temp;
        }
     
        SDL_UnlockSurface(surface);
     
        return toReturn;
    }

  11. #11
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Pour la postérité: ce principe permet de mieux adapter la palette de couleur en fonction de l'image à représenter que si tu avais 256 couleurs fixes.

    Par exemple, si tu veux représenter une image d'un désert, tu auras besoin de beaucoup de nuances de jaune, et donc tu pourras te permettre d'avoir par exemple 200 des 256 valeurs codables qui représentes des nuances précises de ces couleurs.

    A contrario, si tu cherches à représenter une photo d'un océan, ce sont les nuances de bleu qui t'intéresseront en priorité, etc...

    Et d'ailleurs, les premiers ordinateurs personnels, du fait de leur mémoire rare et chère (donc très limitée), utilisaient abondamment ce système. Genre les bon vieux amstrad CPC, amiga, etc...
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  12. #12
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 074
    Points : 7 978
    Points
    7 978
    Par défaut
    Bah et les pc alors ? avec ce bon vieux mode VGA 8 bits palletisé ^^
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Image et codage RGB
    Par perldebutant dans le forum 2D
    Réponses: 6
    Dernier message: 03/05/2007, 07h26
  2. Codage d'une image en base64
    Par Pierre Fauconnier dans le forum Traitement d'images
    Réponses: 5
    Dernier message: 30/03/2007, 16h51
  3. Récupération du codage d'une image
    Par Cedwik dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 04/09/2006, 14h59
  4. Réponses: 5
    Dernier message: 18/05/2005, 13h03
  5. Réponses: 5
    Dernier message: 15/01/2005, 18h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo