1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tools - ppmconv8
3   File:     ppmconv8.c
4 
5   Copyright 2003-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date::            $
14   $Rev:$
15   $Author:$
16  *---------------------------------------------------------------------------*/
17 //
18 //  The 'ppmconv8' tool is for $TwlSDK/build/demos/GX/UnitTest/2D_BmpBg_*
19 //  Please see detail at 2D_BmpBg_* directories.
20 //
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #define	MAX_COLORS		256    // 256 color limits
28 
29 #define	TRUE			1
30 #define	FALSE			0
31 
32 #define NUM_COLUMN_TEXEL	16
33 #define NUM_COLUMN_PALETTE	16
34 
35 #define	V5bit( x )		((x)>>3)
36 #define	RGB5551( r, g, b, a )	((V5bit(r)<<0) | (V5bit(g)<<5) | (V5bit(b)<<10)| (((a)&1)<<15))
37 
38 #define	SIZE_READBUFFER	1024
39 
40 enum
41 {
42     PHASE_READ_MAGIC_NUMBER,
43     PHASE_READ_WIDTH,
44     PHASE_READ_HEIGHT,
45     PHASE_READ_DEPTH,
46 };
47 
48 typedef unsigned char u8;
49 typedef unsigned short u16;
50 
51 typedef struct
52 {
53     u16     color[MAX_COLORS];
54     int     num_colors;
55 }
56 ColorTable;
57 
usage(void)58 static void usage(void)
59 {
60     fprintf(stderr, "Usage: ppmconv8 [256color ppm file] [label_name]\n");
61     exit(1);
62 }
63 
64 /*---------------------------------------------------------------------------*
65   Name:         ReadHeader
66 
67   Description:  Read header information of ppm file
68 
69   Arguments:    fp      ppm file
70                 pwidth  output ptr for the width  of ppm picture
71                 pheight output ptr for the height of ppm picture
72                 pdepth  output ptr for the depth  of ppm picture
73 
74   Returns:      1 if success, 0 if error
75  *---------------------------------------------------------------------------*/
ReadHeader(FILE * fp,int * pwidth,int * pheight,int * pdepth)76 static int ReadHeader(FILE * fp, int *pwidth, int *pheight, int *pdepth)
77 {
78     // Get ppm header
79     //
80     // P6[WS]256[WS]192[WS]255[WS]\n   WS=Space,Tab,CR
81     //
82     char    buffer[SIZE_READBUFFER], *p;
83     int     n;
84     int     phase = PHASE_READ_MAGIC_NUMBER;
85 
86     while (buffer == fgets(buffer, sizeof(buffer), fp))
87     {
88         if (buffer[0] == '#')          // comment
89         {
90             continue;
91         }
92 
93         p = buffer;
94         while (*p != '\0')
95         {
96             switch (phase)
97             {
98             case PHASE_READ_MAGIC_NUMBER:
99                 if (0 != sscanf(p, "P6%n", &n))
100                 {
101                     return FALSE;      // not ppm file
102                 }
103                 phase = PHASE_READ_WIDTH;
104                 break;
105 
106             case PHASE_READ_WIDTH:
107                 if (1 != sscanf(p, "%d%n", pwidth, &n))
108                 {
109                     return FALSE;
110                 }
111                 phase = PHASE_READ_HEIGHT;
112                 break;
113 
114             case PHASE_READ_HEIGHT:
115                 if (1 != sscanf(p, "%d%n", pheight, &n))
116                 {
117                     return FALSE;
118                 }
119                 phase = PHASE_READ_DEPTH;
120                 break;
121 
122             case PHASE_READ_DEPTH:
123                 if (1 != sscanf(p, "%d%n", pdepth, &n))
124                 {
125                     return FALSE;
126                 }
127                 return TRUE;
128 
129             default:
130                 break;
131             }
132 
133             for (p += n; isspace(*p); p++)
134             {
135                 // Do nothing
136             }
137         }
138     }
139     return FALSE;
140 }
141 
142 
143 /*---------------------------------------------------------------------------*
144   Name:         ReadBody
145 
146   Description:  Read picture image
147 
148   Arguments:    fp      ppm file
149                 buffer	output ptr for image
150                 size    buffer size
151 
152   Returns:      1 if success, 0 if error
153  *---------------------------------------------------------------------------*/
ReadBody(FILE * fp,u8 * buffer,int size)154 static int ReadBody(FILE * fp, u8 *buffer, int size)
155 {
156     return size == fread(buffer, sizeof(u8), size, fp);
157 }
158 
159 
160 /*---------------------------------------------------------------------------*
161   Name:         ColorTableInit
162 
163   Description:  Initialize Color Table
164 
165   Arguments:    None
166 
167   Returns:      N/A
168  *---------------------------------------------------------------------------*/
ColorTableInit(ColorTable * t)169 static void ColorTableInit(ColorTable * t)
170 {
171     int     i;
172     for (i = 0; i < MAX_COLORS; i++)
173     {
174         t->color[i] = 0x0000;
175     }
176     t->num_colors = 0;
177 }
178 
179 /*---------------------------------------------------------------------------*
180   Name:         ColorTableAppend
181 
182   Description:  Get color index from Color Table
183 
184   Arguments:    t      ptr for color table
185                 color  color to be added
186 
187   Returns:      >=  0 : index number if color is in color table
188                 == -1 : error no room to append color
189  *---------------------------------------------------------------------------*/
ColorTableAppend(ColorTable * t,u16 color)190 static int ColorTableAppend(ColorTable * t, u16 color)
191 {
192     int     i;
193 
194     for (i = 0; i < t->num_colors; i++)
195     {
196         if (t->color[i] == color)
197         {
198             return i;
199         }
200     }
201 
202     if (i >= MAX_COLORS)
203     {
204         return -1;
205     }
206 
207     t->color[i] = color;
208     t->num_colors++;
209     return i;
210 }
211 
212 
213 /*---------------------------------------------------------------------------*
214   Name:         ColorTableGetColor
215 
216   Description:  Get color table from Color Table
217 
218   Arguments:    None
219 
220   Returns:      N/A
221  *---------------------------------------------------------------------------*/
ColorTableGetColor(ColorTable * t,int index)222 static u16 ColorTableGetColor(ColorTable * t, int index)
223 {
224     return index < t->num_colors ? t->color[index] : 0x0000;
225 }
226 
227 
228 /*---------------------------------------------------------------------------*
229   Name:         main
230 
231   Description:  output 256 color-ed ppm image bitmap as the format
232                 like C source code
233  *---------------------------------------------------------------------------*/
main(int argc,char * argv[])234 int main(int argc, char *argv[])
235 {
236     FILE   *fp;
237     u8     *buffer;
238     int     result = 1;
239     int     width;
240     int     height;
241     int     depth;
242     int     size;
243     int     column;
244     int     i, index;
245     u16     color;
246     ColorTable color_table;
247 
248     if (argc != 3)
249     {
250         usage();
251     }
252 
253     if (NULL != (fp = fopen(argv[1], "rb")))
254     {
255         if (ReadHeader(fp, &width, &height, &depth) && depth == 255)
256         {
257             size = width * height * 3;
258             if (NULL != (buffer = (u8 *)malloc(size)))
259             {
260                 if (ReadBody(fp, buffer, size))
261                 {
262                     printf("const unsigned char %s_Texel[%d * %d] =\n{\n", argv[2], width, height);
263                     printf("\t/* %s: WIDTH=%d HEIGHT=%d DEPTH=%d */\n", argv[1], width, height,
264                            depth);
265 
266                     column = 0;
267                     ColorTableInit(&color_table);
268                     for (i = 0; i < size; i += 3)
269                     {
270                         if (column % NUM_COLUMN_TEXEL == 0)
271                         {
272                             printf("\t");
273                         }
274                         color = RGB5551(buffer[i], buffer[i + 1], buffer[i + 2], 1);
275                         index = ColorTableAppend(&color_table, color);
276                         if (index < 0)
277                         {
278                             fprintf(stderr, "ppmconv8: Error too many colors (over 256)\n");
279                             return 1;
280                         }
281                         printf("0x%02x, ", index);
282                         column++;
283                         if (column % NUM_COLUMN_TEXEL == 0)
284                         {
285                             printf("\n");
286                         }
287                     }
288                     printf("\n};\n\n");
289                     printf("const unsigned short %s_Palette[%d] =\n{\n", argv[2], MAX_COLORS);
290 
291                     column = 0;
292                     for (i = 0; i < MAX_COLORS; i++)
293                     {
294                         if (column % NUM_COLUMN_PALETTE == 0)
295                         {
296                             printf("\t");
297                         }
298                         printf("0x%04x, ", ColorTableGetColor(&color_table, i));
299                         column++;
300                         if (column % NUM_COLUMN_PALETTE == 0)
301                         {
302                             printf("\n");
303                         }
304                     }
305                     printf("\n};\n\n");
306 
307                     result = 0;
308                 }
309             }
310             free(buffer);
311         }
312         fclose(fp);
313     }
314 
315     if (result)
316     {
317         fprintf(stderr, "Cannot convert file \"%s\".\n", argv[1]);
318     }
319 
320     return result;
321 }
322