2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Tool to convert IFF ILBM images into C source.
11 /****************************************************************************************/
19 /****************************************************************************************/
21 #define MAKE_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | ((d)))
23 #define ID_FORM MAKE_ID('F','O','R','M')
24 #define ID_ILBM MAKE_ID('I','L','B','M')
25 #define ID_CMAP MAKE_ID('C','M','A','P')
26 #define ID_BODY MAKE_ID('B','O','D','Y')
27 #define ID_BMHD MAKE_ID('B','M','H','D')
30 #define CMP_BYTERUN1 1
34 /****************************************************************************************/
36 /* For this tool it does not really matter if the following types
37 have a bigger sizeof() than on Amiga */
40 typedef unsigned long ULONG
;
42 typedef unsigned short UWORD
;
45 typedef unsigned char UBYTE
;
47 #include <exec/types.h>
50 /****************************************************************************************/
60 UBYTE bmh_Compression
;
62 UWORD bmh_Transparent
;
69 /****************************************************************************************/
71 static char *filename
;
73 static unsigned char *filebuffer
, *body
, *planarbuffer
, *chunkybuffer
;
74 static unsigned char *planarbuffer_packed
, *chunkybuffer_packed
;
75 static long filesize
, bodysize
, bodysize_packed
;
77 static struct BitMapHeader bmh
;
78 static LONG cmapentries
, totdepth
, bpr
;
79 static BOOL have_bmhd
, have_cmap
, have_body
;
80 static UBYTE red
[256], green
[256], blue
[256];
81 static char imagename
[1000];
82 static char bigimagename
[1000];
84 /****************************************************************************************/
86 static void cleanup(char *msg
, int rc
)
88 if (msg
) fprintf(stderr
, "ilbmtoc: %s\n", msg
);
90 if (chunkybuffer_packed
) free(chunkybuffer_packed
);
91 if (planarbuffer_packed
) free(planarbuffer_packed
);
92 if (chunkybuffer
) free(chunkybuffer
);
93 if (planarbuffer
) free(planarbuffer
);
94 if (filebuffer
) free(filebuffer
);
96 if (file
) fclose(file
);
101 /****************************************************************************************/
103 static void getarguments(int argc
, char **argv
)
105 char *imagenamestart
, *sp
;
110 fprintf(stderr
, "Wrong number of arguments\n");
115 cleanup("Usage: ilbmtoc filename", 1);
120 if (strlen(filename
) >= sizeof(imagename
)) cleanup("Filename too long!", 1);
122 imagenamestart
= filename
;
125 sp
= strchr(imagenamestart
+ 1, '/');
126 if (!sp
) sp
= strchr(imagenamestart
+ 1, '\\');
127 if (!sp
) sp
= strchr(imagenamestart
+ 1, ':');
130 imagenamestart
= sp
+ 1;
133 strcpy(imagename
, imagenamestart
);
134 if ((sp
= strchr(imagename
, '.'))) *sp
= 0;
136 for(i
= 0; i
< strlen(imagename
); i
++) bigimagename
[i
] = toupper(imagename
[i
]);
139 /****************************************************************************************/
141 static ULONG
getlong(void)
145 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
147 ret
= filebuffer
[filepos
++] * 0x1000000;
148 ret
+= filebuffer
[filepos
++] * 0x10000;
149 ret
+= filebuffer
[filepos
++] * 0x100;
150 ret
+= filebuffer
[filepos
++];
155 /****************************************************************************************/
157 static UWORD
getword(void)
161 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
163 ret
= filebuffer
[filepos
++] * 0x100;
164 ret
+= filebuffer
[filepos
++];
169 /****************************************************************************************/
171 static UBYTE
getbyte(void)
175 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
176 ret
= filebuffer
[filepos
++];
181 /****************************************************************************************/
183 static void skipbytes(ULONG howmany
)
188 /****************************************************************************************/
190 static void openfile(void)
192 file
= fopen(filename
, "rb");
193 if (!file
) cleanup("Can't open file!", 1);
195 fseek(file
, 0, SEEK_END
);
196 filesize
= ftell(file
);
198 if (filesize
< 12) cleanup("Bad file size!", 1);
200 fprintf(stderr
, "Filesize is %d\n", filesize
);
202 fseek(file
, 0, SEEK_SET
);
204 filebuffer
= malloc(filesize
+ 10);
205 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
207 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
208 cleanup("Error reading file!", 1);
210 fclose(file
); file
= NULL
;
213 /****************************************************************************************/
215 static void checkfile(void)
221 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
224 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
227 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
230 /****************************************************************************************/
232 static void scanfile(void)
244 fprintf(stderr
, "Chunk: %c%c%c%c Size: %d\n", id
>> 24, id
>> 16, id
>> 8, id
, size
);
249 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
251 bmh
.bmh_Width
= getword();
252 bmh
.bmh_Height
= getword();
253 bmh
.bmh_Left
= (WORD
)getword();
254 bmh
.bmh_Top
= (WORD
)getword();
255 bmh
.bmh_Depth
= getbyte();
256 bmh
.bmh_Masking
= getbyte();
257 bmh
.bmh_Compression
= getbyte();
258 bmh
.bmh_Pad
= getbyte();
259 bmh
.bmh_Transparent
= getword();
260 bmh
.bmh_XAspect
= getbyte();
261 bmh
.bmh_YAspect
= getbyte();
262 bmh
.bmh_PageWidth
= (WORD
)getword();
263 bmh
.bmh_PageHeight
= (WORD
)getword();
265 if (bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
266 if ((bmh
.bmh_Compression
!= CMP_NONE
) && (bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
270 totdepth
= bmh
.bmh_Depth
+ ((bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
272 bpr
= ((bmh
.bmh_Width
+ 15) & ~15) / 8;
274 fprintf(stderr
, "BMHD: %d x %d x %d (%d)\n", bmh
.bmh_Width
,
281 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
283 cmapentries
= size
/ 3;
284 if (size
& 1) size
++;
286 if ((cmapentries
< 2) || (cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
288 for(i
= 0; i
< cmapentries
; i
++)
291 green
[i
] = getbyte();
303 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
304 body
= &filebuffer
[filepos
];
307 if (bmh
.bmh_Compression
== CMP_NONE
)
309 LONG shouldbesize
= totdepth
* bpr
* bmh
.bmh_Height
;
310 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
317 if (size
& 1) size
++;
322 if (filepos
== filesize
) break;
323 if (have_bmhd
&& have_body
&& have_cmap
) break;
326 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
327 if (!have_body
) cleanup("BODY chunk missing!", 1);
330 /****************************************************************************************/
332 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
339 c
= (signed char)(*source
++);
345 if (--unpackedsize
<= 0) return source
;
356 if (--unpackedsize
<= 0) return source
;
363 /****************************************************************************************/
365 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
366 unsigned char **dest
, LONG
*checksize
)
368 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
374 if (step
> 127) step
= 127;
379 if (*checksize
<= 0) return 0;
388 *(*dest
)++ = *(*source_backup
)++;
398 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
400 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
406 if (step
> 127) step
= 127;
411 if (*checksize
<= 0) return 0;
413 *(*dest
)++ = (unsigned char)step
;
420 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
421 LONG size
, LONG check_size
, LONG
*packsize
)
423 unsigned char *source_backup
, *dest_backup
;
424 LONG samebytes_counter
, samebytes
, count
;
425 LONG checksize
= check_size
;
426 unsigned char oldbyte
, actbyte
;
428 if (checksize
< 0) checksize
= 0x7FFFFFFF;
431 samebytes_counter
= 0;
432 source_backup
= source
;
437 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
438 if (--size
< 0) break;
440 if (actbyte
== oldbyte
)
448 samebytes
= samebytes_counter
;
449 samebytes_counter
= 1;
451 if (samebytes
< 3) continue;
453 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
454 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
456 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
458 source_backup
= source
- 1;
460 //fprintf(stderr, "done\n");
462 if (samebytes_counter
>= 3)
464 samebytes
= samebytes_counter
;
465 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
466 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
467 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
471 count
= (LONG
)(source
- source_backup
- 1);
472 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
474 //fprintf(stderr, "realdone\n");
476 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
481 /****************************************************************************************/
483 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
484 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
486 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
488 alignedwidth
= (width
+ 15) & ~15;
489 bpr
= alignedwidth
/ 8;
490 bpl
= bpr
* totplanes
;
492 for(y
= 0; y
< height
; y
++)
494 for(x
= 0; x
< width
; x
++)
496 LONG mask
= 1 << (7 - (x
& 7));
498 unsigned char chunkypix
= 0;
500 for(p
= 0; p
< wantplanes
; p
++)
502 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
514 /****************************************************************************************/
516 static void convertbody(void)
518 LONG unpackedsize
= bpr
* bmh
.bmh_Height
* totdepth
;
520 planarbuffer
= malloc(unpackedsize
);
521 if (!planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
523 if (bmh
.bmh_Compression
== CMP_NONE
)
525 memcpy(planarbuffer
, body
, unpackedsize
);
529 unpack_byterun1(body
, planarbuffer
, unpackedsize
);
532 chunkybuffer
= malloc(bmh
.bmh_Width
* bmh
.bmh_Height
);
533 if (!chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
544 /****************************************************************************************/
546 static void packdata(void)
548 LONG chunkysize
= (LONG
)bmh
.bmh_Width
* (LONG
)bmh
.bmh_Height
;
551 chunkybuffer_packed
= malloc(chunkysize
);
553 if (!chunkybuffer_packed
) cleanup("Memory allocation for packed chunky buffer failed!", 1);
555 fprintf(stderr
, "Starting packing\n");
557 success
= pack_byterun1(chunkybuffer
, chunkybuffer_packed
,
558 chunkysize
, chunkysize
, &bodysize_packed
);
560 fprintf(stderr
, "Done packing. Success = %d\n", success
);
563 free(chunkybuffer_packed
); chunkybuffer_packed
= 0;
567 /****************************************************************************************/
569 static void gensource(void)
571 unsigned char *buffer
;
572 LONG i
, x
, y
, buffersize
;
574 printf("#include <exec/types.h>\n");
576 printf("#define %s_WIDTH %d\n", bigimagename
, bmh
.bmh_Width
);
577 printf("#define %s_HEIGHT %d\n", bigimagename
, bmh
.bmh_Height
);
578 printf("#define %s_PACKED %d\n", bigimagename
, (chunkybuffer_packed
|| planarbuffer_packed
) ? 1 : 0);
579 printf("#define %s_PLANES %d\n", bigimagename
, bmh
.bmh_Depth
);
581 printf("#define %s_COLORS %d\n", bigimagename
, cmapentries
);
587 printf("ULONG %s_pal[%d] =\n", imagename
, cmapentries
);
589 for(i
= 0; i
< cmapentries
; i
++)
591 ULONG col
= (((ULONG
)red
[i
]) << 16) +
592 (((ULONG
)green
[i
]) << 8) +
595 printf(" 0x%06x", col
);
596 if (i
== cmapentries
- 1)
605 if (chunkybuffer_packed
)
607 buffer
= chunkybuffer_packed
;
608 buffersize
= bodysize_packed
;
612 buffer
= chunkybuffer
;
613 buffersize
= bodysize
;
616 printf("UBYTE %s_data[%d] =\n", imagename
, buffersize
);
621 for(x
= 0; x
< buffersize
; x
++)
623 if ((i
++ % 20) == 0) printf("\n ");
624 printf("0x%02x", buffer
[x
]);
625 if (!(x
== buffersize
- 1)) printf(",");
632 /****************************************************************************************/
634 int main(int argc
, char **argv
)
636 getarguments(argc
, argv
);
647 /****************************************************************************************/
648 /****************************************************************************************/
649 /****************************************************************************************/
650 /****************************************************************************************/
651 /****************************************************************************************/