| KOMMANDO | Internet | Matériels | Prestations | NEXTSTEP·OPENSTEP | Formations | Partenaires | Références |
/* Decompression depuis image au format CPII */
/* La compilation ressemble a :
gcc -O3 -DHAVE_UNISTD_H -DUSE_MMAP -o cpii2rgb cpii2rgb.c -lz
strip cpii2rgb
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zlib.h>
#define LARGEUR_MIN 1
#define HAUTEUR_MIN 1
#define min(a,b) ((a) < (b) ? (a) : (b))
void developpeCouleurs (char *table);
void afficheUtilisation (const char *application)
{
fprintf (stderr, "Usage : %s image_compressée x y largeur hauteur [image_RGB]\n", application);
}
int main(int argc, char *argv[])
{
if ((argc != 6) && (argc != 7))
{
afficheUtilisation (argv[0]);
}
else
{
long xExtraction = atoi (argv[2]),
yExtraction = atoi (argv[3]),
largeurExtraction = atoi (argv[4]),
hauteurExtraction = atoi (argv[5]);
if (largeurExtraction >= LARGEUR_MIN && hauteurExtraction >= HAUTEUR_MIN)
{
static const char *maVersion = ZLIB_VERSION;
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");
}
}
if (argc == 7)
{
if (! (destination = fopen (argv[6], "wb")))
{
fprintf (stderr, "création %s impossible\n", argv[6]);
exit (1);
}
}
else
{
destination = stdout;
}
if (source = fopen (argv[1], "rb"))
{
char signature[8];
long largeur,
hauteur,
longueurMaximale;
char couleurs[256][6];
if ((fread (signature, sizeof (signature), 1, source) == 1) && (fread (&largeur, sizeof (long), 1, source) == 1) && (fread (&hauteur, sizeof (long), 1, source) == 1) && (fread (&longueurMaximale, sizeof (long), 1, source) == 1) && (fread (couleurs, sizeof (long), 3, source) == 3) && (fread (couleurs, sizeof (long), 256, source) == 256))
{
unsigned long *tableLignes;
Byte *donneesCompressees,
*donneesDecompressees;
if ((xExtraction >= largeur) || (yExtraction >= hauteur))
{
fprintf (stderr, "zone à extraire en dehors des limites de l'image\n");
exit (1);
}
largeurExtraction = min (largeurExtraction, largeur - xExtraction);
hauteurExtraction = min (hauteurExtraction, hauteur - yExtraction);
developpeCouleurs ((char *) couleurs);
tableLignes = (unsigned long *) malloc ((hauteurExtraction + 1) * sizeof (long));
donneesCompressees = (Byte *) malloc (longueurMaximale * 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 (fseek (source, sizeof (signature) + (6 + 256 + yExtraction) * sizeof (long), SEEK_SET) == -1)
{
fprintf (stderr, "erreur lors du déplacement dans l'index\n");
exit (1);
}
if (fread (tableLignes, sizeof (long), hauteurExtraction + 1, source) == (hauteurExtraction + 1))
{
if (fseek (source, sizeof (signature) + (6 + 256 + hauteur + 1) * sizeof (long) + tableLignes[0], SEEK_SET) == -1)
{
fprintf (stderr, "erreur lors du déplacement dans l'index\n");
exit (1);
}
else
{
long ligne;
for (ligne = 0; ligne < hauteurExtraction; ligne++)
{
long longueurCompressee = tableLignes[ligne + 1] - tableLignes[ligne],
longueurDecompressee = largeur,
numeroPixel;
int erreur;
if (fread (donneesCompressees, sizeof (Byte), longueurCompressee, source) != longueurCompressee)
{
fprintf (stderr, "données manquantes\n");
exit (1);
}
if (((erreur = uncompress (donneesDecompressees, &longueurDecompressee, donneesCompressees, longueurCompressee)) != Z_OK) || (longueurDecompressee != largeur))
{
fprintf (stderr, "une erreur de décompression est intervenue ligne %d (code %d)\n", ligne + yExtraction, erreur);
exit (1);
}
for (numeroPixel = xExtraction; numeroPixel < (xExtraction + largeurExtraction); numeroPixel++)
{
if (fwrite (&couleurs[donneesDecompressees[numeroPixel]], sizeof (char), 6, destination) != 6)
{
fprintf (stderr, "écriture impossible\n");
exit (1);
}
}
}
}
}
else
{
fprintf (stderr, "lecture de l'index des lignes à extraire impossible\n");
}
}
else
{
fprintf (stderr, "lecture de l'entête impossible\n");
}
fclose (source);
if (destination != stdout)
{
fclose (destination);
}
}
else
{
fprintf (stderr, "ouverture %s impossible\n", argv[1]);
}
}
else
{
fprintf (stderr, "largeur ou hauteur trop faible pour justifier une extraction (%d pixels au minimum)\n", LARGEUR_MIN);
}
}
exit(0);
return 0;
}
void developpeCouleurs (char *table)
{
int indice;
long *couleurs = (long *) table;
for (indice = 255; indice >= 0; indice--)
{
long couleur = couleurs[indice];
char rouge = (couleur >> 16) & 255,
vert = (couleur >> 8) & 255,
bleu = couleur & 255;
table[indice * 6 + 5] = table[indice * 6 + 4] = bleu;
table[indice * 6 + 3] = table[indice * 6 + 2] = vert;
table[indice * 6 + 1] = table[indice * 6 + 0] = rouge;
}
}
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 |