| KOMMANDO | Internet | Matériels | Prestations | NEXTSTEP·OPENSTEP | Formations | Partenaires | Références |
/* 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;
}
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
| KOMMANDO | Internet | Matériels | Prestations | NEXTSTEP·OPENSTEP | Formations | Partenaires | Références |