001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: 
005: #define ESC 27
006: 
007: FILE *get_rle_data(char *, int *, int *); // apre il file, controlla intestazione e restituisce file handler e risoluzione
008: unsigned char *read_rle(FILE*, int, int);
009: void check_rle_footer(FILE *);
010: void save_pgm(char *, unsigned char*, int, int);
011: 
012: int main(int argc, char **argv){
013: 
014:   char filename[1000];
015:  
016:   printf("Nome del file RLE da leggere: ");
017:   fscanf("%s", filename);
018: 
019:   int h,w;
020:   FILE *t = get_rle_data(filename, &w, &h);
021: 
022:   unsigned char *immagine = read_rle(t, w, h);
023: 
024:   check_rle_footer(t);
025: 
026: 
027:   printf("Nome del file PGM da scrivere: ");
028:   fscanf("%s", filename);
029: 
030:   save_pgm(filename, immagine, w, h);
031: 
032:   return 0;
033: }
034: 
035: FILE *get_rle_data(char *filename, int *w, int *h)
036: {
037: 
038:   // apro il file in lettura e modalita' binaria
039:   FILE *t=fopen(filename, "rb");
040:   if(!t)
041:   {
042:     perror("");
043:     exit(EXIT_FAILURE);
044:   }
045: 
046:   // leggo i primi tre byte e verifico
047:   int c;
048:   c = fgetc(t); // legge l'ESC
049:   if(c != ESC)
050:   {
051:     printf("Formato RLE non corretto, il primo byte non e' ESC (%u)\n", c);
052:     exit(EXIT_FAILURE);
053:   }
054:   c = fgetc(t); // legge la G
055:   if(c != 'G')
056:   {
057:     printf("Formato RLE non corretto, il secondo byte non e' 'G' (%u)\n", c);
058:     exit(EXIT_FAILURE);
059:   }  
060:   c = fgetc(t); // legge la risoluzione
061:   if(c != 'M' && c != 'H')
062:   {
063:     printf("Formato RLE non corretto, il terzo byte non e' 'M' o 'H' (%u)\n", c);
064:     exit(EXIT_FAILURE);
065:   }  
066: 
067:  
068:   switch(c)
069:   {
070:     case 'M':
071:       printf("File a risoluzione medium 128x96\n");
072:       *w = 128;
073:       *h = 96;
074:       break;
075:     case 'H':
076:       printf("File a risoluzione alta 256x192\n");
077:       *w = 256;
078:       *h = 192;
079:       break;
080:   }
081: 
082:   return t;
083: }
084: 
085: unsigned char *read_rle(FILE* f, int w, int h)
086: {
087:   // alloco spazio sufficiente per tutti i punti immagine
088:   unsigned char *img = malloc(sizeof(unsigned char)*w*h); 
089: 
090:   // lo uso per capire se sto leggendo quanti punti bianchi o quanti punti neri ho, lo inizializzo a 0
091:   // in quanto il primo punto e' sempre nero (ovvero 0)
092:   int color = 0; 
093:   // per scrivere nel buffer allocato uso questo indice
094:   int index = 0;
095: 
096:   unsigned char c;
097:   while(index < w*h)
098:   {
099:     // leggo un byte
100:     c = fgetc(f); 
101: 
102:     // sottraggo 32
103:     c = c - 32;
104: 
105:     for(int i = 0; i < c; ++i)
106:     {
107:       img[index] = color;
108:       ++index;
109:     }
110: 
111:     // commuto colore di scrittura
112:     color =  !color ? 255 : 0;
113: 
114:   }
115: 
116:   return img;
117: }
118: 
119: // legge gli ultimi tre byte del file e controlla
120: // siano corretti
121: void check_rle_footer(FILE *x)
122: {
123:   unsigned char c;
124: 
125:   c = fgetc(x);
126:   if(c != ESC)
127:   {
128:     printf("Formato RLE non corretto, il primo byte della coda non e' 27 (%u)\n", c);
129:     exit(EXIT_FAILURE);
130:   }
131:   c = fgetc(x);
132:   if(c != 'G')
133:   {
134:     printf("Formato RLE non corretto, il secondo byte della coda non e' 'G' (%u)\n", c);
135:     exit(EXIT_FAILURE);
136:   }
137:   c = fgetc(x);
138:   if(c != 'N')
139:   {
140:     printf("Formato RLE non corretto, il terzo byte della coda non e' 'N' (%u)\n", c);
141:     exit(EXIT_FAILURE);
142:   }
143: 
144:   fclose(x); // sono arrivato a fine file
145: }
146: 
147: void save_pgm(char *filename, unsigned char *buffer, int w, int h)
148: {
149:   FILE *p =fopen(filename, "wb");
150: 
151:   if(!p)
152:   {
153:     perror("");
154:     exit(EXIT_FAILURE);
155:   }
156: 
157:   //scrivo header PGM
158:   fprintf(p, "P5\n%d %d\n255\n", w, h);
159: 
160:   // scrivo sequenza punti
161:   fwrite(buffer, sizeof(unsigned char), w*h, p);
162: 
163:   fclose(p);
164: }
165: