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

C++ Discussion :

Erreur lecture et enregistrement d'image


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut Erreur lecture et enregistrement d'image
    salut les gars
    voila j'essaye de lire une image 2D DICOM mais il y a un problème que j'arrive pas à le repérer il est au niveau d'enregistrement de l'image comme PNG (j'ai essayé aussi JPG) à l'aide de QT
    voila la procédure que je suis :
    * lire les tag et les afficher ( j'utilise un autre logiciel pour savoir si les tag sont bien affichés et oui ils sont)
    * quand j’atteins le TAG PIXEL_DATA =0x7FE00010 je sort de la boucle de lecture de tag
    *je calcule le height*width (2 tag déja récupérer) pour savoir le nombre de pixel dans l'image (et ça aussi se déroule très bien la taille la même que celle que donne le logiciel PRO)
    *je regard samplesPerPixel et bitsAllocated (2 tag déja récuperer)pour savoir comment l'image est codée bitsallocated prend 8 ou 16 samplesPerPixel soit 1 soit 3
    *si bitsallocated est à 8 je recupere height*width bit et je les mis dans un buffer
    unsigned char *pixel_8;
    *si bitsallocated est à 16 je recupere 2*(height*width) bit et je les mis dans un autre buffer
    unsigned short *pixel_16;

    J'utilise pour la lecture fread du stdio
    maintenant j'utilise juste bitsallocated=16 pas de 8 :p
    ensuite je regard dans pixelRepresentation une variable qui contient soit 0: non signed ou 1 :signed

    et c'est là ou le probléme se pose :
    si j'essaye d'enregistrer l'image comme il est sans transformer les pixel de signer à non signer le programme est planté dans cette l'igne


    png_write_rows(png_ptr, row_pointers, 1);
    qui est dans qpnghandler.h et j’obtiens la célèbre "violence d'accès à un emplacement privée bla bla "
    voila toute la partie intéressante de la fonction où VC se plante (plutôt mon prog . :p)
    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
    case QImage::Format_Mono:
        case QImage::Format_MonoLSB:
        case QImage::Format_Indexed8:
        case QImage::Format_RGB32:
        case QImage::Format_ARGB32:
        case QImage::Format_RGB888:
            {
                png_bytep* row_pointers = new png_bytep[height];
                for (int y=0; y<height; y++)
                    row_pointers[y] = (png_bytep)image.constScanLine(y);
                png_write_image(png_ptr, row_pointers);
                delete [] row_pointers;
            }
            break;
        default:
            {
                QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
                QImage row;
                png_bytep row_pointers[1];
                for (int y=0; y<height; y++) {
                    row = image.copy(0, y, width, 1).convertToFormat(fmt);
                    row_pointers[0] = png_bytep(row.constScanLine(0));
                    png_write_rows(png_ptr, row_pointers, 1);
                }
            }
    mais attend j'ai une image (plutot une demi image qui ressamble un peu à la photo que je dois avoir :
    l'image original



    ce que j’obtiens



    voila aussi la fonction de lecture et d'enregistrement que j'utilise rien de plus facile

    if (samplesPerPixel == 1 && bitsAllocated == 16)
    {
    pixel_16=(unsigned char*)malloc(numPixels*2);


    fread(pixel_16,1,numPixels*2,dicom_file);
    QImage img( (unsigned char *) pixel_16,
    width,
    height,
    QImage::Format_RGB32);
    img.save("c:/test.png","PNG");
    }
    avec numPixels=height*width

    j'utilise QImage::Format_RGB32 mais aussi avec d'autre format j'obtiens toujours des d'erreur l' hors d'enregistrement de l'image
    malheureusement c'est la premier fois que je travail sur les images
    ce que je demande c'est juste des indications soit au niveau de l’enregistrement de l'image généralement ( je ne sais pas si la méthode que j'utilise est correct ou non ) soit sur mon code
    et mille merccii
    cordialement warlock

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    je ne suis malheureusement pas chez moi où j'ai des sources qui enregistrent/lisent du png avec la libpng.
    Mais le problème semble être l'ordre dans lequel tu enregistres les composantes des pixels. En fait on dirait que tu n'enregistres que la composante rouge de ton pixel.

    Voilà un exemple que je viens de trouver qui indiquer la lecture/écriture d'un fichier PNG: http://zarb.org/~gc/html/libpng.html
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
            for (y=0; y<height; y++)
                    row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
     
            png_read_image(png_ptr, row_pointers);
    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
    png_init_io(png_ptr, fp);
     
     
            /* write header */
            if (setjmp(png_jmpbuf(png_ptr)))
                    abort_("[write_png_file] Error during writing header");
     
            png_set_IHDR(png_ptr, info_ptr, width, height,
                         bit_depth, color_type, PNG_INTERLACE_NONE,
                         PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
     
            png_write_info(png_ptr, info_ptr);
     
     
            /* write bytes */
            if (setjmp(png_jmpbuf(png_ptr)))
                    abort_("[write_png_file] Error during writing bytes");
     
            png_write_image(png_ptr, row_pointers);
     
     
            /* end write */
            if (setjmp(png_jmpbuf(png_ptr)))
                    abort_("[write_png_file] Error during end of write");
     
            png_write_end(png_ptr, NULL);
    A priori tu devrais avoir un truc comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    png_byte** row_pointers = new png_byte*[height];
                for (int y=0; y<height; y++) {
                    row_pointers[y] = new png_byte[width];
                    // fill line here
    }
                png_write_image(png_ptr, row_pointers);
                delete [] row_pointers;
    Mais ne sachant pas ce que fait le scan line, c'est peut-être déjà ce que tu fais.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    merci Bousk pour ta réponse
    mais mon problème c'est que
    * je ne sais pas si la méthode que j'utilise pour lire es pixel est correct ou non
    car je dois les lire manuellement pas avec libpng
    et j'ai déja testé le code fourni avec l’exemple de libpng et il se plante aussi

    mercii encore

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Pour cela, il faudrait voir la fonction de lecture^^
    Effectivement, il est possible que la lecture en amont soit fausse et génère cette image des plus étranges^^
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    merci Bousk je vais relire le standard pour savoir si j'ai commis une erreur

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Ne peux-tu pas utiliser la libpng également pour la lecture de l'image ?
    Sinon, tu peux toujours en regarder les sources, c'est pas évident à suivre, mais ça peut débloquer
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre à l'essai
    Inscrit en
    Juin 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    non malheureusement je ne peux pas utiliser libpng puisque je dois lire l'image manuellement et je crois que libpng ne prend pas les fichiers DICOM en compte

    voila ce que j'ai compris en lisant le standard

    je dois commencer à lire les pixel à partir de l'adresse du tag PIXEL DATA
    + j'ai choisi une image avec bitAllocated à 8 bits pour ne pas tenir compte au si les bytes sont signe ou insigne et ca ne marche aussi pas

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Effectivement, je n'avais pas remarqué cette partie du message.

    Je ne connaissais pas les images DICOM, voilà ce que j'ai trouvé https://docs.google.com/viewer?a=v&q...5_Cjo65mi-iyNg

    Je vois surtout ceci
    image : codées en binaire, en général non compressées
    Donc leur lecture ne doit pas être bien compliquée

    Une fois que tu as tous tes pixels en RGB, tu peux utilier libpng pour les enregistrer dans un fichier png, voir ce code que j'avais réalisé pour enregistrer une SDL_Surface*
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    #include <SDL.h> 
     
    #include <time.h> 
     
    #include <png.h> 
     
    #include <string> 
    #include <iostream> 
    using namespace std; 
     
    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;  
       
        case 2:  
            return *(Uint16 *)p;  
       
        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;  
       
        case 4:  
            return *(Uint32 *)p;  
       
        default:  
            return 0; /* shouldn't happen, but avoids warnings */  
        }  
    } 
     
    bool saveAsPNG(SDL_Surface* toSave, string fileName) 
    { 
         FILE* file = fopen(fileName.c_str(), "wb"); 
        
         png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); 
         if(!png_ptr) 
         { 
              fclose(file); 
              return false; 
         } 
          
         png_infop   png_info = png_create_info_struct(png_ptr); 
          
         if(!png_info)  
         { 
              png_destroy_write_struct(&png_ptr, &png_info); 
              fclose(file); 
              return false; 
         } 
          
         if(setjmp(png_ptr->jmpbuf)) 
         { 
              png_destroy_write_struct(&png_ptr, &png_info); 
              fclose(file); 
              return false; 
         } 
          
         /* données de l'image */ 
         png_init_io(png_ptr, file); 
          
         // type de compression 
         png_set_compression_level(png_ptr, Z_BEST_SPEED); 
          
         // infos de l'image 
         png_set_IHDR(png_ptr, png_info, static_cast<png_uint_32>(toSave->w),  
                      static_cast<png_uint_32>(toSave->h), 8,  
                      PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,  
                      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
         // date de création 
         png_time  modtime; 
         png_convert_from_time_t(&modtime, time(NULL)); 
         png_set_tIME(png_ptr, png_info, &modtime); 
          
         // commentaires de l'image 
         png_text text[6]; 
          
         text[0].key = "Title"; 
         text[0].text = ""; 
         text[0].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         text[1].key = "Author"; 
         text[1].text = ""; 
         text[1].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         text[2].key = "Description"; 
         text[2].text = ""; 
         text[2].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         text[3].key = "Copyright"; 
         text[3].text = ""; 
         text[3].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         text[4].key = "E-mail"; 
         text[4].text = ""; 
         text[4].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         text[5].key = "Url"; 
         text[5].text = ""; 
         text[5].compression = PNG_TEXT_COMPRESSION_NONE; 
          
         png_set_text(png_ptr, png_info, text, 6); 
     
         /* écriture de l'image */ 
         png_write_info(png_ptr, png_info); 
     
         png_byte* line; 
         line = new png_byte[toSave->w * 3]; 
         for(int i = 0; i < 480; ++i) 
         { 
              for(int p = 0, j = 0; j < toSave->w; ++j) 
              { 
                   // extraction du pixel de la SDL_Surface* 
                   Uint32 pixel = getPixel(toSave, j, i); 
                   // extraction de chaque composante et écriture du pixel dans la ligne du png 
                   line[p++] = pixel>>16; 
                   line[p++] = pixel>>8; 
                   line[p++] = pixel; 
              } 
              // écriture de la ligne dans le fichier 
              png_write_row(png_ptr, line); 
         } 
         delete[] line; 
          
         png_write_end(png_ptr, png_info); 
          
         png_destroy_write_struct(&png_ptr, &png_info); 
         fclose(file); 
         return true; 
    }
    La partie en gras est la conversion des pixels en RGB (ou BGR, je l'ignore) pour que la libpng fasse ça correctement .
    (j'ai laissé tout le code tel quel, mais beaucoup ne devrait pas t'intéresser)
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre à l'essai
    Inscrit en
    Juin 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    mercii Bousk
    je vais adapter ton code a ma situation et voir
    mercii encore

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Empecher Lecture d'Enregistrement en cours de Modification
    Par toony dans le forum Administration
    Réponses: 4
    Dernier message: 09/12/2009, 11h18
  2. Enregistrement d'image dans Interbase(champ Blob)
    Par the watcher dans le forum Bases de données
    Réponses: 1
    Dernier message: 07/06/2005, 12h33
  3. [GLScene] Comment enregistrer une image au format TGA
    Par Invité dans le forum API, COM et SDKs
    Réponses: 1
    Dernier message: 27/05/2005, 15h12
  4. Enregistrer une image
    Par N@sH dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 04/05/2005, 10h07
  5. enregistrer une image et un identifiant
    Par dosach dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 18/03/2004, 17h18

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