rev |
line source |
nuclear@4
|
1 #include <stdio.h>
|
nuclear@4
|
2 #include <stdlib.h>
|
nuclear@4
|
3 #include <string.h>
|
nuclear@4
|
4 #include <ctype.h>
|
nuclear@4
|
5
|
nuclear@5
|
6 #define RODATA_STR "__attribute__((section(\".rodata\")))"
|
nuclear@5
|
7
|
nuclear@4
|
8 unsigned char *read_image(int *xsz, int *ysz, int *maxval);
|
nuclear@4
|
9
|
nuclear@5
|
10 int main(int argc, char **argv)
|
nuclear@4
|
11 {
|
nuclear@5
|
12 int i, j, width, height, xtiles, ytiles, maxval;
|
nuclear@5
|
13 unsigned char *pixels, *tiles, *src, *dest;
|
nuclear@5
|
14 const char *prefix = "img_";
|
nuclear@5
|
15
|
nuclear@5
|
16 if(argv[1]) {
|
nuclear@5
|
17 prefix = argv[1];
|
nuclear@5
|
18 }
|
nuclear@4
|
19
|
nuclear@4
|
20 if(!(pixels = read_image(&width, &height, &maxval))) {
|
nuclear@4
|
21 return 1;
|
nuclear@4
|
22 }
|
nuclear@4
|
23 fprintf(stderr, "read image %dx%d (maxval: %d)\n", width, height, maxval);
|
nuclear@4
|
24
|
nuclear@5
|
25 xtiles = width / 8;
|
nuclear@5
|
26 ytiles = height / 8;
|
nuclear@5
|
27 /* each tile is 32 bytes, 8 rows of 4 bytes each */
|
nuclear@5
|
28 if(!(tiles = malloc(xtiles * ytiles * 32))) {
|
nuclear@5
|
29 free(pixels);
|
nuclear@5
|
30 return 1;
|
nuclear@5
|
31 }
|
nuclear@4
|
32
|
nuclear@5
|
33 /* if we have 15 as max val, we'll assume they are straight palette indices
|
nuclear@5
|
34 * otherwise, do color quantization and palette allocation
|
nuclear@5
|
35 */
|
nuclear@5
|
36 if(maxval == 15) {
|
nuclear@5
|
37 /* just drop green/blue components in-place, keep red as index */
|
nuclear@5
|
38 dest = src = pixels;
|
nuclear@5
|
39 for(i=0; i<width * height; i++) {
|
nuclear@5
|
40 *dest++ = *src;
|
nuclear@5
|
41 src += 3;
|
nuclear@5
|
42 }
|
nuclear@5
|
43 } else {
|
nuclear@5
|
44 /* TODO */
|
nuclear@5
|
45 }
|
nuclear@5
|
46
|
nuclear@5
|
47 /* after processing, we have 1 color index per byte */
|
nuclear@5
|
48
|
nuclear@5
|
49 /* slice tiles and pack indices as nibbles */
|
nuclear@5
|
50 dest = tiles;
|
nuclear@5
|
51 for(i=0; i<ytiles; i++) {
|
nuclear@5
|
52 for(j=0; j<xtiles; j++) {
|
nuclear@5
|
53 int x, y;
|
nuclear@5
|
54 int tilestart = (i * xtiles * 8 + j) * 8;
|
nuclear@5
|
55
|
nuclear@5
|
56 for(y=0; y<8; y++) {
|
nuclear@5
|
57 for(x=0; x<4; x++) {
|
nuclear@5
|
58 src = pixels + tilestart + y * width + x * 2;
|
nuclear@5
|
59 *dest++ = (src[0] << 4) | (src[1] & 0xf);
|
nuclear@5
|
60 }
|
nuclear@5
|
61 }
|
nuclear@5
|
62
|
nuclear@4
|
63 }
|
nuclear@4
|
64 }
|
nuclear@4
|
65
|
nuclear@5
|
66 /* output as C array */
|
nuclear@5
|
67 printf("/* generated by ppm2md */\n");
|
nuclear@5
|
68 printf("int %sxtiles " RODATA_STR " = %d;\n", prefix, xtiles);
|
nuclear@5
|
69 printf("int %sytiles " RODATA_STR " = %d;\n", prefix, ytiles);
|
nuclear@5
|
70 printf("unsigned char %stiles[][32] " RODATA_STR " = {", prefix);
|
nuclear@5
|
71
|
nuclear@5
|
72 src = tiles;
|
nuclear@5
|
73 for(i=0; i<xtiles * ytiles; i++) {
|
nuclear@5
|
74 if(i > 0) {
|
nuclear@5
|
75 printf(",\n");
|
nuclear@5
|
76 } else {
|
nuclear@5
|
77 putchar('\n');
|
nuclear@5
|
78 }
|
nuclear@5
|
79 printf("\t{");
|
nuclear@5
|
80 for(j=0; j<32; j++) {
|
nuclear@5
|
81 if(j == 0) {
|
nuclear@5
|
82 printf("%u", (unsigned int)*src++);
|
nuclear@5
|
83 } else {
|
nuclear@5
|
84 printf(", %u", (unsigned int)*src++);
|
nuclear@5
|
85 }
|
nuclear@5
|
86 }
|
nuclear@5
|
87 printf(" }");
|
nuclear@5
|
88 }
|
nuclear@5
|
89 printf("\n};\n");
|
nuclear@5
|
90
|
nuclear@5
|
91
|
nuclear@4
|
92 return 0;
|
nuclear@4
|
93 }
|
nuclear@4
|
94
|
nuclear@4
|
95 char *clean_line(char *s)
|
nuclear@4
|
96 {
|
nuclear@4
|
97 char *tmp;
|
nuclear@4
|
98
|
nuclear@4
|
99 while(*s && isspace(*s)) {
|
nuclear@4
|
100 ++s;
|
nuclear@4
|
101 }
|
nuclear@4
|
102
|
nuclear@4
|
103 tmp = strchr(s, '#');
|
nuclear@4
|
104 if(tmp) *tmp = 0;
|
nuclear@4
|
105 tmp = strchr(s, '\n');
|
nuclear@4
|
106 if(tmp) *tmp = 0;
|
nuclear@4
|
107 tmp = strchr(s, '\r');
|
nuclear@4
|
108 if(tmp) *tmp = 0;
|
nuclear@4
|
109
|
nuclear@4
|
110 return s;
|
nuclear@4
|
111 }
|
nuclear@4
|
112
|
nuclear@4
|
113 unsigned char *read_image(int *width, int *height, int *maxval)
|
nuclear@4
|
114 {
|
nuclear@4
|
115 char buf[256];
|
nuclear@4
|
116 int i, xsz, ysz, hdrline = 0;
|
nuclear@4
|
117 unsigned char *pixels;
|
nuclear@4
|
118
|
nuclear@4
|
119 while(hdrline < 3 && fgets(buf, sizeof buf, stdin)) {
|
nuclear@4
|
120 char *line = clean_line(buf);
|
nuclear@4
|
121 if(!*line) continue;
|
nuclear@4
|
122
|
nuclear@4
|
123 switch(hdrline) {
|
nuclear@4
|
124 case 0:
|
nuclear@4
|
125 if(strcmp(line, "P6") != 0) {
|
nuclear@4
|
126 goto inval;
|
nuclear@4
|
127 }
|
nuclear@4
|
128 break;
|
nuclear@4
|
129
|
nuclear@4
|
130 case 1:
|
nuclear@4
|
131 if(sscanf(line, "%d %d", &xsz, &ysz) != 2) {
|
nuclear@4
|
132 goto inval;
|
nuclear@4
|
133 }
|
nuclear@4
|
134 break;
|
nuclear@4
|
135
|
nuclear@4
|
136 case 2:
|
nuclear@4
|
137 if(sscanf(line, "%d", maxval) != 1) {
|
nuclear@4
|
138 goto inval;
|
nuclear@4
|
139 }
|
nuclear@4
|
140 break;
|
nuclear@4
|
141 }
|
nuclear@4
|
142 ++hdrline;
|
nuclear@4
|
143 }
|
nuclear@4
|
144
|
nuclear@4
|
145 if(!(pixels = malloc(xsz * ysz * 3))) {
|
nuclear@4
|
146 fprintf(stderr, "failed to allocate image: %dx%d\n", xsz, ysz);
|
nuclear@4
|
147 return 0;
|
nuclear@4
|
148 }
|
nuclear@4
|
149
|
nuclear@4
|
150 for(i=0; i<xsz * ysz * 3; i++) {
|
nuclear@4
|
151 int c = getchar();
|
nuclear@4
|
152 if(c == -1) goto inval;
|
nuclear@4
|
153 pixels[i] = c;
|
nuclear@4
|
154 }
|
nuclear@4
|
155
|
nuclear@4
|
156 *width = xsz;
|
nuclear@4
|
157 *height = ysz;
|
nuclear@4
|
158 return pixels;
|
nuclear@4
|
159
|
nuclear@4
|
160 inval:
|
nuclear@4
|
161 fprintf(stderr, "invalid input\n");
|
nuclear@4
|
162 return 0;
|
nuclear@4
|
163 }
|