Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Défis] #12 : zDessin

    5 juin 2012 à 21:06:42

    Ce mois-ci, nous vous proposons un exercice un peu plus compliqué. Il consistera à créer son propre format *.bmp, et à développer une bibliothèque pour pouvoir le manipuler.

    Dans un premier temps, vous mettrez en place le format, puis vous créerez quelques fonctions pour pouvoir y dessiner (traçage de segments, cercles, etc.). Dans un deuxième temps, vous développerez un système d'exportation vers de vrais formats *.bmp (il y en a plusieurs). Dans un troisième temps, vous créerez un lecteur de votre format, à l'aide de la bibliothèque graphique SDL par exemple.

    Si vous souhaitez plus de renseignements sur les défis, rendez vous sur le topic de recensement des défis, vous y trouverez également les règles principales.

    zDessin


    Nous allons donc commencer par définir notre format bmp : le zBMP.
    • Header : entête contenant des informations utiles
    • Palette : couleurs utilisées par les pixels
    • Pixels : pixels utilisés pour le dessin


    OFFSET   TAILLE  DESCRIPTION
    0        4       Nombre magique du fichier à définir. (zBMP)
    4        2       Nombre de pixels en largeur.
    6        2       Nombre de pixels en hauteur.
    8        2       Nombre de bits par pixels (position dans la palette).
    10       2       Nombre de bits pour une composante de couleur.
    12       4       Nombre de couleurs dans la palette


    La palette est un ensemble de couleurs.

    Une couleur est un ensemble de 4 composantes : Red, Green, Blue et Alpha
    (rouge, vert, bleu et opacité)

    La partie pixels va donc indiquer, pour chaque pixel, la position de leur couleur dans la palette

    Voici donc un exemple de fichier résultat :

    Si je veux faire une image de 16x14 avec pour couleurs :

    Couleur R G B A
    Transparent 255 255 255 0
    Rouge 198 0 0 255
    Marron 143 60 31 255
    Bleu 102 102 243 255
    Mauve 247 214 181 255
    Jaune 248 251 30 255
    Noir 0 0 0 255


    Alors, je pourrais avoir une entête/palette, qui ressemble à ça :

    .   FICHIER      --          LEGENDE
    
      7A 42 6D 70    -- "zBmp"
      00 10 00 0E    -- Dimensions : 16 x 14
      00 04 00 08    -- 4 bits/pixel, 8 bits/composante
      00 00 00 07    -- 7 couleurs
    
      FF FF FF 00    -- 0) blanc transparent
      C6 00 00 FF    -- 1) rouge
      8F 3C 1F FF    -- 2) marron
      66 66 F3 FF    -- 3) bleu
      F7 D6 B5 FF    -- 4) mauve
      F8 FB 1E FF    -- 5) jaune
      00 00 00 FF    -- 6) noir


    Si, de plus, le contenu ressemblait à ça :
    0 0 0 0 0 1 1 1 1 1 0 0 4 4 4 0
    0 0 0 0 1 1 1 1 1 1 1 1 1 4 4 0
    0 0 0 0 2 2 2 4 4 6 4 0 1 1 1 0
    0 0 0 2 4 2 4 4 4 6 4 4 4 1 1 0
    0 0 0 2 4 2 2 4 4 4 6 4 4 4 1 0
    0 0 0 2 2 4 4 4 4 6 6 6 6 1 0 0
    0 0 0 0 0 4 4 4 4 4 4 4 1 1 0 0
    0 0 1 1 1 1 3 1 1 1 3 1 1 0 0 2
    4 4 1 1 1 1 1 3 1 1 1 3 0 0 2 2
    4 4 4 1 1 1 1 3 3 3 3 5 3 3 2 2
    0 4 0 0 3 1 3 3 5 3 3 3 3 3 2 2
    0 0 2 2 2 3 3 3 3 3 3 3 3 3 2 2
    0 2 2 2 3 3 3 3 3 3 0 0 0 0 0 0
    0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0


    Alors mon image serait :
    Image utilisateur
    Image finale (agrandie : un rectangle pour chaque pixel)


    NB : En retouchant le fichier, on peut avoir une jolie surprise

    Rechercher/Remplacer :

    Couleur numero caractere
    Rouge 1 ;
    Marron 2 X
    Bleu 3 =
    Mauve 4 .
    Jaune 5 -
    Noir 6 #
    Transparent 0 (espace)

    _______________________
    
              ; ; ; ; ;     . . .   
            ; ; ; ; ; ; ; ; ; . .   
            X X X . . # .   ; ; ;   
          X . X . . . # . . . ; ;   
          X . X X . . . # . . . ;   
          X X . . . . # # # # ;     
              . . . . . . . ; ;     
        ; ; ; ; = ; ; ; = ; ;     X 
    . . ; ; ; ; ; = ; ; ; =     X X 
    . . . ; ; ; ; = = = = - = = X X 
      .     = ; = = - = = = = = X X 
        X X X = = = = = = = = = X X 
      X X X = = = = = =             
      X X                           
    
    _______________________


    Étape 1 : Lecture/Écriture du fichier


    Estimation de la difficulté : médium

    Pour ce niveau, nous vous proposons de lire et d'écrire un fichier de ce format.
    Aucun affichage du dessin ne vous sera encore demandé.

    Il vous faudra cependant coder l'équivalent de ces fonctions :

    Fonction loadZBmp(path) retourne Image
    {Charge une image à partir de son fichier}
    Paramètres
        (I) path : Chaine {Chemin du fichier}
    
    Fonction loadZBmpOn(img, path) retourne Image
    {Charge une image dans img à partir de son fichier}
    Paramètres
        (O) img  : Image  {Image à charger}
        (I) path : Chaine {Chemin du fichier}
    
    Fonction getPixel(x, y, img) retourne Pixel
    {Récupère un pixel selon sa position}
    Paramètres
        (I) x, y : entiers {coordonées du pixel}
        (I) img  : Image   {Image en question}
     
    Procédure saveZBmp(img, path)
    {Sauvegarde l'image}
    Paramètres
        (I) img  : Image  {Image à sauvegarder}
        (I) path : Chaine {Chemin du fichier}
     
    Procédure freeZBmp(img)
    {Libère l'image}
    Paramètres
        (I/O) img : Image  {Image à libérer}


    Étape 2 : Ajout de fonctions graphiques


    Estimation de la difficulté : variable.

    Ce niveau vous propose de créer des fonctions permettant de tracer des formes simples, comme la ligne, le rectangle, le cercle, l'ellipse, etc..

    Le but étant d'obtenir l'algorithme le plus efficace possible.
    Vous pourrez aussi créer des fonctions de remplissage.

    Étape 3 : Exportation


    Estimation de la difficulté : difficile

    Ce niveau va vous proposer d’exporter notre petit format zBMP en un vrai de vrai : le format BMP. Pourquoi celui-là ? Parce que c’est l’un des formats réels les plus simples. Cependant, la partie est quand même loin d’être gagnée d’avance, vous allez voir.

    Il s’agit ici de coder une fonction ressemblant à celle-ci :
    Procédure saveBMP(img, path)
    {Sauvegarde l'image au format BMP}
    Paramètres
        (I) img  : Image  {Image à sauvegarder}
        (I) path : Chaine {Chemin du fichier}


    En fait, il existe plusieurs versions du format BMP, pas entièrement compatibles entre elles, ce qui le rend compliqué à gérer. On va donc se fixer sur une de ces versions, la 3ème de Microsoft (coquettement nommée BITMAPINFOHEADER). C’est la version la plus courante, et celle qui correspond le mieux aux fonctionnalités de notre format zBMP.

    Voici les champs que vous avez à remplir :
    Résumé du format Microsoft BMP V3
    Adresse
    (hexa)
    Taille
    (en octets)
    Champ Valeur Commentaire
    Entête du fichier (14 octets)
    00 2 Nombre magique "BM" "BM" en ASCII vaut 0x424D.
    02 4 taille du fichier
    (en octets)
    - -
    06 4 réservé 0 -
    0A 4 adresse de l’image - L’adresse dans le fichier où commence le tableau de pixels (le “bitmap”) composant l’image elle-même.
    Entête de l’image (40 octets)
    0E 4 taille de ce header
    (en octets)
    40 -
    12 4 largeur - Contrairement aux autres champs, ceux-ci sont des entiers signés (voir explications en-dessous de ce tableau).
    16 4 hauteur -
    1A 2 nombre de plans 1 -
    1C 2 « profondeur », c’est-à-dire
    nombre de bits par pixel
    1, 4, 8, 16, 24 ou 32 Correspond à 4 × notre nombre de semi-octets par pixel.
    1E 4 compression Mettez 0 ou 3. Mettez 3 si la profondeur vaut 16 ou 32 (indique qu’on utilise un masque binaire, cf ci-dessous), 0 sinon.
    22 4 taille de l’image
    (en octets)
    - Taille du “bitmap”.
    26 4 résolution horizontale
    (en px/m)
    - Contrairement aux autres champs, ceux-ci sont des entiers signés.

    Si vous ne savez pas quoi mettre, mettez 3780 pour les deux.
    2A 4 résolution verticale
    (en px-m)
    -
    2E 4 nombre de couleurs - Indique le nombre de couleurs dans la palette. Vous pouvez mettre 0 pour indiquer la valeur maximale dépendant de la profondeur n (2n).
    32 4 nombre de couleurs importantes Mettez 0. -
    Palette
    (optionnelle, taille variable)

    La palette liste les couleurs utilisées dans l’image. Il s’agit d’un tableau de couleurs.
    Chaque couleur est codée sur 4 octets par ses composantes RVBA (rouge, vert, bleu, alpha), chacune sur un octet. Un pixel est codé par l’indice de sa couleur dans la palette.

    La palette n’est obligatoire que pour une profondeur inférieure à 16, et ne doit pas être présente sinon (la couleur étant codée directement dans le pixel).
    Le nombre de couleurs dans la palette dépend de la profondeur n : sa valeur maximale est de 2n. Ce nombre peut cependant être plus petit, il est réglé par le champ correspondant de l’entête.
    Masques binaires
    (optionnels, 12 octets)

    Cette section remplace la palette dans certains cas, si la compression vaut 3. Elle contient trois données, chacune sur 4 octets : les masques binaires pour chacune des composantes rouge, verte et bleue (dans cet ordre).
    Ces masques binaires sont utilisés lorsque la profondeur vaut 16 ou 32. Ils indiquent quels bits du pixel codent chaque composante de couleur.

    Si vous ne comprenez pas, contentez-vous de mettre ces valeurs en fonction de la valeur de la profondeur :
    • Si elle vaut 16, mettez 0xF8000000, 0x007C0000, 0x0001F000 (dans l’ordre RVB). Chaque composante sera alors codée par 5 bits du pixel, et le 16ème bit sera inutilisé.
    • Si elle vaut 32, mettez 0xFF000000, 0x00FF0000, 0x0000FF00. Chaque composante sera alors codée par 8 bits du pixel (soit un octet), et le 4ème octet sera inutilisé.

    Bitmap
    (taille variable)

    Il s’agit du contenu de l’image lui-même, pixel par pixel et ligne par ligne.
    Chaque pixel utilise le nombre de bits spécifié dans l’entête.
    • Si ce nombre est inférieur à 16, il s’agit de l’indice permettant de retrouver sa couleur dans la palette.
    • S’il vaut 16 ou 32, on utilise des masques binaires, comme détaillé ci-dessus.
    • S’il vaut 24, on stocke directement la valeur de la couleur avec ses composantes RVB.
    Les lignes doivent utiliser un nombre d’octets multiple de 4. Si ce n’est pas le cas, on complète avec des octets nuls.


    Toutes les données sont des entiers non signés, sauf les dimensions (et la résolution) qui sont signées. De plus, les pixels de l’image se lisent de bas en haut (!) et de gauche à droite. Une valeur négative pour la hauteur indique qu’il faut lire l’image dans le sens contraire (de haut en bas), et idem pour la largeur (de droite à gauche).

    Enfin, dernier point important : toutes les données doivent être représentées en little-endian ! Et quand je dis « toutes », c’est toutes. Même le nombre magique doit être écrit « à l’envers » (0x4D42 au lieu de 0x424D, donc le M avant le B). Et aussi les composantes de couleurs : en réalité, si elles sont chacune sur un octet, elles devront être dans cet ordre : bleu, vert, rouge, alpha.

    Au fait, vous avez vu que les couleurs peuvent avoir une composante alpha ; elle doit cependant toujours valoir 0 car le BMP ne gère pas la transparence.


    Vous voyez, il y a du boulot ! Pour tester votre programme, vous pouvez tenter d’ouvrir l’image BMP que vous aurez générée avec un logiciel gérant les BMP ; si ça marche, vous pouvez être fier.

    Étape 4 : Affichage


    Estimation de la difficulté : facile

    Ce niveau-ci, indépendant du niveau 3, demande à réaliser un lecteur de .zBmp
    Vous pourrez, par exemple, utiliser la SDL.

    Aller plus loin


    On peut travailler sur les images de plusieurs manières que ce soit :
    Compressions, Traçages/Remplissages, Exports : vous pouvez faire encore pas mal de choses pour vous exercer !

    Vous pouvez même compiler ce projet en une bibliothèque dynamique, si vous le souhaitez !

    Si vous le souhaitez, vous pouvez aussi recréer un paint !
    En plus, vous devriez pouvoir faire un générateur d'ASCII Art ;)

    _________________________

    Cet exercice à été posté ici car il peut être codé à l'aide du C.

    Cependant, il est réalisable par tout langage permettant la manipulation de fichiers et qui dispose d'une bibliothèque graphique.

    Si vous souhaitez utiliser le langage algorithmique ou du pseudo code, les fonctions que vous pouvez utiliser sont les suivantes :

    Fichiers
    Fonction loadFile(path) retourne Fichier
    {Charge un fichier en mémoire}
    Paramètres
        (I) path   : Chaine {Chemin du fichier}
    
    Fonction checkFile(file) retourne Booleen
    {Indique si le fichier file est bien chargé}
    Paramètres
        (I) file : Fichier {Le fichier}
    
    Procédure putByte(file, byte)
    {Ecrit un octet dans le fichier file}
    Paramètres
        (I) file : Fichier {Le fichier chargé}
        (I) byte : Octet {L'octet à écrire}
    
    Fonction readByte(file) retourne Octet
    {Lit un octet dans le fichier file}
    Paramètres
        (I) file : Fichier {Le fichier chargé}
    
    Procedure rwdFile(file)
    {Rembobine le fichier}
    Paramètres
        (I) file : Fichier {le fichier chargé}
    
    Procedure closeFile(file)
    {Ferme le fichier}
    Paramètres
        (I) file : Fichier {le fichier chargé}
    
    Procedure delFile(path)
    {Supprime le fichier}
    Paramètres
        (I) path : Chaine {le fichier à supprimer}
    
    Procedure creatFile(path)
    {Creer un fichier}
    Paramètres
        (I) path : Chaine {le fichier à creer}


    Graphique:
    Fonction createWindow(w, h) retourne Surface
    {Cree une fenetre}
    Paramètres
        w : Entier {La largeur}
        h : Entier {La hauteur}
    
    Procedure freeWindow(screen)
    {Libere une fenetre}
    Paramètres
        screen : Surface {La fenetre}
    
    Fonction createSurface(w, h) retourne Surface
    {Cree une surface}
    Paramètres
        w : Entier {La largeur}
        h : Entier {La hauteur}
    
    Procedure freeSurface(surface)
    {Libere une surface}
    Paramètres
        surface : Surface {La surface}
    
    Fonction checkSurface(surface) retourne Booleen
    {Verifie si une surface/fenetre a bien été chargée}
    Paramètres
        surface : Surface {La surface à vérifier}
    
    Procedure blitSurface(dst, x, y, src, xx, yy, w, h)
    {Colle une surface sur une autre}
    Paramètres
        dst          : Surface {La destination}
        x, y         : Entiers {Endroit où coller}
        src          : Surface {La surface à coller}
        xx, yy, w, h : Entiers {La portion de surface à coller}
    
    Procedure paintSurface(surface, x, y, r, g, b)
    {Change la couleur d'un pixel d'une surface}
    Paramètres
        surface : Surface {La surface}
        x, y    : Entiers {La position du pixel}
        r, g, b : Entiers {La nouvelle couleur}
    
    Procedure display(screen)
    {Met à jour la fenetre donnée}
    Paramètres
        screen : Surface {la fenetre}


    Si vous avez besoin de fonctions supplémentaires que vous ne pouvez pas coder, indiquez leurs spécifications avant (par exemple, si vous voulez faire un paint)
    • Partager sur Facebook
    • Partager sur Twitter
      10 juin 2012 à 14:34:18

      Bonjour.

      Alors que je me lance dans l'étape 1 surgit cette question : N'est-ce pas bizarre ce format avec à la fois une palette et un canal alpha ?
      • Partager sur Facebook
      • Partager sur Twitter

      Developer / MA Computer Science 👨‍💻 👨‍🔬 — bitbucket.org/OPiMedia/workspace/repositorieswww.opimedia.be

        10 juin 2012 à 14:41:27

        Ce qui est bizarre c'est que le format BMP à une composante alpha mais ne gère pas la transparence ^^
        Le fait qu'il y ait à la fois une palette et une composante alpha n'est pas si étrange
        • Partager sur Facebook
        • Partager sur Twitter
        perror(const char * str); will save your life !
          10 juin 2012 à 14:46:14

          c'est pas clair les 2 dernières entrées de l'entête (enfin surtout l'avant dernière). En reprenant ton exemple : 00 04 00 08    -- 4 bits/pixel, 8 bits/composante
          Pour la composante, comme ça vaut 8, ça veut dire que l'image est en 32 bits (RGBA) ? D'ailleurs, pourquoi 2 octets pour cette valeur, alors que 3 bits suffisent¹ ?
          Pour les bits/pixel, ton « 4 » signifie que chaque octet du fichier contient en vérité 2 pixels ?

          ¹: voire un octet tout simplement, j'ai rarement vu des images avec plus de 8 bits/composante
          • Partager sur Facebook
          • Partager sur Twitter
            10 juin 2012 à 14:56:58

            L'image est effectivement en 32 bits
            Je n'ai pas compris la deuxième partie de la question..

            En fait c'est 4 bits pour l'indice de la couleur dans la palette.
            Effectivement, 3 bits auraient suffit, mais je voulais faire un truc rond (pour l'exemple)
            • Partager sur Facebook
            • Partager sur Twitter
            perror(const char * str); will save your life !
              10 juin 2012 à 15:03:02

              Citation : SylafrsOne

              Je n'ai pas compris la deuxième partie de la question...
              En fait c'est 4 bits pour l'indice de la couleur dans la palette.


              doit-on en comprendre, si on lit 3 octets d'avoir les indices de 6 pixels :
              0x11112222 0x33334444 0x55556666
              ?
              • Partager sur Facebook
              • Partager sur Twitter
                10 juin 2012 à 15:32:00

                Bonjour,

                Quelques petites questions, même si je ne pense pas avoir le temps de faire cet exo.

                Il est dit :
                8        2       Nombre de bits par pixels (indice dans la palette).
                10       2       Nombre de bits pour une composante de couleur.
                
                - "indice dans la palette" ? Qu'est ce que ça veut dire ?
                - Le nombre de bits pour une composante couleur, je doute fortement que quelqu'un s'amuse à prendre moins de 8 bits, surtout qu'on ne détaille pas comment traiter ce cas.
                - Par contre, un palette c'est utile jusqu'à 8BPP, au delà, ça devient inutile/très gros. L'idée serait qu'en 16/24/32 BPP, on stocke directement la couleur. Il faudrait préciser dans l'énoncé comment stocker le 16 bits (RGB en 555, 565...). Et peut-être rajouter un champ pour donner un index ou les composantes de la couleur transparente si nécessaire.
                - Pour la palette, il manque une info : le nombre de couleurs présentes. Dans l'exemple, comment savoir qu'il n'y a que 7 couleurs à la lecture ? Ou faut-il stocker le nombre de couleurs max présentes dans la profondeur en cours ? (16c pour 4BPP, 256c pour 8BPP).
                - Dans la palette, il y a une composante "opacité", gérer une opacité couleur par couleur me semble délicat (surtout pour faire l'édition de la palette qui va avec). J'en reviens à mon idée première de rajouter un champ pour la couleur de transparence dans le header, si c'est bien le but recherché.
                - Dans l'exemple présenté, si je ne m'abuse, le format des datas du mario correspondrait à du 8BPP. En 4BPP, ce serait plutôt : 0x00 0x00 0x01 0x11 0x11 0x00 0x44 0x40, etc... Non ?
                (- Faut-il gérer du padding en fin de ligne ? Càd, si dans la ligne décrite ci-dessus, la largeur du dessin était de 17 pixels, faudrait-il commencer la ligne suivant sur un octet ? Et en fin de graph ? Compléter avec des 0 si nécessaire ?).

                Voilà, je pense que ça pourrait aider les participants de préciser ces points.

                Clément.
                • Partager sur Facebook
                • Partager sur Twitter
                  10 juin 2012 à 16:12:36

                  @ minirop :
                  Oui c'est ça.
                  le 1111, 2222, 3333, 4444 seraient les positions de la couleur des pixels dans la palette.

                  @ joe :

                  Par indice je voulais dire position.
                  Typiquement, 2 serait la troisième couleur située dans la palette.
                  Si on met 4 dans le header, on aura jusqu'à 16 couleurs différentes

                  J'ai effectivement oublié le nombre de couleurs Oo, désolé, je vais rajouter ça (sur 4 octets ?).

                  Pour le mario, chaque chiffre correspond à 4 bits, donc, oui, si on regroupe les octets, il faut regrouper les chiffres deux par deux.

                  Pour le padding.
                  Etant donné que l'on a spécifié les dimensions de l'image, je ne vois pas trop pourquoi remplir le reste de 0..
                  • Partager sur Facebook
                  • Partager sur Twitter
                  perror(const char * str); will save your life !
                    10 juin 2012 à 17:39:00

                    Citation : minirop

                    c'est pas clair les 2 dernières entrées de l'entête (enfin surtout l'avant dernière). En reprenant ton exemple : 00 04 00 08    -- 4 bits/pixel, 8 bits/composante
                    Pour la composante, comme ça vaut 8, ça veut dire que l'image est en 32 bits (RGBA) ?
                    Pour les bits/pixel, ton « 4 » signifie que chaque octet du fichier contient en vérité 2 pixels ?


                    C'est vrai que c'est pas clair du tout. Ces deux entrées font redondance, j'ai l'impression. On a toujours une palette ou pas ? Ces champs de

                    Citation : minirop

                    Pour la composante, comme ça vaut 8, ça veut dire que l'image est en 32 bits (RGBA) ? D'ailleurs, pourquoi 2 octets pour cette valeur, alors que 3 bits suffisent¹ ?
                    ¹: voire un octet tout simplement, j'ai rarement vu des images avec plus de 8 bits/composante


                    Effectivement, mais c'est plus simple et plus pratique d'avoir 2 octets (comme pour le vrai BMP).

                    Citation : SylafrsOne

                    Pour le padding.
                    Etant donné que l'on a spécifié les dimensions de l'image, je ne vois pas trop pourquoi remplir le reste de 0..


                    C'est ce qu'on fait dans le vrai format BMP. Au cas où, ça ne coûte pas énormément et ça peut se révéler pratique après.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 juin 2012 à 18:25:37

                      Cette exercice me semble dure...
                      j'aimerai savoir ce qu'il faut connaitre pour pouvoir le faire svp.
                      Faut il connaitre le traitement des bits??
                      Merci
                      • Partager sur Facebook
                      • Partager sur Twitter
                        10 juin 2012 à 21:47:49

                        1/ Savoir utiliser les fichiers en mode binaire.
                        2/ Savoir utiliser les tableaux, et au mieux, les structures.
                        3/ Savoir utiliser les opérateurs bits à bits est aussi conseillé
                        • Partager sur Facebook
                        • Partager sur Twitter
                        perror(const char * str); will save your life !
                          10 juin 2012 à 22:29:57

                          Ok merci je lisse ma place :)
                          • Partager sur Facebook
                          • Partager sur Twitter
                            11 juin 2012 à 23:49:03

                            Voilà où j'en suis, étape 1.
                            J'ai changé quelques noms de fonctions, de façon à rester cohérent avec celles que j'ai ajoutées.

                            Fichier include zbmp.h :
                            /*
                             * zbmp.h
                             *
                             * (c) Olivier Pirson --- DragonSoft
                             * http://www.opimedia.be/DS/
                             *
                             * Débuté le 10 juin 2012
                             * v.00.01.00 --- 11 juin 2012
                             *
                             * Copyright (C) 2012 Olivier Pirson
                             *
                             * This program is free software: you can redistribute it and/or modify
                             * it under the terms of the GNU General Public License as published by
                             * the Free Software Foundation, either version 3 of the License, or
                             * (at your option) any later version.
                             *
                             * This program is distributed in the hope that it will be useful,
                             * but WITHOUT ANY WARRANTY; without even the implied warranty of
                             * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
                             * GNU General Public License for more details.
                             *
                             * You should have received a copy of the GNU General Public License
                             * along with this program. If not, see <http://www.gnu.org/licenses/>.
                             */
                            #define ZBMP_VERSION "v.00.00.00 --- 2012 June 11"
                            
                            
                            /** \mainpage zBMP
                            <h1>
                              Implémentation du format zBMP
                              défini par le
                              <a class="net" href="http://www.siteduzero.com/forum-83-774823-p1-defis-12-zdessin.html" target="_blank"><i>[Défis] #12 : zDessin</i></a>
                              (<a class="net" href="http://www.siteduzero.com/" target="_blank">Le Site du Zéro</a>)
                            </h1>
                            
                            <div>
                              &copy; Olivier <span style="font-variant:small-caps">Pirson</span>
                              &ndash;&nbsp;<a class="net" href="http://www.gnu.org/licenses/gpl.html" target="_blank">GPL &ndash; GNU General Public License</a>
                            </div>
                            
                            <div>
                              <h2>Description du format de fichier zBMP</h2>
                              <table>
                                <tr><th>Offset</th><th>Taille</th><th>Description</th></tr>
                                <tr><th style="background-color:#86b5e2"></th><th style="background-color:#86b5e2">16</th><th style="background-color:#86b5e2">Header</th></tr>
                                <tr><td>0</td><td>4</td><td>ZBMP_MAGIC_NUMBER, les 4 octets "zBmp"</td></tr>
                                <tr><td>4</td><td>2</td><td>zbmp_pixels_t.width, largeur en pixels</td></tr>
                                <tr><td>6</td><td>2</td><td>zbmp_pixels_t.height, hauteur en pixels</td></tr>
                                <tr><td>8</td><td>2</td><td>zbmp_pixels_t.bits_by_pixel, nombre de bits par pixels (taille de l'index de la couleur dans la palette)</td></tr>
                                <tr><td>10</td><td>2</td><td>zbmp_palette_t.bits_by_channel, nombre de bits chaque canal d'une couleur</td></tr>
                                <tr><td>12</td><td>4</td><td>zbmp_palette_t.nb_colors, nombre de couleurs dans la palette</td></tr>
                            
                                <tr><th style="background-color:#86b5e2"></th><th style="background-color:#86b5e2">zbmp_palette_t.data_size</th><th style="background-color:#86b5e2">Palette de couleurs</th></tr>
                                <tr><td>16</td><td>zbmp_palette_t.bits_by_channel/8*4</td><td>couleur d'indice 0 : canaux rouge, vert, bleu, alpha</td></tr>
                                <tr><td>16 + zbmp_palette_t.bits_by_channel/8*4</td><td>zbmp_palette_t.bits_by_channel/8*4</td><td>couleur d'indice 1 : canaux rouge, vert, bleu, alpha</td></tr>
                                <tr><td>16 + zbmp_palette_t.bits_by_channel/8*4*2</td><td>zbmp_palette_t.bits_by_channel/8*4</td><td>couleur d'indice 2 : canaux rouge, vert, bleu, alpha</td></tr>
                                <tr><td>16 + zbmp_palette_t.bits_by_channel/8*4*3</td><td>zbmp_palette_t.bits_by_channel/8*4</td><td>couleur d'indice 3 : canaux rouge, vert, bleu, alpha</td></tr>
                                <tr><td>...</td><td>...</td><td>...</td></tr>
                                <tr><td>16 + zbmp_palette_t.bits_by_channel/8*4*(zbmp_palette_t.nb_colors - 1)</td><td>zbmp_palette_t.bits_by_channel/8*4</td><td>couleur d'indice (zbmp_palette_t.nb_colors - 1) : canaux rouge, vert, bleu, alpha</td></tr>
                            
                                <tr><th style="background-color:#86b5e2"></th><th style="background-color:#86b5e2">zbmp_pixels_t.data_size</th><th style="background-color:#86b5e2">Grille de pixels</th></tr>
                                <tr><td>16 + zbmp_palette_t.data_size</td><td>zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>ligne des pixels de coordonnées (..., 0)</td></tr>
                                <tr><td>16 + zbmp_palette_t.data_size + zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>ligne des pixels de coordonnées (..., 1)</td></tr>
                                <tr><td>16 + zbmp_palette_t.data_size + zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width*2</td><td>zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>ligne des pixels de coordonnées (..., 2)</td></tr>
                                <tr><td>16 + zbmp_palette_t.data_size + zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width*3</td><td>zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>ligne des pixels de coordonnées (..., 3)</td></tr>
                                <tr><td>...</td><td>...</td><td>...</td></tr>
                                <tr><td>16 + zbmp_palette_t.data_size + zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width*(zbmp_pixels_t.height - 1)</td><td>zbmp_pixels_t.bits_by_pixel/8*zbmp_pixels_t.width</td><td>ligne des pixels de coordonnées (..., zbmp_pixels_t.height - 1)</td></tr>
                            
                                <tr><th style="background-color:#86b5e2"></th><th style="background-color:#86b5e2"></th><th style="background-color:#86b5e2">Fin du fichier</th></tr>
                                <tr><td>16 + zbmp_palette_t.data_size + zbmp_pixels_t.data_size</td><td></td><td>EOF</td></tr>
                              </table>
                            </div>
                            
                            <div align="right">
                              &copy; Olivier <span style="font-variant:small-caps">Pirson</span>\n
                              <a class="mail" href="mailto:olivier_pirson_opi@yahoo.fr?subject=[zBMP]"><tt>olivier_pirson_opi@yahoo.fr</tt></a>\n
                              <a class="net" href="http://www.opimedia.be/DS/" target="_blank"><tt>http://www.opimedia.be/DS/</tt></a>
                            </div>
                            */
                            
                            #include <stdbool.h>
                            #include <stdio.h>
                            #include <stdlib.h>
                            
                            
                            
                            /*******************
                             * Macro constante *
                             *******************/
                            /**
                             * Taille du header en octets
                             */
                            #define ZBMP_HEADER_SIZE 16
                            
                            
                            
                            /*************
                             * Constante *
                             *************/
                            /**
                             * Nombre magique débutant les fichiers images de format zBMP (== "zBmp")
                             */
                            extern const unsigned char *ZBMP_MAGIC_NUMBER;
                            
                            
                            
                            /*********
                             * Types *
                             *********/
                            /**
                             * Palette de couleurs
                             */
                            typedef struct {
                              /** Nombre de bits par canal (== 8) */
                              unsigned short bits_by_channel;
                            
                              /** Nombre de couleurs */
                              unsigned int nb_colors;
                            
                              /** Pointeur vers les couleurs (chacune composée de 4 canals : rouge, vert, bleu et alpha) */
                              unsigned char *data_ptr;
                            
                              /** == nb_colors*4*bits_by_channel/8 */
                              unsigned int data_size;
                            } zbmp_palette_t;
                            
                            
                            /**
                             * Grille de pixels
                             */
                            typedef struct {
                              /** Largeur (doit être paire si bits_by_pixel == 4) */
                              unsigned short width;
                            
                              /** Hauteur */
                              unsigned short height;
                            
                              /* Nombre de bits par pixel (== 4 ou 8) */
                              unsigned short bits_by_pixel;
                            
                              /** Pointeur vers les pixels */
                              unsigned char *data_ptr;
                            
                              /** == width*height*bits_by_pixel/8 arrondi à l'unité supérieure */
                              unsigned int data_size;
                            } zbmp_pixels_t;
                            
                            
                            /**
                             * Image, composée d'une palette et d'une grille de pixels
                             */
                            typedef struct {
                              /** La palette de couleurs */
                              zbmp_palette_t palette;
                            
                              /** La grille de pixels */
                              zbmp_pixels_t pixels;
                            } zbmp_img_t;
                            
                            
                            
                            /**************
                             * Prototypes *
                             **************/
                            /**
                             * Envoie sur stream les size premiers octets pointés par data_ptr
                             *
                             * Pre: stream: flux accessible en écriture
                             *      data_ptr: zone mémoire d'au-moins size octets
                             */
                            void zbmp_data_fprint(FILE *stream,
                                                  const unsigned char *data_ptr,
                                                  size_t size);
                            
                            
                            /**
                             * Envoie sur stream les valeurs hexadécimales des size premiers octets pointés par data_ptr,
                             * en les séparant par un espace
                             *
                             * Pre: stream: flux accessible en écriture
                             *      data_ptr: zone mémoire d'au-moins size octets
                             */
                            void zbmp_data_fprint_hex(FILE *stream,
                                                      const unsigned char *data_ptr,
                                                      size_t size);
                            
                            
                            
                            /**
                             * Crée et renvoie une image
                             * dont la palette contient nb_colors couleurs
                             *                          et chaque canal à une taille de bits_by_channel bits,
                             * avec une grille de width x height pixels
                             *                 dont chaque pixel à une taille de bits_by_pixel bits.
                             *
                             * La mémoire allouée doit être libérée par zbmp_img_free()
                             *
                             * Pre: bits_by_channel: 8
                             *      bits_by_pixel: 4 ou 8
                             *      width : doit être paire si bits_by_pixel == 4
                             */
                            zbmp_img_t zbmp_img_create(unsigned short bits_by_channel,
                                                       unsigned int nb_colors,
                                                       unsigned short bits_by_pixel,
                                                       unsigned short width,
                                                       unsigned short height);
                            
                            
                            /**
                             * Libère la mémoire allouée à l'image
                             * et initialise les données à une valeur nulle
                             *
                             * Pre: img_ptr: pointe vers une image valide
                             */
                            void zbmp_img_free(zbmp_img_t *img_ptr);
                            
                            
                            /**
                             * Envoie l'image img au format zBMP dans le flux stream
                             *
                             * Pre: stream: flux accessible en écriture
                             *      img: image valide
                             */
                            bool zbmp_img_fsave(FILE *stream,
                                                zbmp_img_t img);
                            
                            
                            /**
                             * Renvoie l'image chargée du fichier filename au format zBMP
                             *
                             * Si le fichier ne peut être ouvert ou si le format n'est pas reconnu
                             * alors renvoie une image vide
                             *
                             * Pre: filename: non NULL
                             */
                            zbmp_img_t zbmp_img_load(const char *filename);
                            
                            
                            /**
                             * Envoie sur stdout la palette puis la grille de pixels.
                             * Cf. zbmp_palette_print() et zbmp_pixels_print()
                             */
                            void zbmp_img_print(zbmp_img_t img,
                                                bool infos,
                                                const char *characters,
                                                char other);
                            
                            
                            /**
                             * Sauve l'image img au format zBMP dans le fichier de nom filename.
                             * Si le fichier existe déjà il est écrasé.
                             *
                             * Renvoie true en cas de succès,
                             *         false en cas d'échec
                             *
                             * Pre: img: image valide
                             *      filename: non NULL
                             */
                            bool zbmp_img_save(zbmp_img_t img,
                                               const char *filename);
                            
                            
                            
                            /**
                             * Crée et renvoie une palette de nb_colors couleurs
                             * dont chaque canal à une taille de bits_by_channel bits,
                             *
                             * La mémoire allouée doit être libérée par zbmp_palette_free()
                             *
                             * Pre: bits_by_channel: 8
                             */
                            zbmp_palette_t zbmp_palette_create(unsigned short bits_by_channel,
                                                               unsigned int nb_colors);
                            
                            
                            /**
                             * Libère la mémoire allouée à la palette
                             * et initialise les données à une valeur nulle
                             *
                             * Pre: palette_ptr: pointe vers une palette valide
                             */
                            void zbmp_palette_free(zbmp_palette_t *palette_ptr);
                            
                            
                            /**
                             * Envoie palette dans le flux stream
                             *
                             * Si infos alors commence par envoyer :
                             *   - palette.bits_by_channel
                             *   - palette.nb_colors
                             *
                             * Pre: stream: flux accessible en écriture
                             *      palette: palette valide
                             */
                            bool zbmp_palette_fsave(FILE *stream,
                                                    zbmp_palette_t palette,
                                                    bool infos);
                            
                            
                            /**
                             * Renvoie la valeur du canal alpha de la couleur d'indice index
                             *
                             * Pre: palette: palette valide
                             *      index < palette.nb_color
                             */
                            unsigned int zbmp_palette_get_alpha(zbmp_palette_t palette,
                                                                unsigned int index);
                            
                            
                            /**
                             * Renvoie la valeur du canal bleu de la couleur d'indice index
                             *
                             * Pre: palette: palette valide
                             *      index < palette.nb_color
                             */
                            unsigned int zbmp_palette_get_blue(zbmp_palette_t palette,
                                                               unsigned int index);
                            
                            
                            /**
                             * Renvoie la valeur du canal vert de la couleur d'indice index
                             *
                             * Pre: palette: palette valide
                             *      index < palette.nb_color
                             */
                            unsigned int zbmp_palette_get_green(zbmp_palette_t palette,
                                                                unsigned int index);
                            
                            
                            /**
                             * Renvoie la valeur du canal rouge de la couleur d'indice index
                             *
                             * Pre: palette: palette valide
                             *      index < palette.nb_color
                             */
                            unsigned int zbmp_palette_get_red(zbmp_palette_t palette,
                                                              unsigned int index);
                            
                            
                            /**
                             * Envoie la palette de façon lisible sur stdout.
                             *
                             * Chaque indice de couleur est associé à un caractère dans characters
                             *   ou au caractère other si characters est trop courte.
                             *
                             * Si infos alors commence par envoyer
                             *   - palette.bits_by_channel
                             *   - palette.nb_colors
                             *
                             * Pre: palette: palette valide
                             *      characters: NULL ou string
                             */
                            void zbmp_palette_print(zbmp_palette_t palette,
                                                    bool infos,
                                                    const char *characters,
                                                    char other);
                            
                            
                            /**
                             * Fixe la valeur des canaux à (red, gree, blue, alpha)) de la couleur d'indice index
                             *
                             * Pre: palette_ptr: pointe vers une palette valide
                             *      palette_ptr->bits_by_channel == 8
                             */
                            void zbmp_palette_set_color(zbmp_palette_t *palette_ptr,
                                                        unsigned int index,
                                                        unsigned int red,
                                                        unsigned int green,
                                                        unsigned int blue,
                                                        unsigned int alpha);
                            
                            
                            
                            /**
                             * Crée et renvoie une grille de width x height pixels
                             * dont chaque pixel à une taille de bits_by_pixel bits.
                             *
                             * La mémoire allouée doit être libérée par zbmp_pixels_free()
                             *
                             * Pre: bits_by_pixel: 4 ou 8
                             *      width : doit être paire si bits_by_pixel == 4
                             */
                            zbmp_pixels_t zbmp_pixels_create(unsigned short bits_by_pixel,
                                                             unsigned short width,
                                                             unsigned short height);
                            
                            
                            /**
                             * Libère la mémoire allouée à la grille
                             * et initialise les données à une valeur nulle
                             *
                             * Pre: pixels_ptr: pointe vers une grille valide
                             */
                            void zbmp_pixels_free(zbmp_pixels_t *pixels_ptr);
                            
                            
                            /**
                             * Envoie pixels dans le flux stream
                             *
                             * Si infos alors commence par envoyer :
                             *   - pixels.width
                             *   - pixels.height
                             *   - pixels.bits_by_pixel
                             *
                             * Pre: stream: flux accessible en écriture
                             *      pixels: grille valide
                             */
                            bool zbmp_pixels_fsave(FILE *stream,
                                                   zbmp_pixels_t pixels,
                                                   bool infos);
                            
                            
                            /**
                             * Renvoie l'indice de la couleur du pixel de coordonnée (x, y)
                             *
                             * Pre: pixels: grille valide
                             *      x < pixels.width
                             *      y < pixels.height
                             */
                            unsigned int zbmp_pixels_get_pixel(zbmp_pixels_t pixels,
                                                               unsigned short x,
                                                               unsigned short y);
                            
                            
                            /**
                             * Si characters != NULL
                             * alors envoie la grille de façon lisible sur stdout
                             *   (chaque indice de couleur est associé à un caractère dans characters
                             *    ou au caractère other si characters est trop courte),
                             * sinon envoie la grille sur stdout.
                             *
                             * Va à la ligne en fin de chaque ligne de la grille.
                             *
                             * Si infos alors commence par envoyer
                             *   - pixels.width
                             *   - pixels.height
                             *   - pixels.bits_by_pixel
                             *
                             * Pre: pixels: palette valide
                             *      characters: NULL ou string
                             */
                            void zbmp_pixels_print(zbmp_pixels_t pixels,
                                                   bool infos,
                                                   const char *characters,
                                                   char other);
                            
                            
                            /**
                             * Fixe l'indice de la couleur du pixel de coordonnée (x, y) à la valeur index
                             *
                             * Pre: pixels_ptr: pointe vers une grille valide
                             *      x < pixels.width
                             *      y < pixels.height
                             */
                            void zbmp_pixels_set_pixel(zbmp_pixels_t *pixels_ptr,
                                                       unsigned short x,
                                                       unsigned short y,
                                                       unsigned int index);
                            


                            Fichier zbmp.c, qui implémente les fonctions :
                            /*
                              zbmp.c
                            
                              (c) Olivier Pirson --- DragonSoft
                              http://www.opimedia.be/DS/
                            */
                            #include "zbmp.h"
                            
                            #include <assert.h>
                            #include <stdio.h>
                            #include <string.h>
                            
                            
                            
                            /*************
                             * Constante *
                             *************/
                            const unsigned char *ZBMP_MAGIC_NUMBER = (const unsigned char *)"zBmp";
                            
                            
                            
                            /*************
                             * Fonctions *
                             *************/
                            void zbmp_data_fprint(FILE *stream,
                                                  const unsigned char *data_ptr,
                                                  size_t size) {
                              assert(data_ptr);
                              assert(sizeof(unsigned char) == 1);
                            
                              fwrite((const void *)data_ptr, size, 1, stream);
                            }
                            
                            
                            void zbmp_data_fprint_hex(FILE *stream,
                                                      const unsigned char *data_ptr,
                                                      size_t size) {
                              assert(data_ptr);
                              assert(sizeof(unsigned char) == 1);
                            
                              while ( size-- > 1 ) {
                                fprintf(stream, "%02x ", *(data_ptr++));
                              }
                              fprintf(stream, "%02x", *data_ptr);
                            }
                            
                            
                            zbmp_img_t zbmp_img_create(unsigned short bits_by_channel,
                                                       unsigned int nb_colors,
                                                       unsigned short bits_by_pixel,
                                                       unsigned short width,
                                                       unsigned short height) {
                              zbmp_img_t img;
                            
                              img.palette = zbmp_palette_create(bits_by_channel, nb_colors);
                              img.pixels = zbmp_pixels_create(bits_by_pixel, width, height);
                            
                              return img;
                            }
                            
                            
                            void zbmp_img_free(zbmp_img_t *img_ptr) {
                              assert(img_ptr);
                            
                              zbmp_palette_free(&img_ptr->palette);
                              zbmp_pixels_free(&img_ptr->pixels);
                            }
                            
                            
                            bool zbmp_img_fsave(FILE *stream,
                                                zbmp_img_t img) {
                              assert(stream);
                            
                              assert(sizeof(ZBMP_MAGIC_NUMBER) == 4);
                            
                              assert(sizeof(img.pixels.width) == 2);
                              assert(sizeof(img.pixels.height) == 2);
                              assert(sizeof(img.pixels.bits_by_pixel) == 2);
                            
                              assert(sizeof(img.palette.bits_by_channel) == 2);
                              assert(sizeof(img.palette.nb_colors) == 4);
                            
                              return ((fwrite(ZBMP_MAGIC_NUMBER, 4, 1, stream) == 1)
                            
                                      && (fputc(img.pixels.width >> 8, stream) != EOF)
                                      && (fputc(img.pixels.width & 0xff, stream) != EOF)
                            
                                      && (fputc(img.pixels.height >> 8, stream) != EOF)
                                      && (fputc(img.pixels.height & 0xff, stream) != EOF)
                            
                                      && (fputc(img.pixels.bits_by_pixel >> 8, stream) != EOF)
                                      && (fputc(img.pixels.bits_by_pixel & 0xff, stream) != EOF)
                            
                                      && (fputc(img.palette.bits_by_channel >> 8, stream) != EOF)
                                      && (fputc(img.palette.bits_by_channel & 0xff, stream) != EOF)
                            
                                      && (fputc(img.palette.nb_colors >> 24, stream) != EOF)
                                      && (fputc((img.palette.nb_colors >> 16) & 0xff, stream) != EOF)
                                      && (fputc((img.palette.nb_colors >> 8) & 0xff, stream) != EOF)
                                      && (fputc(img.palette.nb_colors & 0xff, stream) != EOF)
                            
                                      && zbmp_palette_fsave(stream, img.palette, false)
                                      && zbmp_pixels_fsave(stream, img.pixels, false));
                            }
                            
                            
                            zbmp_img_t zbmp_img_load(const char *filename) {
                              assert(filename);
                            
                              {
                                FILE *stream = fopen(filename, "rb");
                                zbmp_img_t img;
                            
                                if ( stream ) {
                                  unsigned char header[ZBMP_HEADER_SIZE];
                            
                                  if ( (fread(header, 16, 1, stream) == 1)
                                       && (strncmp((char *)header, (char *)ZBMP_MAGIC_NUMBER, 4) == 0) ) {
                                    unsigned short width = (header[4] << 8) | header[5];
                                    unsigned short height = (header[6] << 8) | header[7];
                                    unsigned short bits_by_pixel = (header[8] << 8) | header[9];
                            
                                    unsigned short bits_by_channel = (header[10] << 8) | header[11];
                                    unsigned int nb_colors = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15];
                            
                                    img = zbmp_img_create(bits_by_channel, nb_colors, bits_by_pixel, width, height);
                            
                                    if ( img.palette.data_ptr ) {
                                      if ( fread(img.palette.data_ptr, img.palette.data_size, 1, stream) != 1 ) {
                                        zbmp_palette_free(&img.palette);
                                      }
                                    }
                            
                                    if ( img.pixels.data_ptr ) {
                                      if ( fread(img.pixels.data_ptr, img.pixels.data_size, 1, stream) != 1 ) {
                                        zbmp_pixels_free(&img.pixels);
                                      }
                                    }
                            
                                    fclose(stream);
                            
                                    return img;
                                  }
                                }
                            
                                /* Fichier pas ouvrable ou format non reconnu */
                                fclose(stream);
                            
                                return zbmp_img_create(0, 0, 0, 0, 0);
                              }
                            }
                            
                            
                            void zbmp_img_print(zbmp_img_t img,
                                                bool infos,
                                                const char *characters,
                                                char other) {
                              zbmp_palette_print(img.palette, infos, characters, other);
                              zbmp_pixels_print(img.pixels, infos, characters, other);
                            }
                            
                            
                            bool zbmp_img_save(zbmp_img_t img,
                                               const char *filename) {
                              assert(filename);
                            
                              {
                                FILE *stream = fopen(filename, "wb");
                            
                                if ( stream ) {
                                  const bool SUCCESS = zbmp_img_fsave(stream, img);
                            
                                  return (fclose(stream) == 0) && SUCCESS;
                                }
                                else {
                                  return false;
                                }
                              }
                            }
                            
                            
                            zbmp_palette_t zbmp_palette_create(unsigned short bits_by_channel,
                                                               unsigned int nb_colors) {
                              zbmp_palette_t palette;
                            
                              if ( nb_colors ) {
                                assert(sizeof(unsigned char) == 1);
                            
                                assert(bits_by_channel == 8);
                                assert(nb_colors <= (1<<bits_by_channel));
                            
                                palette.bits_by_channel = bits_by_channel;
                                palette.nb_colors = nb_colors;
                            
                                palette.data_size = nb_colors*bits_by_channel/(8/4);
                            
                                palette.data_ptr = calloc(palette.data_size, 1);
                            
                                if ( palette.data_ptr ) {
                                  return palette;
                                }
                              }
                            
                              /* Palette vide ou échec de l'allocation mémoire */
                              palette.data_ptr = NULL;
                              zbmp_palette_free(&palette);
                            
                              return palette;
                            }
                            
                            
                            void zbmp_palette_free(zbmp_palette_t *palette_ptr) {
                              assert(palette_ptr);
                            
                              if ( palette_ptr->data_ptr ) {
                                free(palette_ptr->data_ptr);
                            
                                palette_ptr->data_ptr = NULL;
                              }
                            
                              palette_ptr->bits_by_channel = 0;
                              palette_ptr->nb_colors = 0;
                            
                              palette_ptr->data_size = 0;
                            }
                            
                            
                            bool zbmp_palette_fsave(FILE *stream,
                                                    zbmp_palette_t palette,
                                                    bool infos) {
                              assert(stream);
                              assert(palette.data_ptr);
                              assert(palette.data_size == palette.nb_colors*4*palette.bits_by_channel/8);
                            
                              if ( infos ) {
                                assert(sizeof(palette.bits_by_channel) == 2);
                                assert(sizeof(palette.nb_colors) == 4);
                            
                                if ( (fputc(palette.bits_by_channel >> 8, stream) == EOF)
                                     || (fputc(palette.bits_by_channel & 0xff, stream) == EOF)
                            
                                     || (fputc(palette.nb_colors >> 24, stream) == EOF)
                                     || (fputc((palette.nb_colors >> 16) & 0xff, stream) == EOF)
                                     || (fputc((palette.nb_colors >> 8) & 0xff, stream) == EOF)
                                     || (fputc(palette.nb_colors & 0xff, stream) == EOF) ) {
                                  return false;
                                }
                              }
                            
                              return (fwrite(palette.data_ptr, palette.data_size, 1, stream) == 1);
                            }
                            
                            
                            unsigned int zbmp_palette_get_alpha(zbmp_palette_t palette,
                                                                unsigned int index) {
                              assert(palette.bits_by_channel == 8);
                            
                              return *(palette.data_ptr + palette.bits_by_channel/8*(4*index + 3));
                            }
                            
                            
                            unsigned int zbmp_palette_get_blue(zbmp_palette_t palette,
                                                               unsigned int index) {
                              assert(palette.bits_by_channel == 8);
                            
                              return *(palette.data_ptr + palette.bits_by_channel/8*(4*index + 2));
                            }
                            
                            
                            unsigned int zbmp_palette_get_green(zbmp_palette_t palette,
                                                                unsigned int index) {
                              assert(palette.bits_by_channel == 8);
                            
                              return *(palette.data_ptr + palette.bits_by_channel/8*(4*index + 1));
                            }
                            
                            
                            unsigned int zbmp_palette_get_red(zbmp_palette_t palette,
                                                              unsigned int index) {
                              assert(palette.bits_by_channel == 8);
                            
                              return *(palette.data_ptr + palette.bits_by_channel/8*4*index);
                            }
                            
                            
                            void zbmp_palette_print(zbmp_palette_t palette,
                                                    bool infos,
                                                    const char *characters,
                                                    char other) {
                              if ( infos ) {
                                printf("Palette: %u bits by channel   %u nb colors\n",
                                       palette.bits_by_channel,
                                       palette.nb_colors);
                              }
                            
                              {
                                const size_t LEN = (characters
                                                    ? strlen(characters)
                                                    : 0);
                            
                                unsigned int i = 0;
                            
                                for ( ; i < palette.nb_colors; i++) {
                                  printf("%5u: %3u %3u %3u %3u   %c\n",
                                         i,
                                         zbmp_palette_get_red(palette, i),
                                         zbmp_palette_get_green(palette, i),
                                         zbmp_palette_get_blue(palette, i),
                                         zbmp_palette_get_alpha(palette, i),
                                         (i < LEN
                                          ? characters[i]
                                        : other));
                                }
                              }
                            }
                            
                            
                            void zbmp_palette_set_color(zbmp_palette_t *palette_ptr,
                                                        unsigned int index,
                                                        unsigned int red,
                                                        unsigned int green,
                                                        unsigned int blue,
                                                        unsigned int alpha) {
                              assert(palette_ptr);
                              assert(palette_ptr->bits_by_channel == 8);
                            
                              {
                                const unsigned int BYTES_BY_CHANNEL = palette_ptr->bits_by_channel/8;
                            
                                unsigned char *ptr = palette_ptr->data_ptr + BYTES_BY_CHANNEL*4*index;
                            
                                *ptr = red;
                            
                                ptr += BYTES_BY_CHANNEL;
                                *ptr = green;
                            
                                ptr += BYTES_BY_CHANNEL;
                                *ptr = blue;
                            
                                *(ptr + BYTES_BY_CHANNEL) = alpha;
                              }
                            }
                            
                            
                            zbmp_pixels_t zbmp_pixels_create(unsigned short bits_by_pixel,
                                                             unsigned short width,
                                                             unsigned short height) {
                              zbmp_pixels_t pixels;
                            
                              if ( width && height ) {
                                assert(sizeof(unsigned char)  == 1);
                            
                                assert((bits_by_pixel == 4) || (bits_by_pixel == 8));
                                assert((bits_by_pixel%2 == 0) || (bits_by_pixel != 4));
                            
                                pixels.width = width;
                                pixels.height = height;
                                pixels.bits_by_pixel = bits_by_pixel;
                            
                                pixels.data_size = width*height*bits_by_pixel;
                                pixels.data_size = pixels.data_size/8 + (pixels.data_size%8
                                                                         ? 1
                                                                         : 0);
                            
                                pixels.data_ptr = calloc(pixels.data_size, 1);
                            
                                if ( pixels.data_ptr ) {
                                  return pixels;
                                }
                              }
                            
                              /* Grille vide ou échec de l'allocation mémoire */
                              pixels.data_ptr = NULL;
                              zbmp_pixels_free(&pixels);
                            
                              return pixels;
                            }
                            
                            
                            void zbmp_pixels_free(zbmp_pixels_t *pixels_ptr) {
                              assert(pixels_ptr);
                            
                              if ( pixels_ptr->data_ptr ) {
                                free(pixels_ptr->data_ptr);
                            
                                pixels_ptr->data_ptr = NULL;
                              }
                            
                              pixels_ptr->width = 0;
                              pixels_ptr->height = 0;
                              pixels_ptr->bits_by_pixel = 0;
                            
                              pixels_ptr->data_size = 0;
                            }
                            
                            
                            bool zbmp_pixels_fsave(FILE *stream,
                                                   zbmp_pixels_t pixels,
                                                   bool infos) {
                              assert(stream);
                              assert(pixels.data_ptr);
                              assert(pixels.data_size == pixels.width*pixels.height*pixels.bits_by_pixel/8 + (pixels.width*pixels.height*pixels.bits_by_pixel%8
                                                                                                              ? 1
                                                                                                              : 0));
                            
                              if ( infos ) {
                                assert(sizeof(pixels.width) == 2);
                                assert(sizeof(pixels.height) == 2);
                                assert(sizeof(pixels.bits_by_pixel) == 2);
                            
                                if ( (fputc(pixels.width >> 8, stream) == EOF)
                                     || (fputc(pixels.width & 0xff, stream) == EOF)
                            
                                     || (fputc(pixels.height >> 8, stream) == EOF)
                                     || (fputc(pixels.height & 0xff, stream) == EOF)
                            
                                     || (fputc(pixels.bits_by_pixel >> 8, stream) == EOF)
                                     || (fputc(pixels.bits_by_pixel & 0xff, stream) == EOF) ) {
                                  return false;
                                }
                              }
                            
                              return (fwrite(pixels.data_ptr, pixels.data_size, 1, stream) == 1);
                            }
                            
                            
                            unsigned int zbmp_pixels_get_pixel(zbmp_pixels_t pixels,
                                                               unsigned short x,
                                                               unsigned short y) {
                              assert(sizeof(unsigned char) == 1);
                            
                              assert((pixels.bits_by_pixel == 4) || (pixels.bits_by_pixel == 8));
                            
                              if ( pixels.bits_by_pixel == 4 ) {
                                const unsigned int POS = y*pixels.width + x;
                                const unsigned char *const PTR = pixels.data_ptr + POS*pixels.bits_by_pixel/8;
                            
                                return (POS%2
                                        ? *PTR & 0xf
                                        : *PTR >> 4);
                              }
                              else {
                                return *(pixels.data_ptr + (y*pixels.width + x)*pixels.bits_by_pixel/8);
                              }
                            }
                            
                            
                            void zbmp_pixels_print(zbmp_pixels_t pixels,
                                                   bool infos,
                                                   const char *characters,
                                                   char other) {
                              if ( infos ) {
                                printf("Pixels %ux%u   %u bits by pixel\n",
                                       pixels.width,
                                       pixels.height,
                                       pixels.bits_by_pixel);
                              }
                            
                              {
                                const size_t LEN = (characters
                                                    ? strlen(characters)
                                                    : 0);
                            
                                unsigned int y = 0;
                            
                                for ( ; y < pixels.height; y++) {
                                  unsigned int x = 0;
                            
                                  for ( ; x < pixels.width; x++) {
                                    const unsigned int c = zbmp_pixels_get_pixel(pixels, x, y);
                            
                                    if ( characters ) {
                                      printf("%c", (c < LEN
                                                    ? characters[c]
                                                    : other));
                                    }
                                    else {
                                      printf("%02x ", c);
                                    }
                                  }
                                  puts("");
                                }
                              }
                            }
                            
                            
                            void zbmp_pixels_set_pixel(zbmp_pixels_t *pixels_ptr,
                                                       unsigned short x,
                                                       unsigned short y,
                                                       unsigned int index) {
                              assert(sizeof(unsigned char) == 1);
                            
                              assert(pixels_ptr);
                              assert((pixels_ptr->bits_by_pixel == 4) || (pixels_ptr->bits_by_pixel == 8));
                            
                              if ( pixels_ptr->bits_by_pixel == 4 ) {
                                const unsigned int POS = y*pixels_ptr->width + x;
                            
                                unsigned char *ptr = pixels_ptr->data_ptr + POS*pixels_ptr->bits_by_pixel/8;
                            
                                if ( POS%2 ) {
                                  *ptr &= 0xf0;
                                  *ptr |= 0xf & index;
                                }
                                else {
                                  *ptr &= 0x0f;
                                  *ptr |= (0xf & index) << 4;
                                }
                              }
                              else {
                                *(pixels_ptr->data_ptr + (y*pixels_ptr->width + x)*pixels_ptr->bits_by_pixel/8) = index;
                              }
                            }
                            


                            Fichier mario.c, qui teste les précédents avec l'exemple de l'image de Mario :
                            /*
                              mario.c
                            
                              (c) Olivier Pirson --- DragonSoft
                              http://www.opimedia.be/DS/
                            
                              Débuté le 10 juin 2012
                              v.00.01.00 --- 11 juin 2012
                            */
                            
                            #include <assert.h>
                            #include <stdlib.h>
                            #include <stdio.h>
                            #include <string.h>
                            
                            #include "zbmp.h"
                            
                            
                            
                            /***********************
                             * Fonctions d'exemple *
                             ***********************/
                            /**
                             * Rempli la palette avec la palette d'exemple pour l'image de Mario
                             * du défi http://www.siteduzero.com/forum-83-774823-p1-defis-12-zdessin.html
                             *
                             * Si raw alors place les valeurs directement
                             *        sinon utilise la fonction zbmp_palette_set_color()
                             *
                             * Pre: palette_ptr: pointe vers une palette valide d'au-moins 7 couleurs
                             *                   et de 8 bits par canal
                             */
                            void palette_mario7(zbmp_palette_t *palette_ptr, bool raw) {
                              assert(palette_ptr);
                              assert(palette_ptr->nb_colors >= 7);
                            
                              {
                                const unsigned char data[7][4] = {{255, 255, 255,   0},   /* transparent  */
                                                                  {198,   0,   0, 255},   /* rouge */
                                                                  {143,  60,  31, 255},   /* marron */
                                                                  {102, 102, 243, 255},   /* bleu */
                                                                  {247, 214, 181, 255},   /* mauve */
                                                                  {248, 251,  30, 255},   /* jaune */
                                                                  {  0,   0,   0, 255}};  /* noir */
                            
                                if ( raw ) {
                                  assert(palette_ptr->bits_by_channel == 8);
                            
                                  {
                                    unsigned int i = 0;
                                    unsigned char *ptr = palette_ptr->data_ptr;
                            
                                    for ( ; i < 7 ; i++) {
                                      unsigned int c = 0;
                            
                                      for ( ; c < 4 ; c++, ptr++) {
                                        *ptr = data[i][c];
                                      }
                                    }
                                  }
                                }
                                else {
                                  unsigned int i = 0;
                            
                                  for ( ; i < 7 ; i++) {
                                    zbmp_palette_set_color(palette_ptr, i, data[i][0], data[i][1], data[i][2], data[i][3]);
                                  }
                                }
                              }
                            }
                            
                            
                            /**
                             * Rempli la grille avec l'image de Mario
                             * du défi http://www.siteduzero.com/forum-83-774823-p1-defis-12-zdessin.html
                             *
                             * Si raw alors place les valeurs directement
                             *        sinon utilise la fonction zbmp_pixels_set_pixel()
                             *
                             * Pre: pixels_ptr: pointe vers une grille valide d'une taille au-moins de 16x14
                             *                  (si raw alors exactement 16 de largeur et 4 bits par pixel)
                             */
                            void pixels_mario16_14(zbmp_pixels_t *pixels_ptr, bool raw) {
                              assert(pixels_ptr);
                              assert(pixels_ptr->width >= 16);
                              assert(pixels_ptr->height >= 14);
                            
                              {
                                const unsigned char data[14][16] = {{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 4, 4, 4, 0},
                                                                    {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 0},
                                                                    {0, 0, 0, 0, 2, 2, 2, 4, 4, 6, 4, 0, 1, 1, 1, 0},
                                                                    {0, 0, 0, 2, 4, 2, 4, 4, 4, 6, 4, 4, 4, 1, 1, 0},
                                                                    {0, 0, 0, 2, 4, 2, 2, 4, 4, 4, 6, 4, 4, 4, 1, 0},
                                                                    {0, 0, 0, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 1, 0, 0},
                                                                    {0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 1, 1, 0, 0},
                                                                    {0, 0, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 0, 0, 2},
                                                                    {4, 4, 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 0, 0, 2, 2},
                                                                    {4, 4, 4, 1, 1, 1, 1, 3, 3, 3, 3, 5, 3, 3, 2, 2},
                                                                    {0, 4, 0, 0, 3, 1, 3, 3, 5, 3, 3, 3, 3, 3, 2, 2},
                                                                    {0, 0, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2},
                                                                    {0, 2, 2, 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0},
                                                                    {0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
                            
                                if ( raw ) {
                                  assert(pixels_ptr->bits_by_pixel == 4);
                                  assert(pixels_ptr->width == 16);
                                  assert(pixels_ptr->data_ptr);
                            
                                  {
                                    unsigned int y = 0;
                                    unsigned char *ptr = pixels_ptr->data_ptr;
                            
                                    for ( ; y < pixels_ptr->height ; y++) {
                                      unsigned int x = 0;
                            
                                      for ( ; x < pixels_ptr->width ; x += 2, ptr++) {
                                        *ptr = (data[y][x]<<4) | data[y][x + 1];
                                      }
                                    }
                                  }
                                }
                                else {
                                  unsigned int y = 0;
                            
                                  for ( ; y < pixels_ptr->height ; y++) {
                                    unsigned int x = 0;
                            
                                    for ( ; x < pixels_ptr->width ; x++) {
                                      zbmp_pixels_set_pixel(pixels_ptr, x, y, data[y][x]);
                                    }
                                  }
                                }
                              }
                            }
                            
                            
                            
                            /********
                             * Main *
                             ********/
                            int main(int argc,
                                     char *argv[]) {
                              zbmp_img_t
                                img,
                                img2;
                            
                              assert(sizeof(unsigned char)  == 1);
                              assert(sizeof(unsigned short) == 2);
                              assert(sizeof(unsigned int)   == 4);
                            
                              img = zbmp_img_create(8, 7,
                                                    4, 16, 14);
                            
                              palette_mario7(&img.palette, false);
                              pixels_mario16_14(&img.pixels, false);
                            
                              zbmp_img_print(img, true, " ;X=.-#", '?');
                            
                              puts("");
                            
                              zbmp_pixels_print(img.pixels, true, NULL, '?');
                            
                              printf("\nSave \"mario.zbmp\": %s\n", (zbmp_img_save(img, "mario.zbmp")
                                                                     ? "ok"
                                                                     : "failed!"));
                            
                              zbmp_img_free(&img);
                            
                            
                              img2 = zbmp_img_create(8, 7,
                                                     4, 16, 14);
                              img2 = zbmp_img_load("mario.zbmp");
                            
                              printf("\nSave \"mario2.zbmp\": %s\n", (zbmp_img_save(img2, "mario2.zbmp")
                                                                      ? "ok"
                                                                      : "failed!"));
                            
                              zbmp_img_free(&img2);
                            
                              return EXIT_SUCCESS;
                            }
                            


                            Fichier Makefile :
                            # (c) Olivier Pirson --- http://www.opimedia.be/ --- olivier_pirson_opi@yahoo.fr
                            # 11 juin 2012
                            
                            PROGS = mario
                            
                            
                            
                            .SUFFIXES:
                            .SUFFIXES:        .c .o
                            ###########
                            # Options #
                            ###########
                            CPP      = gcc
                            CPPFLAGS = #-DNDEBUG
                            
                            CC     = gcc
                            CFLAGS = -ansi -pedantic -Wall -g #-Winline -O3
                            
                            LD      = gcc
                            LDFLAGS = #-s -Llib
                            LIBS    =
                            
                            DOXYGEN = doxygen
                            RM      = rm -f
                            RMDIR   = rmdir
                            SHELL   = sh
                            
                            
                            # Pour Window$
                            EXE = .exe
                            
                            
                            
                            ###
                            # #
                            ###
                            .PHONY:        all doc
                            
                            all:        $(PROGS)
                            
                            doc:
                                    $(DOXYGEN) Doxyfile
                            
                            mario:        zbmp.o
                            
                            zbmp.o:        zbmp.h
                            
                            
                            
                            ##########
                            # Règles #
                            ##########
                            .PRECIOUS:        %.o
                            
                            %:        %.o
                                    $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
                            
                            %:        %.c
                                    $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
                            
                            %.o:        %.c
                                    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
                            
                            
                            
                            #############
                            # Nettoyage #
                            #############
                            .PHONY:        clean cleandoc distclean overclean
                            
                            clean:
                                    $(RM) *.o
                            
                            cleandoc:
                                            $(RM) -f html/search/*
                                            -$(RMDIR) html/search/
                                            $(RM) -f html/*
                                            -$(RMDIR) html
                            
                            distclean:        clean
                                            $(RM) mario.zbmp mario2.zbmp
                                            $(RM) $(addsuffix $(EXE),$(PROGS))
                            
                            overclean:        distclean cleandoc


                            C'est contraignant de ne pas pouvoir attacher un fichier archive avec les sources !

                            EDIT : J'ai ajouté le fichier Makefile.
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Developer / MA Computer Science 👨‍💻 👨‍🔬 — bitbucket.org/OPiMedia/workspace/repositorieswww.opimedia.be

                              12 juin 2012 à 19:09:36

                              Pour commencer, merci pour ta participation :)

                              Pour les projets, github est assez sympas, il permet de faire la colo syntaxique en ligne, et utilise git, un très bon gestionnaire de version (mateo en a fait un tuto)

                              Comme ça, on peut passer les archives simplement.
                              Ou alors on utilise pastebin ^^

                              Je n'ai pas le temps de lire le code en ce moment, je vais le lire plus tard :)
                              • Partager sur Facebook
                              • Partager sur Twitter
                              perror(const char * str); will save your life !
                                19 juin 2012 à 16:39:32

                                Je pense qu'il y a peu de contributeurs car le sujet est.. assez "complexe".

                                Je veux dire par là qu'on ne sait pas trop comment s'y prendre et qu'on sait pas comme un fichier .bmp est structuré (ou du moins on a que des bases mais qui nous servent pas trop pour commencer).

                                Ce qu'il faudrait, je pense, c'est prendre une image relativement petite (pourquoi pas un seul pixel ou deux ?), la décomposer en .bmp (ou la structurer), puis de faire notre image avec le format .zBmp

                                Cela nous donnerait une petite base pour savoir comment écrire une image, en .bmp par exemple.

                                Si cela est impossible et je le comprendrai (c'est chronophage d'écrire un mini-tutoriel), un petit lien vers un tuto montrant tout ça serait parfait ;)

                                ABE.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Anonyme
                                  19 juin 2012 à 20:46:23

                                  Je viens de me lancer même si je ne suis pas exactement le sujet : j'ai tout d'abord créé une sorte de mini-librairie (pas encore compilée en tant que telle pour l'instant) dont voici l'architecture :

                                  .
                                  ├── color.h
                                  ├── image.c
                                  ├── image.h
                                  ├── io
                                  │   ├── console.c
                                  │   └── console.h
                                  ├── main.c
                                  ├── palette.c
                                  └── palette.h
                                  
                                  1 directory, 8 files


                                  Comme vous pouvez le voire, j'ai construit le premier module d'export (io) pour la console histoire de vérifier si tout fonctionnait bien. Ça faisait extrêmement longtemps que j'avais fait du C et j'ai néanmoins réussi à me débrouiller avec les malloc et autres après une vite relecture du tutoriel.

                                  Tout est sous la forme de structures relativement simples mais structurées (j'avais pas prévu ce jeu de mot à la base). Cependant je rencontre un problème qui m'a l'air tout simple mais agaçant car je n'arrive pas à le résoudre après relecture du code.

                                  Lorsque je tente de modifier un pixel de mon image et que j'affiche celle-ci dans la console, j'obtient ceci :

                                  (255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)
                                  (255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)
                                  (255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)
                                  (255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)
                                  (255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)(255,0,0,0)


                                  Comme vous pouvez le constater, la modification que j'ai effectuée s'est appliquée à toute l'image au lieu d'un seul pixel ; ou peut-être que je me suis trompé dans la boucle d'affichage qui sait.
                                  D'ailleurs, le voici le code de la boucle d'affichage :

                                  #include "console.h"
                                  
                                  #include <stdio.h>
                                  
                                  void io_console_dump(image_t* image)
                                  {
                                      int x, y;
                                      for (y = 0; y < image->height; y++) {
                                          for (x = 0; x < image->width; x++) {
                                              color_t* pixel = image_pixel(image, x, y);
                                              printf("(%d,%d,%d,%d)", pixel->r, pixel->g, pixel->b, pixel->a);
                                          }
                                          printf("\n");
                                      }
                                  }
                                  

                                  Apparemment l'incrémentation fonctionne bien après un test de debug au printf abusif.
                                  Je planche peut-être sur une mauvaise implémentation de ma fonction image_pixel qui permet de récupérer un pointeur sur un pixel ; voici son implémentation :

                                  color_t* image_pixel(image_t* image, unsigned int x, unsigned int y)
                                  {
                                      return &image->palette->colors[image->pixels[x + image->width * y]];
                                  }
                                  

                                  Evidemment, afin de mieux cerner mon problème, je vous joins la représentation des deux structures image_t et palette_t :

                                  typedef struct {
                                      color_t* colors;
                                      unsigned int size;
                                  } palette_t;
                                  

                                  typedef struct {
                                      palette_t* palette;
                                      unsigned char* pixels;
                                  
                                      unsigned char width;
                                      unsigned char height;
                                  } image_t;
                                  

                                  La structure color_t se résumant à une simple structure avec les 4 attributs RGBA.

                                  Merci d'avance pour votre aide,
                                  MicroJoe.


                                  (En fait je ne vous l'ai pas dit, mais le prétexte de ma participation est de tester mon environnement de travail avant de me lancer dans un projet de domination du monde, muhaha :lol: ).
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    19 juin 2012 à 21:01:41

                                    Je n'ai pas vu d'erreur, peut-être dans le reste du code ?

                                    Je ne voyais pas le défi si complexe que ça oO
                                    (à la base, c'était pour les défis pour débutants !)
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    perror(const char * str); will save your life !
                                    Anonyme
                                      19 juin 2012 à 21:10:54

                                      AMHA ça reste faisable par des débutants, c'est juste qu'il faudrait rendre le sujet plus clair comme précisé précédemment. Par exemple, je n'ai toujours pas compris pourquoi tu nous demandais de préciser le nombre d'octets par pixels dans l'entête du format zBMP alors que tu nous imposes ensuite d'utiliser un format RGBA.

                                      Bon après on va pas se mentir non-plus, ça a plutôt l'air d'être un exercice pour des débutants « avancés ».
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 juin 2012 à 21:13:15

                                        Je me suis mal expliqué, mais c'est la taille maximale des indices dans la carte
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        perror(const char * str); will save your life !

                                        [Défis] #12 : zDessin

                                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                        • Editeur
                                        • Markdown