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

Résolu
allinaleks - 3 avril 2013 à 21:21
 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

6 réponses

cptpingu Messages postés 3838 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 17 juin 2024 124
5 avril 2013 à 11:21
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
3
’ correspond a un apostrophe je ne sais pas comment remodifier mon message ^^ je suis nouveau sur le forum
1
j'ai trouvé ma réponse finalement :D
0
cptpingu Messages postés 3838 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 17 juin 2024 124
4 avril 2013 à 21:11
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
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 */
}
}
0
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;
    }
}
0
Rejoignez-nous