source: vital-to8-sdk/gfx-tools/tga2teo.c @ 1

Last change on this file since 1 was 1, checked in by svn, 5 years ago

Import initial

File size: 8.3 KB
Line 
1#include "stdio.h"
2#include "stdlib.h"
3#include "math.h"
4
5/*
6
7        image converter based on http://paulbourke.net/dataformats/tga/
8        tga converter to various formats:
9
10        here for thomson TO8/TO9 formats with specific gamma factor
11
12*/
13
14typedef struct {
15   char  idlength;
16   char  colourmaptype;
17   char  datatypecode;
18   short int colourmaporigin;
19   short int colourmaplength;
20   char  colourmapdepth;
21   short int x_origin;
22   short int y_origin;
23   short width;
24   short height;
25   char  bitsperpixel;
26   char  imagedescriptor;
27} HEADER;
28
29typedef struct {
30   unsigned char r,g,b,a;
31} PIXEL;
32
33void MergeBytes(PIXEL *,unsigned char *,int);
34
35int main(int argc,char **argv)
36{
37   int n=0,i,j;
38   int bytes2read,skipover = 0;
39   unsigned char p[5];
40   FILE *fptr;
41   HEADER header;
42   PIXEL *pixels;
43
44   if (argc < 2) {
45      fprintf(stderr,"Usage: %s tgafile\n",argv[0]);
46      exit(-1);
47   }
48
49   /* Open the file */
50   if ((fptr = fopen(argv[1],"r")) == NULL) {
51      fprintf(stderr,"File open failed\n");
52      exit(-1);
53   }
54
55   /* Display the header fields */
56   header.idlength = fgetc(fptr);
57   fprintf(stderr,"ID length:         %d\n",header.idlength);
58   header.colourmaptype = fgetc(fptr);
59   fprintf(stderr,"Colourmap type:    %d\n",header.colourmaptype);
60   header.datatypecode = fgetc(fptr);
61   fprintf(stderr,"Image type:        %d\n",header.datatypecode);
62   fread(&header.colourmaporigin,2,1,fptr);
63   fprintf(stderr,"Colour map offset: %d\n",header.colourmaporigin);
64   fread(&header.colourmaplength,2,1,fptr);
65   fprintf(stderr,"Colour map length: %d\n",header.colourmaplength);
66   header.colourmapdepth = fgetc(fptr);
67   fprintf(stderr,"Colour map depth:  %d\n",header.colourmapdepth);
68   fread(&header.x_origin,2,1,fptr);
69   fprintf(stderr,"X origin:          %d\n",header.x_origin);
70   fread(&header.y_origin,2,1,fptr);
71   fprintf(stderr,"Y origin:          %d\n",header.y_origin);
72   fread(&header.width,2,1,fptr);
73   fprintf(stderr,"Width:             %d\n",header.width);
74   fread(&header.height,2,1,fptr);
75   fprintf(stderr,"Height:            %d\n",header.height);
76   header.bitsperpixel = fgetc(fptr);
77   fprintf(stderr,"Bits per pixel:    %d\n",header.bitsperpixel);
78   header.imagedescriptor = fgetc(fptr);
79   fprintf(stderr,"Descriptor:        %d\n",header.imagedescriptor);
80
81   /* Allocate space for the image */
82   if ((pixels = malloc(header.width*header.height*sizeof(PIXEL))) == NULL) {
83      fprintf(stderr,"malloc of image failed\n");
84      exit(-1);
85   }
86   for (i=0;i<header.width*header.height;i++) {
87      pixels[i].r = 0;
88      pixels[i].g = 0;
89      pixels[i].b = 0;
90      pixels[i].a = 0;
91   }
92
93   /* What can we handle */
94   if (header.datatypecode != 2 && header.datatypecode != 10) {
95      fprintf(stderr,"Can only handle image type 2 and 10\n");
96      exit(-1);
97   }
98   if (header.bitsperpixel != 16 &&
99       header.bitsperpixel != 24 && header.bitsperpixel != 32) {
100      fprintf(stderr,"Can only handle pixel depths of 16, 24, and 32\n");
101      exit(-1);
102   }
103   if (header.colourmaptype != 0 && header.colourmaptype != 1) {
104      fprintf(stderr,"Can only handle colour map types of 0 and 1\n");
105      exit(-1);
106   }
107
108   /* Skip over unnecessary stuff */
109   skipover += header.idlength;
110   skipover += header.colourmaptype * header.colourmaplength;
111   fprintf(stderr,"Skip over %d bytes\n",skipover);
112   fseek(fptr,skipover,SEEK_CUR);
113
114   /* Read the image */
115   bytes2read = header.bitsperpixel / 8;
116   while (n < header.width * header.height) {
117      if (header.datatypecode == 2) {                     /* Uncompressed */
118         if (fread(p,1,bytes2read,fptr) != bytes2read) {
119            fprintf(stderr,"Unexpected end of file at pixel %d\n",i);
120            exit(-1);
121         }
122         MergeBytes(&(pixels[n]),p,bytes2read);
123         n++;
124      } else if (header.datatypecode == 10) {             /* Compressed */
125         if (fread(p,1,bytes2read+1,fptr) != bytes2read+1) {
126            fprintf(stderr,"Unexpected end of file at pixel %d\n",i);
127            exit(-1);
128         }
129         j = p[0] & 0x7f;
130         MergeBytes(&(pixels[n]),&(p[1]),bytes2read);
131         n++;
132         if (p[0] & 0x80) {         /* RLE chunk */
133            for (i=0;i<j;i++) {
134               MergeBytes(&(pixels[n]),&(p[1]),bytes2read);
135               n++;
136            }
137         } else {                   /* Normal chunk */
138            for (i=0;i<j;i++) {
139               if (fread(p,1,bytes2read,fptr) != bytes2read) {
140                  fprintf(stderr,"Unexpected end of file at pixel %d\n",i);
141                  exit(-1);
142               }
143               MergeBytes(&(pixels[n]),p,bytes2read);
144               n++;
145            }
146         }
147      }
148   }
149   fclose(fptr);
150
151   fprintf(stderr,"[INFO] now in vm part ;) \n");
152   /* now count colors used */
153   int palette_24b[256];
154   int palette_to[16];
155   int col_num=1;
156   int val;
157   palette_24b[0]=(pixels[0].b<<16)|(pixels[0].g<<8)|(pixels[0].r);
158   for (i=1;i<header.height*header.width;i++) {
159      val=(pixels[i].b<<16)|(pixels[i].g<<8)|(pixels[i].r);
160      // does this color exists in palette     
161      for (j=0;j<col_num;j++) {
162        if (palette_24b[j]==val) break;
163      }
164      if (j==col_num) {
165         if (col_num==255) {
166            col_num=256;
167            fprintf(stderr,"[ERROR] too many colors (+256) !!!\n");
168            exit(-1);
169         }
170         palette_24b[col_num]=val;
171         col_num++;
172      }
173   }
174   fprintf(stderr,"[INFO] Number of unique colors %d\n",col_num);
175
176   if (col_num>16) {
177            fprintf(stderr,"[ERROR] too many colors %d\n",col_num);
178            exit(-1);
179   }
180
181
182   for (i=0;i<16;i++) palette_to[i]=0;
183
184
185   for (i=0;i<col_num;i++) {
186        palette_to[i]=pal_conv((palette_24b[i]&0xFF0000)>>16)<<8;
187        palette_to[i]|=pal_conv((palette_24b[i]&0xFF00)>>8)<<4;
188        palette_to[i]|=pal_conv((palette_24b[i]&0xFF));
189        fprintf(stderr,"[INFO] palette[%d]=%03x\n",i,palette_to[i]);
190   }
191
192
193   /* ouput in 2 files raw data 8kb each (palette at end) */
194   FILE *COL;
195   FILE *PT;
196
197   COL=fopen("COL.BIN","wb");
198   PT=fopen("PT.BIN","wb");
199
200   // on modifie les pixels 2 par 2
201   for (i=0;i<header.height*header.width;i++) {
202      int mem;
203      val=(pixels[i].b<<16)|(pixels[i].g<<8)|(pixels[i].r);
204      // on retrouve l'index dans la palette dans j
205      for (j=0;j<16;j++) {
206        if (val==palette_24b[j]) break;
207      }
208      switch (i%4) {
209      case 0 : mem=j<<4;
210        break;
211      case 1 : fputc(mem|j,PT);
212        break;
213      case 2 : mem=j<<4;
214        break;
215      case 3 : fputc(mem|j,COL);
216        break;
217      }
218   }
219   for (i=0;i<16;i++) {
220        fputc((palette_to[i]&0xFF00)>>8,PT);
221        fputc((palette_to[i]&0xFF),PT);
222        fputc((palette_to[i]&0xFF00)>>8,COL);
223        fputc((palette_to[i]&0xFF),COL);
224   }
225
226   fclose(PT);
227   fclose(COL);
228}
229
230int
231pal_conv(int v) {
232   int i;
233   /* convert palette to thomson gamma factor */
234//   static int gamma[16]={0,100,127,147,163,179,191,203,215,223,231,239,243,247,251,255};
235   static int seuils[17]={0,50,114,137,155,171,185,197,209,219,227,235,241,245,249,253,257};
236   for (i=0;i<16;i++) {
237      if (v<seuils[i+1]) break;
238   }
239   return i;
240}
241
242void
243output_tga(HEADER header,PIXEL *pixels) {
244   FILE *fptr;
245   int i;
246   /* Write the result as a uncompressed TGA */
247   if ((fptr = fopen("tgatest.tga","w")) == NULL) {
248      fprintf(stderr,"Failed to open outputfile\n");
249      exit(-1);
250   }
251   putc(0,fptr);
252   putc(0,fptr);
253   putc(2,fptr);                         /* uncompressed RGB */
254   putc(0,fptr); putc(0,fptr);
255   putc(0,fptr); putc(0,fptr);
256   putc(0,fptr);
257   putc(0,fptr); putc(0,fptr);           /* X origin */
258   putc(0,fptr); putc(0,fptr);           /* y origin */
259   putc((header.width & 0x00FF),fptr);
260   putc((header.width & 0xFF00) / 256,fptr);
261   putc((header.height & 0x00FF),fptr);
262   putc((header.height & 0xFF00) / 256,fptr);
263   putc(32,fptr);                        /* 24 bit bitmap */
264   putc(0,fptr);
265   for (i=0;i<header.height*header.width;i++) {
266      putc(pixels[i].b,fptr);
267      putc(pixels[i].g,fptr);
268      putc(pixels[i].r,fptr);
269      putc(pixels[i].a,fptr);
270   }
271   fclose(fptr);
272}
273
274void MergeBytes(PIXEL *pixel,unsigned char *p,int bytes)
275{
276   if (bytes == 4) {
277      pixel->r = p[2];
278      pixel->g = p[1];
279      pixel->b = p[0];
280      pixel->a = p[3];
281   } else if (bytes == 3) {
282      pixel->r = p[2];
283      pixel->g = p[1];
284      pixel->b = p[0];
285      pixel->a = 0;
286   } else if (bytes == 2) {
287      pixel->r = (p[1] & 0x7c) << 1;
288      pixel->g = ((p[1] & 0x03) << 6) | ((p[0] & 0xe0) >> 2);
289      pixel->b = (p[0] & 0x1f) << 3;
290      pixel->a = (p[1] & 0x80);
291   }
292}
293
Note: See TracBrowser for help on using the repository browser.