#include <stdio.h>
#include <stdlib.h>
#include "cimage.h"
#define ENTIERE 0
#define QUINCONCE 1
#define NMAX 120
/* type Image : comporte un champ echelle
(seuls les points de coordonnees multiples de echelle appartiennent a l'image)
un champ type_grille
(QUINCONCE ou ENTIERE)
*/
typedef struct {
int nrow;
int ncol;
int nb_coul;
int type_grille;
int echelle;
unsigned char* gray;
} Cimageprov;
/*****************************************/
/* Fonction de lecture d'une image de type PGM */
/*****************************************/
FILE* lire_image(char* name, int* width, int* height, int* nb_coul,
Cimageprov* image, int* pos) {
long nb_lu;
char ce_char;
FILE* fid;
char start_of_line;
char magic [3];
int in_header = 1;
fid = fopen (name, "r");
if (((int) fid) == -1) {
printf ("Pb fopen\n");
return (0);
}
nb_lu = fread (magic, 1, 3, fid);
while (in_header) {
nb_lu = fread (&start_of_line, 1,
1, fid);
if (start_of_line != '#') {
printf ("in header
no more #\n");
fseek (fid, -1, SEEK_CUR);
break;
}
else {
printf ("in header
lire comment\n");
nb_lu = fread (&ce_char,
1, 1, fid);
while ((ce_char !=
10) && (ce_char !=13))
nb_lu = fread (&ce_char, 1, 1, fid);
nb_lu = fread (&ce_char,
1, 1, fid);
if ((ce_char != 10)
&& (ce_char !=13))
fseek (fid, -1, SEEK_CUR);
printf ("in header
fin lire comment\n");
}
}
printf ("FIN comment\n");
fscanf (fid, "%d", width);
printf ("Lecture width ok\n");
fscanf (fid, "%d", height);
printf ("Lecture h ok\n");
fscanf (fid, "%d", nb_coul);
printf ("Lecture coul ok\n");
printf ("%d %d %d \n", *height, *width, *nb_coul);
fread (&ce_char, 1, 1, fid);
*pos = ftell (fid);
image->gray = malloc ((*height) * (*width));
nb_lu = fread (image->gray, *width, *height, fid);
image->nrow = *height;
image->ncol = *width;
image->nb_coul = *nb_coul;
return (fid);
}
/************************************************/
/* Fonction de copie d'une variable image dans une autre */
/* (formatte de plus une image type QUINCONCE pour */
/* affichage en mettant a blanc les points hors treillis)
*/
/************************************************/
void sauver_image_niveau_n (Cimageprov* image, Cimageprov* image_niveau_n)
{
int i,j;
image_niveau_n->ncol = image->ncol/image->echelle;
image_niveau_n->nrow = image->nrow/image->echelle;
image_niveau_n->gray = malloc (image_niveau_n->ncol *
image_niveau_n->nrow);
if (image->type_grille == QUINCONCE)
for (i = 0; i < image->ncol; i+=image->echelle)
for (j = 0; j <
image->nrow; j+=image->echelle)
if (((i+j) / image->echelle) % 2 != 0)
image->gray [i+j*image->ncol] = 255;
for (i = 0; i < image->ncol/image->echelle; i++) {
for (j = 0; j < image->nrow/image->echelle;
j++) {
image_niveau_n->gray
[i+ j*image_niveau_n->ncol] =
image->gray [image->echelle*i+ j*image->ncol*image->echelle];
}
}
}
/**************************************************/
/* Passage de Xn a Xn+1
*/
/* le resultat est mis dans la meme variable image
*/
/**************************************************/
void calcul_niveau_suivant (Cimageprov* image) {
long k;
int i,j;
if (image->type_grille == ENTIERE) {
for (i = 0; i < image->ncol; i+=image->echelle)
{
for (j = 0; j <
image->nrow; j+=image->echelle) {
if (((i+j) / image->echelle) % 2 == 0) {
k = i+j*image->ncol;
if ((i>=image->echelle) && (image->gray [k-image->echelle]<image->gray
[k]))
image->gray [k] = image->gray [k-image->echelle];
if ((i<image->ncol-image->echelle) && (image->gray [k+image->echelle]<image->gray
[k]))
image->gray [k] = image->gray [k+image->echelle];
if ((j>= image->echelle) && (image->gray [k-image->echelle*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [k-image->echelle*image->ncol];
if ((j<image->nrow-image->echelle) && (image->gray [k+image->echelle*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [k+image->echelle*image->ncol];
}
}
}
image->type_grille = QUINCONCE;
} else {
for (i = 0; i < image->ncol; i+=2*image->echelle)
{
for (j = 0; j <
image->nrow; j+=2*image->echelle) {
k = i+j*image->ncol;
if ((i>=image->echelle) && (j>=image->echelle) &&
(image->gray [i-image->echelle+ (j-image->echelle)*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [i-image->echelle+ (j-image->echelle)*image->ncol];
if ((i>=image->echelle) && (j<image->nrow-image->echelle) &&
(image->gray [i-image->echelle+ (j+image->echelle)*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [i-image->echelle+ (j+image->echelle)*image->ncol];
if ((i<image->ncol-image->echelle) && (j>=image->echelle) &&
(image->gray [i+image->echelle+ (j-image->echelle)*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [i+image->echelle+ (j-image->echelle)*image->ncol];
if ((i<image->ncol-image->echelle) && (j<image->nrow-image->echelle)
&&
(image->gray [i+image->echelle+ (j+image->echelle)*image->ncol]<image->gray
[k]))
image->gray [k] = image->gray [i+image->echelle+ (j+image->echelle)*image->ncol];
}
}
image->echelle = 2*image->echelle;
image->type_grille = ENTIERE;
}
}
/*************************************************/
/* Operateur de synthese : passage Xn a Xn-1
*/
/*************************************************/
void calcul_niveau_prec (Cimageprov* image) {
int max,i,j;
long k;
if (image->type_grille == QUINCONCE) {
for (i = 0; i < image->ncol; i+=image->echelle)
{
for (j = 0; j <
image->nrow; j+=image->echelle) {
if (((i+j)/image->echelle) % 2 != 0) {
max = 0;
k = i+j*image->ncol;
if ((i>=image->echelle) && (image->gray [k-image->echelle]>max))
max = image->gray [k-image->echelle];
if ((i<image->ncol-image->echelle) && (image->gray [k+image->echelle]>max))
max = image->gray [k+image->echelle];
if ((j>= image->echelle) && (image->gray [k-image->echelle*image->ncol]>max))
max = image->gray [k-image->echelle*image->ncol];
if ((j<image->nrow-image->echelle) && (image->gray [k+image->echelle*image->ncol]>max))
max = image->gray [k+image->echelle*image->ncol];
image->gray [k] = max;
}
}
}
image->type_grille = ENTIERE;
} else {
image->echelle = image->echelle/2;
for (i = 0; i < image->ncol; i+=image->echelle)
{
for (j = 0; j <
image->nrow; j+=image->echelle) {
if ((((i/image->echelle) % 2) != 0) && (((j/image->echelle) % 2)
!= 0)) {
max = 0;
k = i+j*image->ncol;
if ((i>=image->echelle) && (j>=image->echelle) &&
(image->gray [i-image->echelle+ (j-image->echelle)*image->ncol]>max))
max = image->gray [i-image->echelle+ (j-image->echelle)*image->ncol];
if ((i>=image->echelle) && (j<image->nrow-image->echelle) &&
(image->gray [i-image->echelle+ (j+image->echelle)*image->ncol]>max))
max = image->gray [i-image->echelle+ (j+image->echelle)*image->ncol];
if ((i<image->ncol-image->echelle) && (j>=image->echelle) &&
(image->gray [i+image->echelle+ (j-image->echelle)*image->ncol]>max))
max = image->gray [i+image->echelle+ (j-image->echelle)*image->ncol];
if ((i<image->ncol-image->echelle) && (j<image->nrow-image->echelle)
&&
(image->gray [i+image->echelle+ (j+image->echelle)*image->ncol]>max))
max = image->gray [i+image->echelle+ (j+image->echelle)*image->ncol];
image->gray [k] = max;
}
}
}
image->type_grille = QUINCONCE;
}
}
int main () {
int height;
int width;
int nb_coul;
int pos;
int delta;
char ce_char;
Cimageprov image_in;
Cimageprov image_courante;
Cimageprov image_niveau_n;
int k,n,i,j;
long nb_lu, nb_ec;
char name[30];
char name_out[3];
FILE* fid_in; /* image originale
*/
FILE* fid_out; /* approximation
*/
FILE* fid_diff; /* erreur de l'approximation
*/
FILE* fid_xn; /* image niveau
n */
printf ("Entrez le nom de l'image : \n");
scanf("%s", name);
printf ("Entrez un nb pair de niveaux de la pyramide :\n");
scanf("%d", &n);
if (n > NMAX) {
printf ("Nb trop grand !\n");
return 0;
}
fid_in = lire_image (name, &width, &height,
&nb_coul, &image_in, &pos);
fid_out = fopen ("approx.pgm", "w");
if (((int) fid_out) == -1) {
printf ("Pb fopen\n");
return (0);
}
fid_diff = fopen ("diff.pgm", "w");
if (((int) fid_diff) == -1) {
printf ("Pb fopen\n");
return (0);
}
fid_xn = fopen ("xn.pgm", "w");
if (((int) fid_xn) == -1) {
printf ("Pb fopen\n");
return (0);
}
image_courante.gray = malloc (image_in.ncol*image_in.nrow);
image_courante.ncol = image_in.ncol;
image_courante.nrow = image_in.nrow;
image_courante.echelle = 1;
image_courante.type_grille = ENTIERE;
for (k = 0; k < image_in.ncol*image_in.nrow; k++)
image_courante.gray [k] = image_in.gray
[k];
for (i=0; i<n; i++) {
calcul_niveau_suivant (&image_courante);
}
sauver_image_niveau_n (&image_courante, &image_niveau_n);
fprintf (fid_xn, "P5\n# CREATOR : FIFI\n%d %d\n255\n",
image_niveau_n.ncol,
image_niveau_n.nrow, fid_xn);
nb_ec = fwrite (image_niveau_n.gray, image_niveau_n.ncol,
image_niveau_n.nrow, fid_xn);
for (i=0; i<n; i++) {
calcul_niveau_prec (&image_courante);
}
fseek (fid_in, 0, SEEK_SET);
for (k = 1; k <= pos; k++) {
nb_lu = fread (&ce_char, 1, 1, fid_in);
nb_ec = fwrite (&ce_char, 1, 1,
fid_out);
}
nb_ec = fwrite (image_courante.gray, width, height, fid_out);
for (k = 0; k < width*height; k++)
image_courante.gray [k] = image_in.gray
[k] - image_courante.gray [k];
fseek (fid_in, 0, SEEK_SET);
for (k = 1; k <= pos; k++) {
nb_lu = fread (&ce_char, 1, 1, fid_in);
nb_ec = fwrite (&ce_char, 1, 1,
fid_diff);
}
nb_ec = fwrite (image_courante.gray, width, height, fid_diff);
fclose (fid_in);
fclose (fid_out);
fclose (fid_diff);
free (image_courante.gray);
return (0);
}