1 /* $NetBSD: xpm2bootimg.c,v 1.3 2009/03/14 21:04:17 dsl Exp $ */
4 * convert XPM format image to boot title format
6 * written by Yasha (ITOH Yasufumi), public domain
17 /* if you change this, you must also make changes to the extraction code */
20 #define LENMAX (1<<LENBIT)
22 #if VALBIT + LENBIT > 8
23 #error too long encoding --- not portable between architectures in this code
26 /* this program may run on cross host, and should be portable */
33 static void putbyte
PROTO((int c
));
34 static void initdot
PROTO((void));
35 static void putrun
PROTO((int val
, int len
));
36 static void adddot
PROTO((int val
));
37 static void flushdot
PROTO((void));
39 static unsigned rgb16b
PROTO((int rgb
));
40 static char *destring
PROTO((char *str
));
41 static char *getline
PROTO((void));
42 static void error
PROTO((char *msg
));
43 int main
PROTO((int argc
, char *argv
[]));
55 static unsigned char wbuf
;
58 if (obytes
% 16 && opt_ascii
)
62 printf("\t.byte\t0x%02x\n", wbuf
);
67 printf("| compressed image %d bytes\n", obytes
);
70 if (obytes
% 16 == 0 && opt_ascii
)
78 if ((obytes
>> 1) % 8 != 1)
80 printf("0x%04x", (wbuf
<< 8) | c
);
82 printf("%c%c", wbuf
, c
);
85 if (obytes
% 16 == 0 && opt_ascii
)
93 outbuf
= bufbits
= curval
= curlen
= obytes
= 0;
99 putrun(int val
, int len
)
102 /* fprintf(stderr, "val %d, len %d\n", val, len);*/
107 bufbits
+= VALBIT
+ LENBIT
;
110 putbyte((unsigned char) (outbuf
>> (bufbits
- 8)));
122 putrun(curval
, curlen
);
127 if (curlen
== LENMAX
) {
138 putrun(curval
, curlen
);
143 /* make sure data drain */
146 putrun(curval
, LENMAX
);
152 * convert r8g8b8 to g5r5b5i1
157 unsigned r
= rgb
>> 16, g
= (rgb
>> 8) & 0xff, b
= rgb
& 0xff;
160 rgb16
= (g
<< 8 & 0xf800) | (r
<< 3 & 0x7c0) | (b
>> 2 & 0x3e);
164 * valid bits used for I bit
166 if ((r
& 7) + (g
& 7) + (b
& 7) >= 11)
174 /* str: must be writable */
179 if (*str
!= '"' || (len
= strlen(str
)) < 2)
195 static char *filename
;
197 static unsigned lineno
;
202 static char buf
[256];
205 if (!fgets(buf
, sizeof buf
, infp
)) {
210 return NULL
; /* end of input */
213 if (!(p
= strchr(buf
, '\n'))) {
214 fprintf(stderr
, "%s:%d: too long line\n", filename
, lineno
);
226 msg
= "format error";
228 fprintf(stderr
, "%s:%d: %s\n", filename
, lineno
, msg
);
232 static struct color
{
235 COL_BLACK
, COL_1
, COL_2
, COL_WHITE
241 enum col bitmap
[IMGHEIGHT
][IMGWIDTH
];
244 main(int argc
, char *argv
[])
247 unsigned u
, colors
, xcol
, x
;
250 char *progname
= argv
[0];
255 if (argc
> 1 && !strcmp(argv
[1], "-s")) {
257 * -s option: output assembler source
258 * (output binary otherwise)
267 } else if (argc
== 2) {
268 if ((infp
= fopen(argv
[1], "r")) == NULL
) {
274 fprintf(stderr
, "usage: %s [file.xpm]\n", progname
);
281 if (!(p
= getline()))
284 if (strcmp(p
, "/* XPM */"))
285 error((char *) NULL
);
287 while ((p
= getline()) && !(p
= destring(p
)))
290 error((char *) NULL
);
293 * the first string must be
294 * "56 52 5 1 XPMEXT",
299 if (sscanf(p
, "%u %u %u %u %s",
300 &w
, &h
, &colors
, &cpp
, buf
) != 5)
301 error("must be \"56 52 * 1 XPMEXT\"");
304 error("image width must be 56");
306 error("image height must be 52");
308 error("chars-per-pixel must be 1");
309 if (strcmp(buf
, "XPMEXT"))
310 error("XPMEXT is required");
312 if (colors
> sizeof coltbl
/ sizeof coltbl
[0])
313 error("too many colors");
320 for (u
= 0; u
< colors
; u
++) {
321 while ((p
= getline()) && !(p
= destring(p
)))
324 error((char *) NULL
);
325 if (sscanf(p
, "%c %c %s", buf
, buf
+1, buf
+2) != 3)
326 error((char *) NULL
);
328 coltbl
[u
].ch
= buf
[0];
331 if (sscanf(buf
+3, "%x", &v
) != 1)
332 error((char *) NULL
);
334 coltbl
[u
].val
= COL_BLACK
;
335 else if (v
== 0xffffff)
336 coltbl
[u
].val
= COL_WHITE
;
337 else if (xcol
== 0) {
338 coltbl
[u
].val
= COL_1
;
341 } else if (xcol
== 1) {
342 coltbl
[u
].val
= COL_2
;
346 error("too many colors");
347 } else if (!strcmp(buf
+2, "None")) {
349 * transparent color is treated as black
351 coltbl
[u
].val
= COL_BLACK
;
353 error("unknown color (symbolic name is not supported)");
359 for (u
= 0; u
< IMGHEIGHT
; u
++) {
361 while ((p
= getline()) && !(p
= destring(p
)))
364 error((char *) NULL
);
366 if (strlen(p
) != IMGWIDTH
)
367 error((char *) NULL
);
369 for (x
= 0; x
< IMGWIDTH
; x
++, p
++) {
372 for (i
= 0; i
< colors
; i
++)
373 if (coltbl
[i
].ch
== *p
)
375 error("unknown character");
378 bitmap
[u
][x
] = coltbl
[i
].val
;
383 * read XPMEXTs and output copyright string
386 while ((p
= getline()) && *p
== '\"') {
387 if (!(p
= destring(p
)))
388 error((char *) NULL
);
389 if (!strcmp(p
, "XPMEXT copyright"))
391 else if (!strncmp(p
, "XPMENDEXT", 3))
393 else if (!strncmp(p
, "XPM", 3))
398 printf("\t.ascii\t\"\\n%s\"\n", p
);
405 /* terminate string */
407 printf("\t.byte\t0\n");
411 /* output color palette */
413 printf("\t.word\t0x%x,0x%x\n", col1
, col2
);
415 printf("%c%c%c%c", col1
>> 8, col1
, col2
>> 8, col2
);
418 * scan bitmap and output
422 for (u
= 0; u
< IMGHEIGHT
; u
++)
423 for (x
= 0; x
< IMGWIDTH
; x
++)
424 adddot(bitmap
[u
][x
]);
431 return ferror(stdout
);