KOMMANDOInternetMatérielsPrestationsNEXTSTEP·OPENSTEPFormationsPartenairesRéférences



[Banniere]


/* Ameliorations futures :
   grouper les differents elements de l'entete dans une structure (plus simple a manipuler pour les entrees/sorties) */

/* Compression depuis une image au format RGB */

/* Structure du fichier genere :
 signature sur 8 octets (identifiant sur 4 caracteres "CPII", numero de version sur 3 caracteres 000-999 et caractere nul)
 largeur sur 4 octets
 hauteur sur 4 octets
 longueur compressee maximale sur 4 octets
 zone libre pour usage futur sur 12 octets
 palette sur 4 x 256 = 1024 octets (fixe) ; 4e octet de chaque couleur (celui de poids fort) reserve pour usage futur (pour l'instant a 0xff)
 index de toutes les lignes sur (hauteur + 1) x 4 octets (la derniere valeur permet de calculer la taille compressee de la derniere ligne de l'image)
 chaque ligne est ensuite codee sur largeur x 1 octet (index dans la palette) puis compressee
*/

/* La compilation ressemble a :
  gcc -O3 -DHAVE_UNISTD_H -DUSE_MMAP -o rgb2cpii rgb2cpii.c -lz
  strip rgb2cpii
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zlib.h>

#define LARGEUR_MIN 500
#define HAUTEUR_MIN 500

char numeroEncre (long *palette, char rouge, char vert, char bleu);

void afficheUtilisation (const char *application)
{
    printf ("Usage : %s image_RGB largeur hauteur image_compressée\n", application);
}

int main(int argc, char *argv[])
{
    if (argc != 5)
    {
        afficheUtilisation (argv[0]);
    }
    else
    {
        char signature[8] = "CPII001";  /* Compressed Paletted Indexed Image */
        long largeur = atoi (argv[2]),
             hauteur = atoi (argv[3]);

        if (largeur >= LARGEUR_MIN && hauteur >= HAUTEUR_MIN)
        {
            static const char *maVersion = ZLIB_VERSION;
            unsigned long palette[256],
                          *tableLignes;
            Byte *donneesCompressees,
                 *donneesDecompressees;
            FILE *source,
                 *destination;

            if (zlibVersion ()[0] != maVersion[0]) 
            {
                fprintf (stderr, "Version de librairie zlib inutilisable\n");
                exit (1);
            } 
            else 
            {
                if (strcmp (zlibVersion (), ZLIB_VERSION) != 0) 
                {
                    fprintf (stderr, "Attention : versions différentes de librairies zlib\n");
                }
            }
            tableLignes = (unsigned long *) malloc ((hauteur + 1) * sizeof (long));
            donneesCompressees = (Byte *) malloc ((long) (largeur * 1.1 + 12) * sizeof (Byte));
            donneesDecompressees = (Byte *) malloc (largeur * sizeof (Byte));

            if (tableLignes == Z_NULL || donneesCompressees == Z_NULL || donneesDecompressees == Z_NULL)
            {
                fprintf (stderr, "mémoire insuffisante\n");
                exit (1);
            }
            if ((source = fopen (argv[1], "rb")) && (destination = fopen (argv[4], "wb")))
            {
                long ligne,
                     longueurMaximale = 0;
                unsigned long deplacement = 0;

                if (fseek (destination, sizeof (signature) + (6 + 256 + hauteur + 1) * sizeof (long), SEEK_SET) == -1)
                {
                    fprintf (stderr, "réservation de la zone d'entête impossible\n");
                    exit (1);
                }
                memset (palette, 0, 256 * sizeof (long));

                for (ligne = 0; ligne < hauteur; ligne++)
                {
                    long numeroPixel,
                         longueurCompressee = (long) largeur * 1.1 + 12;
                    int  erreur;

                    for (numeroPixel = 0; numeroPixel < largeur; numeroPixel++)
                    {
                        char pixel[6];

                        if (fread (pixel, sizeof (pixel), 1, source) == 1)
                        {
                            donneesDecompressees[numeroPixel] = numeroEncre (palette, pixel[0], pixel[2], pixel[4]);
                        }
                        else
                        {
                            fprintf (stderr, "données manquantes\n");
                            exit (1);
                        }
                    }
                    if ((erreur = compress2 (donneesCompressees, &longueurCompressee, donneesDecompressees, largeur, Z_BEST_COMPRESSION)) != Z_OK)
                    {
                        fprintf (stderr, "une erreur de compression est intervenue ligne %d (code %d)\n", ligne, erreur);
                        exit (1);
                    }
                    if (fwrite (donneesCompressees, sizeof (char), longueurCompressee, destination) != longueurCompressee)
                    {
                        fprintf (stderr, "écriture impossible\n");
                        exit (1);
                    }
                    if (longueurCompressee > longueurMaximale)
                    {
                        longueurMaximale = longueurCompressee;
                    }
                    tableLignes[ligne] = deplacement;
                    deplacement += longueurCompressee;
                }
                tableLignes[ligne] = deplacement;
                fclose (source);
                rewind (destination);

                if ((fwrite (signature, sizeof (signature), 1, destination) == 1) && (fwrite (&hauteur, sizeof (long), 1, destination) == 1) && (fwrite (&largeur, sizeof (long), 1, destination) == 1) && (fwrite (&longueurMaximale, sizeof (long), 1, destination) == 1) && (fwrite (palette, sizeof (long), 3, destination) == 3) && (fwrite (palette, sizeof (long), 256, destination) == 256) && (fwrite (tableLignes, sizeof (long), hauteur + 1, destination) == (hauteur + 1)))
                {
                    fclose (destination);
                    printf ("Image compressée !\n");
                }
                else
                {
                    fclose (destination);
                    fprintf (stderr, "écriture entête impossible\n");
                    unlink (argv[4]);
                }
                free (tableLignes);
                free (donneesCompressees);
                free (donneesDecompressees);
            }
            else
            {
                fprintf (stderr, "ouverture %s ou création %s impossible\n", argv[1], argv[4]);
            }
        }
        else
        {
            fprintf (stderr, "largeur ou hauteur trop faible pour justifier une compression (%d minimum)\n", LARGEUR_MIN);
        }
    }
    exit(0);
    return 0;
}

char numeroEncre (long *palette, char rouge, char vert, char bleu)
{
    long couleur = (255 << 24) | (rouge << 16) | (vert << 8) | bleu,
         couleurTestee;
    int indice;

    for (indice = 0; indice < 256; indice++)
    {
        if (couleurTestee = palette[indice])
        {
            if (couleur == couleurTestee)
            {
                return (char) indice;
            }
        }
        else
        {
            break;
        }
    }
    if (indice == 256)
    {
        static int excesCouleursAffiche = 0;

        if (! excesCouleursAffiche)
        {
            printf ("Il y a plus de 256 couleurs différentes dans l'image\n");
            excesCouleursAffiche = 1;
        }
        return (char) 255;
    }
    palette[indice] = couleur;
    return (char) indice;
}

[petit logo]

     Chercher sur ce site

Une remarque, une question ou une suggestion ? Merci de nous écrire à info@kommando.com.

KOMMANDO
Siège social : 3, rue Jacques Daguerre · 95370 MONTIGNY lès CORMEILLES
Tél : 33 (0)6 60 60 10 48 · Fax : 33 (0)6 61 60 10 48 · info@kommando.com



KOMMANDOInternetMatérielsPrestationsNEXTSTEP·OPENSTEPFormationsPartenairesRéférences