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: