[SDL] Problème de la detection de couleur d'un pixel [Résolu]

- - Dernière réponse :  allinaleks - 5 avril 2013 à 12:58
Bonjour à tous,

Je sollicite votre aide après avoir fait de longues recherches sur internet et tout particulièrement sur cette discussion.

http://www.cppfrance.com/forum/sujet-SDL-OBTENIR-COULEUR-PIXEL-DANS-SDL_SURFACE_424607.aspx

J’écris actuellement un code qui me servira dans le but de comparer la couleur d’un pixel donné d’une image avec tout les autres pixels de l’image.
Dans le cas ou ces deux couleurs sont identiques, je change la couleur du deuxième pixel en noir.

Par exemple si je prends une image de couleur uniforme et que je prends la couleur d’un pixel de cette image comme référence .
Je parcours tout les pixel un à un de cette image, et si tout se passe bien mon image final devrait être entièrement noire.

Dans mon cas, le problème est que lorsque je parcours les différents pixel de mon image, ceci influence les valeur de r,g,b .

Dans mon code rond.png est un carré mauve uniforme.

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include "SDL_image.h"



int main (int argc, char ** argv )
{
Uint8 r, g, b;
Uint8 re,gre,blue;

SDL_Surface *img=NULL;
int i,taille;
Uint32 couleur,echantillon;
img=IMG_Load("images/rond.png");

SDL_GetRGB(*(Uint32*)img->pixels+10, img->format, &re, &gre, &blue);

echantillon=SDL_MapRGB(img->format,re,gre,blue);
fprintf(stderr, " %d %d %d ",re,gre,blue);


/* ici je crée ma couleur de référence, JE CHOISI UN PIXEL DE COORDONNES 0,10 ET JE RECUPERE LES VALEURS DE redref,blueref,greenref
Mais la je rencontre un problème si je prend un pixel de coordonnées 0,11 blueref va s’incrémenter de 1, c’est pourquoi dans ma boucle if seul un pixel de même couleur est détecté */


couleur=SDL_MapRGB(img->format,9,9,9);

taille=img->w*img->h;

for(i=0;i<taille;i++)
{
SDL_GetRGB(*(Uint32*)img->pixels+i, img->format, &r,&g,&b);
if(r==re && g==gre && blue==b){
*( (Uint32*)img->pixels+i) =couleur;fprintf(stderr,"+");}

// fprintf me permet d afficher le nombre d’entrée dans la boucle même si je peux vérifier sur l’image finale que les pixel ont bien été modifié

}
SDL_SaveBMP(img, "image.png");
//résultat l image modifie n est pas noire, seul le pixel de coordonnées 0,10 est modifié
return 0;
}

J’ai aussi essayer ce bout de code sur la fin qui ne marche pas non plus on ne rentre même pas une fois dans le if une seule fois l image reste intacte.

for(i=0;i<taille;i++)
{

if(*( (Uint32*)img->pixels+i)==echantillon)
*( (Uint32*)img->pixels+i) =couleur;

}
J‘ai déjà utilisé GetRGB pour ce genre de manipulation mais cette fois-ci je coince vraiment.
J’espère avoir votre aide car j’ai vraiment tout essayé j’ai essayer de coller l image sur un écran pour comparer les couleurs de mon image, sans résultat.
Merci d’avance :D
Afficher la suite 

Votre réponse

6 réponses

Meilleure réponse
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
3
Merci
Merci pour la réponse.

Comme j'ai vu que tu essayais de sauvegarder en PNG, je précise que ce n'est pas faisable de base. Tu peux utiliser cette fonction qui permet de sauvegarder aisément en PNG plutôt qu'en BMP:
https://github.com/cptpingu/game/tree/master/src/SDL

Je me permet de mettre ton code dans des balises de code et de mettre au propre 2-3 petits trucs vraiment mineurs (pas besoin de break si tu as un return par exemple, ajout de const, ajout d'assert):
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include "SDL_image.h"

Uint32 getpixel(const SDL_Surface* surface, int x, int y)
{
  const int bpp = surface->format->BytesPerPixel;

  /* Here p is the address to the pixel we want to retrieve */
  const Uint8* p = (Uint8*)surface->pixels + y * surface->pitch + x * bpp;

  switch (bpp)
  {
    case 1:
      return *p;
    case 2:
      return *(Uint16*)p;
    case 3:
      if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
      return p[0] | p[1] << 8 | p[2] << 16;
    case 4:
      return *(Uint32*)p;
    default:
      assert(false && "Shouldn't be reached!");
      return 0;
  }
  return 0;
}

int main (void)
{
  int i, j;
  SDL_Surface* img = NULL;
  Uint32 couleur, echantillon;
  img = IMG_Load("images/rond.bmp");

  echantillon = getpixel(img, 80, 80);
  couleur = SDL_MapRGB(img->format, 0, 255, 9);


  for (i = 0; i < img->h; ++i)
    for (j = 0; j < img->w; ++j)
      if (echantillon == getpixel(img, j, i))
*((Uint32*)img->pixels + (img->h * i) + j) = couleur;

  SDL_SaveBMP(img, "image.bmp");
  //SDL_SavePNG(img, "image.png"); cf fonction que je te propose ci-dessus.
  return 0;
}


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 104 internautes ce mois-ci

Commenter la réponse de cptpingu
0
Merci
’ correspond a un apostrophe je ne sais pas comment remodifier mon message ^^ je suis nouveau sur le forum
Commenter la réponse de allinaleks
0
Merci
j'ai trouvé ma réponse finalement :D
Commenter la réponse de allinaleks
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Bonjour.

j'ai trouvé ma réponse finalement

Félicitations. Mais il est d'usage de plutôt poster: "Voici la solution que j'ai appliqué + solution", plutôt que: "C'est ok".
Quelqu'un qui tomberait sur ton sujet et qui aurait le même problème que toi, serait surement intéressé par la solution :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
Commenter la réponse de cptpingu
0
Merci
oui je comprend et j'allais le faire, j'ai juste pas eu le temps je suis parti manger car j'ai du poster la solution sur deux autres forum :D et j'ai mis résolu ici pour prévenir que la solution est trouvée.

voici la réponse néanmoins je comprend ta remarque

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include "SDL_image.h"


Uint32 getpixel(SDL_Surface *surface, int x, int y);

int main (int argc, char ** argv )
{
int i,j;
SDL_Surface *img=NULL;
Uint32 couleur,echantillon;
img=IMG_Load("images/rond.bmp");

echantillon=getpixel(img,80,80);

couleur=SDL_MapRGB(img->format,0,255,9);


for(i=0;ih;i++)
for (j=0; jw; j++)
{
if(echantillon==getpixel(img,j,i))
*( (Uint32*)img->pixels+(img->h*i)+j) =couleur;
}
SDL_SaveBMP(img, "image.bmp");
return 0;
}

Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
return *p;
break;

case 2:
return *(Uint16 *)p;
break;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;

case 4:
return *(Uint32 *)p;
break;

default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
Commenter la réponse de allinaleks
0
Merci
merci pour ta réponse j'ai encore appri des choses et merci pour le liens de ton code SavePNG par contre on m'a dit que cette ligne
*((Uint32*)img->pixels + (img->h * i) + j) ne marche pas tout le temps et qu il faut utiliser une fonction putpixel.

Sur mon ordinateur ça marche sans problème mais un ami a moi a du utilisé cette fonction pour remplacer la ligne.
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    
    switch(bpp) {
        case 1:
            *p = pixel;
            break;
            
        case 2:
            *(Uint16 *)p = pixel;
            break;
            
        case 3:
            if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                p[0] = (pixel >> 16) & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = pixel & 0xff;
            } else {
                p[0] = pixel & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = (pixel >> 16) & 0xff;
            }
            break;
            
        case 4:
            *(Uint32 *)p = pixel;
            break;
    }
}
Commenter la réponse de allinaleks

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.