2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Tool to convert IFF ILBM images into C source.
11 /****************************************************************************************/
18 /****************************************************************************************/
20 #define MAKE_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | ((d)))
22 #define ID_FORM MAKE_ID('F','O','R','M')
23 #define ID_ILBM MAKE_ID('I','L','B','M')
24 #define ID_CMAP MAKE_ID('C','M','A','P')
25 #define ID_BODY MAKE_ID('B','O','D','Y')
26 #define ID_BMHD MAKE_ID('B','M','H','D')
29 #define CMP_BYTERUN1 1
33 /****************************************************************************************/
35 /* For this tool it does not really matter if the following types
36 have a bigger sizeof() than on Amiga */
39 typedef unsigned long ULONG
;
41 typedef unsigned short UWORD
;
44 typedef unsigned char UBYTE
;
46 #include <exec/types.h>
49 /****************************************************************************************/
59 UBYTE bmh_Compression
;
61 UWORD bmh_Transparent
;
68 /****************************************************************************************/
70 static char *filename
;
72 static unsigned char *filebuffer
, *body
, *planarbuffer
, *chunkybuffer
;
73 static unsigned char *planarbuffer_packed
, *chunkybuffer_packed
;
74 static LONG filesize
, bodysize
, bodysize_packed
;
76 static struct BitMapHeader bmh
;
77 static LONG cmapentries
, totdepth
, bpr
;
78 static BOOL have_bmhd
, have_cmap
, have_body
;
79 static UBYTE red
[256], green
[256], blue
[256];
80 static char imagename
[1000];
81 static char bigimagename
[1000];
82 static BOOL brush2c
; // compatibility with brush2c from MUI SDK
83 static BOOL brush2pix
; // compatibility with brush2pix from JabberWocky
85 /****************************************************************************************/
87 static void cleanup(char *msg
, int rc
)
89 if (msg
) fprintf(stderr
, "ilbmtoc: %s\n", msg
);
91 if (chunkybuffer_packed
) free(chunkybuffer_packed
);
92 if (planarbuffer_packed
) free(planarbuffer_packed
);
93 if (chunkybuffer
) free(chunkybuffer
);
94 if (planarbuffer
) free(planarbuffer
);
95 if (filebuffer
) free(filebuffer
);
97 if (file
) fclose(file
);
102 /****************************************************************************************/
104 static void getarguments(int argc
, char **argv
)
106 char *imagenamestart
, *sp
;
108 unsigned int narg
= 1;
110 if (!strcasecmp(argv
[1], "-b2c"))
115 else if (!strcasecmp(argv
[1], "-b2p"))
122 filename
= argv
[narg
++];
124 cleanup("Usage: ilbmtoc [-b2c|-b2p] filename [imagename]", 1);
127 imagenamestart
= argv
[narg
];
130 imagenamestart
= filename
;
133 sp
= strchr(imagenamestart
+ 1, '/');
134 if (!sp
) sp
= strchr(imagenamestart
+ 1, '\\');
135 if (!sp
) sp
= strchr(imagenamestart
+ 1, ':');
138 imagenamestart
= sp
+ 1;
142 if (strlen(imagename
) >= sizeof(imagename
)) cleanup("Image name too long!", 1);
144 strcpy(imagename
, imagenamestart
);
145 if ((sp
= strchr(imagename
, '.'))) *sp
= 0;
147 for(i
= 0; i
< strlen(imagename
); i
++) bigimagename
[i
] = toupper(imagename
[i
]);
150 /****************************************************************************************/
152 static ULONG
getlong(void)
156 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
158 ret
= filebuffer
[filepos
++] * 0x1000000;
159 ret
+= filebuffer
[filepos
++] * 0x10000;
160 ret
+= filebuffer
[filepos
++] * 0x100;
161 ret
+= filebuffer
[filepos
++];
166 /****************************************************************************************/
168 static UWORD
getword(void)
172 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
174 ret
= filebuffer
[filepos
++] * 0x100;
175 ret
+= filebuffer
[filepos
++];
180 /****************************************************************************************/
182 static UBYTE
getbyte(void)
186 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
187 ret
= filebuffer
[filepos
++];
192 /****************************************************************************************/
194 static void skipbytes(ULONG howmany
)
199 /****************************************************************************************/
201 static void openfile(void)
203 file
= fopen(filename
, "rb");
204 if (!file
) cleanup("Can't open file!", 1);
206 fseek(file
, 0, SEEK_END
);
207 filesize
= ftell(file
);
209 if (filesize
< 12) cleanup("Bad file size!", 1);
211 fprintf(stderr
, "Filesize is %ld\n", filesize
);
213 fseek(file
, 0, SEEK_SET
);
215 filebuffer
= malloc(filesize
+ 10);
216 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
218 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
219 cleanup("Error reading file!", 1);
221 fclose(file
); file
= NULL
;
224 /****************************************************************************************/
226 static void checkfile(void)
232 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
235 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
238 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
241 /****************************************************************************************/
243 static void scanfile(void)
255 /* Cast the IFF identifier to 4 ASCII chars:
256 (Use unsigned as i ANSI-C the cast to signed is implementation-dependent.) */
257 fprintf( stderr
, "Chunk: %c%c%c%c Size: %ld\n"
258 , (unsigned char) (id
>> 24)
259 , (unsigned char) (id
>> 16)
260 , (unsigned char) (id
>> 8)
261 , (unsigned char) (id
)
268 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
270 bmh
.bmh_Width
= getword();
271 bmh
.bmh_Height
= getword();
272 bmh
.bmh_Left
= (WORD
)getword();
273 bmh
.bmh_Top
= (WORD
)getword();
274 bmh
.bmh_Depth
= getbyte();
275 bmh
.bmh_Masking
= getbyte();
276 bmh
.bmh_Compression
= getbyte();
277 bmh
.bmh_Pad
= getbyte();
278 bmh
.bmh_Transparent
= getword();
279 bmh
.bmh_XAspect
= getbyte();
280 bmh
.bmh_YAspect
= getbyte();
281 bmh
.bmh_PageWidth
= (WORD
)getword();
282 bmh
.bmh_PageHeight
= (WORD
)getword();
284 if (bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
285 if ((bmh
.bmh_Compression
!= CMP_NONE
) && (bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
289 totdepth
= bmh
.bmh_Depth
+ ((bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
291 bpr
= ((bmh
.bmh_Width
+ 15) & ~15) / 8;
293 fprintf(stderr
, "BMHD: %d x %d x %d (%ld)\n", bmh
.bmh_Width
,
300 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
302 cmapentries
= size
/ 3;
303 if (size
& 1) size
++;
305 if ((cmapentries
< 2) || (cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
307 for(i
= 0; i
< cmapentries
; i
++)
310 green
[i
] = getbyte();
322 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
323 body
= &filebuffer
[filepos
];
326 if (bmh
.bmh_Compression
== CMP_NONE
)
328 LONG shouldbesize
= totdepth
* bpr
* bmh
.bmh_Height
;
329 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
336 if (size
& 1) size
++;
341 if (filepos
== filesize
) break;
342 if (have_bmhd
&& have_body
&& have_cmap
) break;
345 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
346 if (!have_body
) cleanup("BODY chunk missing!", 1);
349 /****************************************************************************************/
351 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
358 c
= (signed char)(*source
++);
364 if (--unpackedsize
<= 0) return source
;
375 if (--unpackedsize
<= 0) return source
;
382 /****************************************************************************************/
384 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
385 unsigned char **dest
, LONG
*checksize
)
387 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
393 if (step
> 127) step
= 127;
398 if (*checksize
<= 0) return 0;
407 *(*dest
)++ = *(*source_backup
)++;
417 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
419 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
425 if (step
> 127) step
= 127;
430 if (*checksize
<= 0) return 0;
432 *(*dest
)++ = (unsigned char)step
;
439 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
440 LONG size
, LONG check_size
, LONG
*packsize
)
442 unsigned char *source_backup
, *dest_backup
;
443 LONG samebytes_counter
, samebytes
, count
;
444 LONG checksize
= check_size
;
445 unsigned char oldbyte
, actbyte
;
447 if (checksize
< 0) checksize
= 0x7FFFFFFF;
450 samebytes_counter
= 0;
451 source_backup
= source
;
456 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
457 if (--size
< 0) break;
459 if (actbyte
== oldbyte
)
467 samebytes
= samebytes_counter
;
468 samebytes_counter
= 1;
470 if (samebytes
< 3) continue;
472 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
473 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
475 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
477 source_backup
= source
- 1;
479 //fprintf(stderr, "done\n");
481 if (samebytes_counter
>= 3)
483 samebytes
= samebytes_counter
;
484 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
485 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
486 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
490 count
= (LONG
)(source
- source_backup
- 1);
491 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
493 //fprintf(stderr, "realdone\n");
495 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
500 /****************************************************************************************/
502 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
503 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
505 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
507 alignedwidth
= (width
+ 15) & ~15;
508 bpr
= alignedwidth
/ 8;
509 bpl
= bpr
* totplanes
;
511 for(y
= 0; y
< height
; y
++)
513 for(x
= 0; x
< width
; x
++)
515 LONG mask
= 1 << (7 - (x
& 7));
517 unsigned char chunkypix
= 0;
519 for(p
= 0; p
< wantplanes
; p
++)
521 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
533 /****************************************************************************************/
535 static void convertbody(void)
537 LONG unpackedsize
= bpr
* bmh
.bmh_Height
* totdepth
;
539 planarbuffer
= malloc(unpackedsize
);
540 if (!planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
542 if (bmh
.bmh_Compression
== CMP_NONE
)
544 memcpy(planarbuffer
, body
, unpackedsize
);
548 unpack_byterun1(body
, planarbuffer
, unpackedsize
);
551 chunkybuffer
= malloc(bmh
.bmh_Width
* bmh
.bmh_Height
);
552 if (!chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
563 /****************************************************************************************/
565 static void packdata(void)
567 LONG chunkysize
= (LONG
)bmh
.bmh_Width
* (LONG
)bmh
.bmh_Height
;
570 chunkybuffer_packed
= malloc(chunkysize
);
572 if (!chunkybuffer_packed
) cleanup("Memory allocation for packed chunky buffer failed!", 1);
574 fprintf(stderr
, "Starting packing\n");
576 success
= pack_byterun1(chunkybuffer
, chunkybuffer_packed
,
577 chunkysize
, chunkysize
, &bodysize_packed
);
579 fprintf(stderr
, "Done packing. Success = %d\n", success
);
582 free(chunkybuffer_packed
); chunkybuffer_packed
= 0;
586 /****************************************************************************************/
588 static void gensource(void)
590 unsigned char *buffer
;
591 LONG i
, x
, buffersize
;
593 printf("#include <exec/types.h>\n");
595 printf("#define %s_WIDTH %d\n", bigimagename
, bmh
.bmh_Width
);
596 printf("#define %s_HEIGHT %d\n", bigimagename
, bmh
.bmh_Height
);
597 printf("#define %s_PACKED %d\n", bigimagename
, (chunkybuffer_packed
|| planarbuffer_packed
) ? 1 : 0);
598 printf("#define %s_PLANES %d\n", bigimagename
, bmh
.bmh_Depth
);
600 printf("#define %s_COLORS %ld\n", bigimagename
, cmapentries
);
606 printf("const ULONG %s_pal[%ld] =\n", imagename
, cmapentries
);
608 for(i
= 0; i
< cmapentries
; i
++)
610 ULONG col
= (((ULONG
)red
[i
]) << 16) +
611 (((ULONG
)green
[i
]) << 8) +
614 printf(" 0x%06lx", col
);
615 if (i
== cmapentries
- 1)
624 if (chunkybuffer_packed
)
626 buffer
= chunkybuffer_packed
;
627 buffersize
= bodysize_packed
;
631 buffer
= chunkybuffer
;
632 buffersize
= bodysize
;
635 printf("const UBYTE %s_data[%ld] =\n", imagename
, buffersize
);
640 for(x
= 0; x
< buffersize
; x
++)
642 if ((i
++ % 20) == 0) printf("\n ");
643 printf("0x%02x", buffer
[x
]);
644 if (!(x
== buffersize
- 1)) printf(",");
651 /****************************************************************************************/
653 static void genbrush2csource(void)
659 printf("#ifdef USE_%s_COLORS\n", bigimagename
);
660 printf("const ULONG %s_colors[%ld] =\n{\n", imagename
, cmapentries
* 3);
661 for (i
= 0; i
< cmapentries
; i
++)
663 printf("\t0x%08lx,0x%08lx,0x%08lx,\n",
664 (long) ((ULONG
)red
[i
] << 24 | (ULONG
)red
[i
] << 16 | (ULONG
)red
[i
] << 8 | (ULONG
)red
[i
]),
665 (long) ((ULONG
)green
[i
] << 24 | (ULONG
)green
[i
] << 16 | (ULONG
)green
[i
] << 8 | (ULONG
)green
[i
]),
666 (long) ((ULONG
)blue
[i
] << 24 | (ULONG
)blue
[i
] << 16 | (ULONG
)blue
[i
] << 8 | (ULONG
)blue
[i
]));
669 printf("#endif\n\n");
674 printf("#define %s_WIDTH %3d\n", bigimagename
, bmh
.bmh_Width
);
675 printf("#define %s_HEIGHT %3d\n", bigimagename
, bmh
.bmh_Height
);
676 printf("#define %s_DEPTH %3d\n", bigimagename
, bmh
.bmh_Depth
);
677 printf("#define %s_COMPRESSION %3d\n", bigimagename
, bmh
.bmh_Compression
);
678 printf("#define %s_MASKING %3d\n", bigimagename
, bmh
.bmh_Masking
);
681 printf("#ifdef USE_%s_HEADER\n", bigimagename
);
682 printf("const struct BitMapHeader %s_header =\n{ %ld,%ld,%ld,%ld,%ld,%ld,%ld,0,%ld,%ld,%ld,%ld,%ld };\n",
683 imagename
, (long)bmh
.bmh_Width
, (long)bmh
.bmh_Height
, (long)bmh
.bmh_Left
, (long)bmh
.bmh_Top
,
684 (long)bmh
.bmh_Depth
, (long)bmh
.bmh_Masking
, (long)bmh
.bmh_Compression
, (long)bmh
.bmh_Transparent
,
685 (long)bmh
.bmh_XAspect
, (long)bmh
.bmh_YAspect
, (long)bmh
.bmh_PageWidth
, (long)bmh
.bmh_PageHeight
);
686 printf("#endif\n\n");
688 printf("#ifdef USE_%s_BODY\n", bigimagename
);
689 printf("const UBYTE %s_body[%ld] = {\n", imagename
, bodysize
);
690 for (i
= 0; i
< bodysize
; i
++)
692 printf("0x%02lx,", (long)(body
[i
]));
693 if (!((i
+ 1) % 15)) printf("\n");
700 /****************************************************************************************/
702 static void genbrush2pixsource(void)
708 printf("const ULONG %s_colors[%ld] =\n{\n", imagename
, cmapentries
* 3);
709 for (i
= 0; i
< cmapentries
; i
++)
711 printf("\t0x%08lx,0x%08lx,0x%08lx,\n",
712 (long)((ULONG
)red
[i
] << 24 | (ULONG
)red
[i
] << 16 | (ULONG
)red
[i
] << 8 | (ULONG
)red
[i
]),
713 (long)((ULONG
)green
[i
] << 24 | (ULONG
)green
[i
] << 16 | (ULONG
)green
[i
] << 8 | (ULONG
)green
[i
]),
714 (long)((ULONG
)blue
[i
] << 24 | (ULONG
)blue
[i
] << 16 | (ULONG
)blue
[i
] << 8 | (ULONG
)blue
[i
]));
721 printf("#define %s_WIDTH %3d\n", bigimagename
, bmh
.bmh_Width
);
722 printf("#define %s_HEIGHT %3d\n", bigimagename
, bmh
.bmh_Height
);
723 printf("#define %s_DEPTH %3d\n", bigimagename
, bmh
.bmh_Depth
);
724 printf("#define %s_COMPRESSION %3d\n", bigimagename
, bmh
.bmh_Compression
);
725 printf("#define %s_MASKING %3d\n", bigimagename
, bmh
.bmh_Masking
);
728 printf("const UBYTE %s_body[%ld] = {\n", imagename
, bodysize
);
729 for (i
= 0; i
< bodysize
; i
++)
731 printf("0x%02lx,", (long)(body
[i
]));
732 if (!((i
+ 1) % 15)) printf("\n");
737 if (have_cmap
&& have_body
)
739 printf("\nmuidefpix %s_defpix =\n{\n", imagename
);
740 printf("\t%s_body,\n", imagename
);
741 printf("\t%s_colors,\n", imagename
);
742 printf("\t%s_WIDTH, %s_HEIGHT, %s_DEPTH,\n", bigimagename
, bigimagename
, bigimagename
);
743 printf("\t%s_COMPRESSION, %s_MASKING \n", bigimagename
, bigimagename
);
748 /****************************************************************************************/
750 int main(int argc
, char **argv
)
752 getarguments(argc
, argv
);
763 genbrush2pixsource();
777 /****************************************************************************************/