2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Tool to convert IFF ILBM images into Amiga icon file.
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')
29 #define ID_ICON MAKE_ID('I','C','O','N')
30 #define ID_FACE MAKE_ID('F','A','C','E')
31 #define ID_IMAG MAKE_ID('I','M','A','G')
34 #define CMP_BYTERUN1 1
38 /****************************************************************************************/
40 /* For this tool it does not really matter if the following types
41 have a bigger sizeof() than on Amiga */
45 typedef unsigned long ULONG
;
47 typedef unsigned short UWORD
;
50 typedef unsigned char UBYTE
;
52 #include <exec/types.h>
55 /****************************************************************************************/
65 UBYTE bmh_Compression
;
67 UWORD bmh_Transparent
;
74 /****************************************************************************************/
78 struct BitMapHeader bmh
;
79 struct BitMapHeader planarbmh
;
80 unsigned char *planarbuffer
, *chunkybuffer
;
81 LONG cmapentries
, bpr
, totdepth
;
83 UBYTE remaptable
[256];
86 /****************************************************************************************/
94 /****************************************************************************************/
96 struct Palette std4colpal
=
107 /****************************************************************************************/
109 static char *filename
, *outfilename
, *infilename
;
110 static unsigned char *filebuffer
, *body
;
111 static FILE *file
, *outfile
, *infile
;
112 static long filesize
, bodysize
, bodysize_packed
;
114 static struct ILBMImage img1
, img2
;
115 static BOOL have_bmhd
, have_cmap
, have_body
, is_png
;
117 static char *image1option
;
118 static char *image2option
;
119 static char *defaulttooloption
;
120 static char *drawerdataoption
;
121 static char **tooltypesoption
;
122 static LONG typeoption
= 3; /* WBTOOL */
123 static LONG iconleftoption
= 0x80000000; /* NO_ICON_POSITION */
124 static LONG icontopoption
= 0x80000000; /* NO_ICON_POSITION */
125 static LONG stackoption
= 4096;
126 static LONG drawerleftoption
= 0;
127 static LONG drawertopoption
= 20;
128 static LONG drawerwidthoption
= 300;
129 static LONG drawerheightoption
= 100;
130 static LONG drawervleftoption
= 0;
131 static LONG drawervtopoption
= 0;
132 static LONG drawershowoption
= 0;
133 static LONG drawershowasoption
= 0;
134 static LONG transparentoption
= 0;
136 /****************************************************************************************/
138 static void freeimage(struct ILBMImage
*img
)
140 if (img
->chunkybuffer
)
142 free(img
->chunkybuffer
);
143 img
->chunkybuffer
= NULL
;
146 if (img
->planarbuffer
)
148 free(img
->planarbuffer
);
149 img
->planarbuffer
= NULL
;
167 /****************************************************************************************/
169 static void cleanup(char *msg
, int rc
)
171 if (msg
) fprintf(stderr
, "ilbmtoicon: %s\n", msg
);
176 if (outfile
) fclose(outfile
);
177 if (infile
) fclose(infile
);
182 /****************************************************************************************/
184 static void getarguments(int argc
, char **argv
)
188 if ((argc
!= 4) && (argc
!= 5))
190 fprintf(stderr
, "Wrong number of arguments\n");
191 cleanup("Usage: ilbmtoicon icondescription image1 [image2] filename", 1);
196 infilename
= argv
[1];
197 image1option
= argv
[2];
198 outfilename
= argv
[3];
202 infilename
= argv
[1];
203 image1option
= argv
[2];
204 image2option
= argv
[3];
205 outfilename
= argv
[4];
209 /****************************************************************************************/
211 static char *skipblanks(char *s
)
213 while ((*s
== ' ') || (*s
== '\t')) s
++;
218 /****************************************************************************************/
220 static char *skipword(char *s
)
233 /****************************************************************************************/
235 static char *checkquotes(char *s
)
250 while((*s2
!= '"') && (*s2
!= '\0')) s2
++;
256 /****************************************************************************************/
258 #define KEYWORD_STRING 0
259 #define KEYWORD_INTEGER 1
260 #define KEYWORD_STRINGARRAY 2
261 #define KEYWORD_CYCLE 3
263 #define MAX_ARRAY_SIZE 200
265 /****************************************************************************************/
273 struct cycle typecycles
[] =
285 struct cycle showcycles
[] =
294 struct cycle showascycles
[] =
307 /****************************************************************************************/
318 {KEYWORD_STRING
, "DEFAULTTOOL" , &defaulttooloption
, NULL
},
319 {KEYWORD_STRING
, "DRAWERDATA" , &drawerdataoption
, NULL
},
320 {KEYWORD_CYCLE
, "TYPE" , &typeoption
, typecycles
},
321 {KEYWORD_STRINGARRAY
, "TOOLTYPE" , &tooltypesoption
, NULL
},
322 {KEYWORD_INTEGER
, "STACK" , &stackoption
, NULL
},
323 {KEYWORD_INTEGER
, "ICONLEFTPOS" , &iconleftoption
, NULL
},
324 {KEYWORD_INTEGER
, "ICONTOPPOS" , &icontopoption
, NULL
},
325 {KEYWORD_INTEGER
, "DRAWERLEFTPOS" , &drawerleftoption
, NULL
},
326 {KEYWORD_INTEGER
, "DRAWERTOPPOS" , &drawertopoption
, NULL
},
327 {KEYWORD_INTEGER
, "DRAWERWIDTH" , &drawerwidthoption
, NULL
},
328 {KEYWORD_INTEGER
, "DRAWERHEIGHT" , &drawerheightoption
, NULL
},
329 {KEYWORD_INTEGER
, "DRAWERVIEWLEFT" , &drawervleftoption
, NULL
},
330 {KEYWORD_INTEGER
, "DRAWERVIEWTOP" , &drawervtopoption
, NULL
},
331 {KEYWORD_CYCLE
, "DRAWERSHOW" , &drawershowoption
, showcycles
},
332 {KEYWORD_CYCLE
, "DRAWERSHOWAS" , &drawershowoption
, showascycles
},
333 {KEYWORD_INTEGER
, "TRANSPARENT" , &transparentoption
, NULL
},
338 /****************************************************************************************/
340 static void handleoption(char *keyword
, char *keyvalue
)
345 for(kw
= keywordtable
; kw
->keyword
; kw
++)
347 if (strcasecmp(kw
->keyword
, keyword
) == 0)
352 *(char **)kw
->store
= strdup(keyvalue
);
353 if (!(*(char **)kw
->store
)) cleanup("Out of memory!", 1);
356 case KEYWORD_INTEGER
:
357 *(LONG
*)kw
->store
= strtol(keyvalue
, 0, 0);
361 for(cy
= (struct cycle
*)kw
->extra
; cy
->keyword
; cy
++)
363 if (strcasecmp(keyvalue
, cy
->keyword
) == 0)
365 *(LONG
*)kw
->store
= cy
->value
;
371 case KEYWORD_STRINGARRAY
:
372 if (!(*(char ***)kw
->store
))
374 *(char ***)kw
->store
= (char **)malloc(MAX_ARRAY_SIZE
* sizeof(char *));
375 if (!(*(char ***)kw
->store
)) cleanup("Out of memory!", 1);
377 memset(*(char ***)kw
->store
, 0, MAX_ARRAY_SIZE
* sizeof(char *));
382 char **strarray
= *(char ***)kw
->store
;
385 dupvalue
= strdup(keyvalue
);
386 if (!dupvalue
) cleanup("Out of memory!", 1);
394 if (i
>= MAX_ARRAY_SIZE
- 1) cleanup("Array overflow!", 1);
396 *strarray
= dupvalue
;
399 } /* switch(kw->type) */
403 } /* if (strcasecmp(kw->keyword, keyword) == 0) */
405 } /* for(kw = keywordtable; kw->keyword; kw++) */
409 /****************************************************************************************/
411 static void parseline(char *s
)
414 char *keyvalue
= NULL
;
418 if (*s
== '#') return;
419 if (*s
== ';') return;
424 if (*s
== '\0') return;
427 s
= skipblanks(s
+ 1);
429 if (*s
== '=') s
= skipblanks(s
+ 1);
430 if (*s
== '\0') return;
432 keyvalue
= checkquotes(s
);
434 handleoption(keyword
, keyvalue
);
437 /****************************************************************************************/
439 static void parseiconsource(void)
443 infile
= fopen(infilename
, "r");
446 while(fgets(s
, sizeof(s
), infile
))
456 /****************************************************************************************/
458 static void showoptions(void)
462 printf("image1: %s\n", image1option
? image1option
: "(NULL)");
463 printf("image2: %s\n", image2option
? image2option
: "(NULL)");
464 printf("type: %d\n", typeoption
);
466 strarray
= tooltypesoption
;
469 printf("tooltypes:\n");
472 printf(" %s\n", *strarray
++);
479 /****************************************************************************************/
481 static ULONG
getlong(void)
485 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
487 ret
= filebuffer
[filepos
++] * 0x1000000;
488 ret
+= filebuffer
[filepos
++] * 0x10000;
489 ret
+= filebuffer
[filepos
++] * 0x100;
490 ret
+= filebuffer
[filepos
++];
495 /****************************************************************************************/
497 static UWORD
getword(void)
501 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
503 ret
= filebuffer
[filepos
++] * 0x100;
504 ret
+= filebuffer
[filepos
++];
509 /****************************************************************************************/
511 static UBYTE
getbyte(void)
515 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
516 ret
= filebuffer
[filepos
++];
521 /****************************************************************************************/
523 static void skipbytes(ULONG howmany
)
528 /****************************************************************************************/
530 static void openimage(struct ILBMImage
*img
)
532 file
= fopen(filename
, "rb");
533 if (!file
) cleanup("Can't open file!", 1);
535 fseek(file
, 0, SEEK_END
);
536 filesize
= ftell(file
);
538 if (filesize
< 12) cleanup("Bad file size!", 1);
540 //fprintf(stderr, "Filesize is %d\n", filesize);
542 fseek(file
, 0, SEEK_SET
);
544 filebuffer
= malloc(filesize
+ 10);
545 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
547 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
548 cleanup("Error reading file!", 1);
550 fclose(file
); file
= NULL
;
553 /****************************************************************************************/
555 static void checkimage(struct ILBMImage
*img
)
557 static UBYTE pngsig
[8] = {137, 80, 78, 71, 13, 10, 26, 10};
562 if (memcmp(filebuffer
, pngsig
, 8) == 0)
566 else if (is_png
== 0)
569 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
572 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
575 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
577 else if (is_png
== 1)
579 cleanup("Second image must be a PNG image, too!", 1);
583 /****************************************************************************************/
585 static void scanimage(struct ILBMImage
*img
)
601 //fprintf(stderr, "Chunk: %c%c%c%c Size: %d\n", id >> 24, id >> 16, id >> 8, id, size);
606 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
608 img
->bmh
.bmh_Width
= getword();
609 img
->bmh
.bmh_Height
= getword();
610 img
->bmh
.bmh_Left
= (WORD
)getword();
611 img
->bmh
.bmh_Top
= (WORD
)getword();
612 img
->bmh
.bmh_Depth
= getbyte();
613 img
->bmh
.bmh_Masking
= getbyte();
614 img
->bmh
.bmh_Compression
= getbyte();
615 img
->bmh
.bmh_Pad
= getbyte();
616 img
->bmh
.bmh_Transparent
= getword();
617 img
->bmh
.bmh_XAspect
= getbyte();
618 img
->bmh
.bmh_YAspect
= getbyte();
619 img
->bmh
.bmh_PageWidth
= (WORD
)getword();
620 img
->bmh
.bmh_PageHeight
= (WORD
)getword();
622 if (img
->bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
623 if ((img
->bmh
.bmh_Compression
!= CMP_NONE
) && (img
->bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
627 img
->totdepth
= img
->bmh
.bmh_Depth
+ ((img
->bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
629 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
631 /*fprintf(stderr, "BMHD: %d x %d x %d (%d)\n", img->bmh.bmh_Width,
635 img
->planarbmh
= img
->bmh
;
639 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
641 img
->cmapentries
= size
/ 3;
642 if (size
& 1) size
++;
644 if ((img
->cmapentries
< 2) || (img
->cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
646 for(i
= 0; i
< img
->cmapentries
; i
++)
648 img
->rgb
[i
][0] = getbyte();
649 img
->rgb
[i
][1] = getbyte();
650 img
->rgb
[i
][2] = getbyte();
661 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
662 body
= &filebuffer
[filepos
];
665 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
667 LONG shouldbesize
= img
->totdepth
* img
->bpr
* img
->bmh
.bmh_Height
;
668 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
675 if (size
& 1) size
++;
680 if (filepos
== filesize
) break;
681 if (have_bmhd
&& have_body
&& have_cmap
) break;
684 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
685 if (!have_body
) cleanup("BODY chunk missing!", 1);
688 /****************************************************************************************/
690 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
697 c
= (signed char)(*source
++);
703 if (--unpackedsize
<= 0) return source
;
714 if (--unpackedsize
<= 0) return source
;
721 /****************************************************************************************/
723 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
724 unsigned char **dest
, LONG
*checksize
)
726 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
732 if (step
> 127) step
= 127;
737 if (*checksize
<= 0) return 0;
746 *(*dest
)++ = *(*source_backup
)++;
756 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
758 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
764 if (step
> 127) step
= 127;
769 if (*checksize
<= 0) return 0;
771 *(*dest
)++ = (unsigned char)step
;
778 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
779 LONG size
, LONG check_size
, LONG
*packsize
)
781 unsigned char *source_backup
, *dest_backup
;
782 LONG samebytes_counter
, samebytes
, count
;
783 LONG checksize
= check_size
;
784 unsigned char oldbyte
, actbyte
;
786 if (checksize
< 0) checksize
= 0x7FFFFFFF;
789 samebytes_counter
= 0;
790 source_backup
= source
;
795 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
796 if (--size
< 0) break;
798 if (actbyte
== oldbyte
)
806 samebytes
= samebytes_counter
;
807 samebytes_counter
= 1;
809 if (samebytes
< 3) continue;
811 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
812 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
814 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
816 source_backup
= source
- 1;
818 //fprintf(stderr, "done\n");
820 if (samebytes_counter
>= 3)
822 samebytes
= samebytes_counter
;
823 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
824 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
825 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
829 count
= (LONG
)(source
- source_backup
- 1);
830 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
832 //fprintf(stderr, "realdone\n");
834 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
839 /****************************************************************************************/
841 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
842 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
844 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
846 alignedwidth
= (width
+ 15) & ~15;
847 bpr
= alignedwidth
/ 8;
848 bpl
= bpr
* totplanes
;
850 for(y
= 0; y
< height
; y
++)
852 for(x
= 0; x
< width
; x
++)
854 LONG mask
= 0x80 >> (x
& 7);
856 unsigned char chunkypix
= 0;
858 for(p
= 0; p
< wantplanes
; p
++)
860 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
872 /****************************************************************************************/
874 static void c2p(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
, LONG planes
)
876 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
878 alignedwidth
= (width
+ 15) & ~15;
879 bpr
= alignedwidth
/ 8;
882 for(y
= 0; y
< height
; y
++)
884 for(x
= 0; x
< width
; x
++)
886 LONG mask
= 0x80 >> (x
& 7);
888 unsigned char chunkypix
= source
[x
];
890 for(p
= 0; p
< planes
; p
++)
892 if (chunkypix
& (1 << p
))
893 dest
[p
* bpr
+ offset
] |= mask
;
895 dest
[p
* bpr
+ offset
] &= ~mask
;
905 /****************************************************************************************/
907 static void convertbody(struct ILBMImage
*img
)
909 LONG unpackedsize
= img
->bpr
* img
->bmh
.bmh_Height
* img
->totdepth
;
911 img
->planarbuffer
= malloc(unpackedsize
);
912 if (!img
->planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
914 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
916 memcpy(img
->planarbuffer
, body
, unpackedsize
);
920 unpack_byterun1(body
, img
->planarbuffer
, unpackedsize
);
923 img
->chunkybuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
924 if (!img
->chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
926 p2c(img
->planarbuffer
,
935 /****************************************************************************************/
937 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
)
939 ULONG dist
, bestdist
= 0xFFFFFFFF;
942 for(i
= 0; i
< pal
->numentries
; i
++)
944 LONG r1
, g1
, b1
, r2
, g2
, b2
, dr
, dg
, db
;
950 r2
= (LONG
)pal
->rgb
[i
][0];
951 g2
= (LONG
)pal
->rgb
[i
][1];
952 b2
= (LONG
)pal
->rgb
[i
][2];
958 dist
= (dr
* dr
) + (dg
* dg
) + (db
* db
);
970 /****************************************************************************************/
972 static void remapplanar(struct ILBMImage
*img
, struct Palette
*pal
)
975 LONG i
, x
, y
, highestcol
= 0, newdepth
= 0;
977 remapbuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
978 if (!remapbuffer
) cleanup("Error allocating remap buffer!", 1);
980 for(i
= 0; i
< img
->cmapentries
; i
++)
982 img
->remaptable
[i
] = findcolor(pal
, img
->rgb
[i
][0], img
->rgb
[i
][1], img
->rgb
[i
][2]);
985 for(i
= 0; i
< img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
; i
++)
987 remapbuffer
[i
] = img
->remaptable
[img
->chunkybuffer
[i
]];
989 if (remapbuffer
[i
] > highestcol
)
990 highestcol
= remapbuffer
[i
];
993 for(i
= highestcol
; i
; i
>>= 1) newdepth
++;
994 if (newdepth
== 0) newdepth
= 1;
996 if (newdepth
> img
->totdepth
)
998 free(img
->planarbuffer
);
1000 img
->planarbuffer
= malloc(img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1001 if (!img
->planarbuffer
)
1004 cleanup("Error re-allocating planar buffer!", 1);
1008 img
->planarbmh
.bmh_Depth
= newdepth
;
1010 memset(img
->planarbuffer
, 0, img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1012 c2p(remapbuffer
, img
->planarbuffer
, img
->bmh
.bmh_Width
, img
->bmh
.bmh_Height
, newdepth
);
1017 /****************************************************************************************/
1019 static void loadimage(char *name
, struct ILBMImage
*img
)
1034 /****************************************************************************************/
1039 UBYTE do_version
[2];
1040 UBYTE do_gadget_nextgadget
[4];
1041 UBYTE do_gadget_leftedge
[2];
1042 UBYTE do_gadget_topedge
[2];
1043 UBYTE do_gadget_width
[2];
1044 UBYTE do_gadget_height
[2];
1045 UBYTE do_gadget_flags
[2];
1046 UBYTE do_gadget_activation
[2];
1047 UBYTE do_gadget_gadgettype
[2];
1048 UBYTE do_gadget_gadgetrender
[4];
1049 UBYTE do_gadget_selectrender
[4];
1050 UBYTE do_gadget_gadgettext
[4];
1051 UBYTE do_gadget_mutualexclude
[4];
1052 UBYTE do_gadget_specialinfo
[4];
1053 UBYTE do_gadget_gadgetid
[2];
1054 UBYTE do_gadget_userdata
[4];
1057 UBYTE do_defaulttool
[4];
1058 UBYTE do_tooltypes
[4];
1059 UBYTE do_currentx
[4];
1060 UBYTE do_currenty
[4];
1061 UBYTE do_drawerdata
[4];
1062 UBYTE do_toolwindow
[4];
1063 UBYTE do_stacksize
[4];
1066 /****************************************************************************************/
1068 struct olddrawerdata
1070 UBYTE dd_newwindow_leftedge
[2];
1071 UBYTE dd_newwindow_topedge
[2];
1072 UBYTE dd_newwindow_width
[2];
1073 UBYTE dd_newwindow_height
[2];
1074 UBYTE dd_newwindow_detailpen
;
1075 UBYTE dd_newwindow_blockpen
;
1076 UBYTE dd_newwindow_idcmpflags
[4];
1077 UBYTE dd_newwindow_flags
[4];
1078 UBYTE dd_newwindow_firstgadget
[4];
1079 UBYTE dd_newwindow_checkmark
[4];
1080 UBYTE dd_newwindow_title
[4];
1081 UBYTE dd_newwindow_screen
[4];
1082 UBYTE dd_newwindow_bitmap
[4];
1083 UBYTE dd_newwindow_minwidth
[2];
1084 UBYTE dd_newwindow_minheight
[2];
1085 UBYTE dd_newwindow_maxwidth
[2];
1086 UBYTE dd_newwindow_maxheight
[2];
1087 UBYTE dd_newwindow_type
[2];
1088 UBYTE dd_currentx
[4];
1089 UBYTE dd_currenty
[4];
1092 /****************************************************************************************/
1094 struct newdrawerdata
1097 UBYTE dd_viewmodes
[2];
1100 /****************************************************************************************/
1115 /****************************************************************************************/
1117 #define SET_BYTE(field,value) \
1118 ACT_STRUCT.field = value
1120 #define SET_WORD(field, value) \
1121 ACT_STRUCT.field[0] = ((value) >> 8) & 0xFF; \
1122 ACT_STRUCT.field[1] = (value) & 0xFF;
1124 #define SET_LONG(field,value) \
1125 ACT_STRUCT.field[0] = ((value) >> 24) & 0xFF; \
1126 ACT_STRUCT.field[1] = ((value) >> 16) & 0xFF; \
1127 ACT_STRUCT.field[2] = ((value) >> 8) & 0xFF; \
1128 ACT_STRUCT.field[3] = (value) & 0xFF;
1130 #define BOOL_YES 0x2A2A2A2A
1131 #define BOOL_NO 0x00000000
1133 static void writediskobject(void)
1135 struct diskobject dobj
;
1137 #define ACT_STRUCT dobj
1139 SET_WORD(do_magic
, 0xE310);
1140 SET_WORD(do_version
, 1);
1141 SET_LONG(do_gadget_nextgadget
, 0);
1142 SET_WORD(do_gadget_leftedge
, 0);
1143 SET_WORD(do_gadget_topedge
, 0);
1144 SET_WORD(do_gadget_width
, img1
.bmh
.bmh_Width
);
1145 SET_WORD(do_gadget_height
, img1
.bmh
.bmh_Height
);
1149 /* GFLG_GADGHIMAGE + GFLG_GADGIMAGE */
1150 SET_WORD(do_gadget_flags
, 4 + 2);
1154 /* GFLG_GADGIMAGE */
1155 SET_WORD(do_gadget_flags
, 4);
1158 SET_WORD(do_gadget_activation
, 0);
1159 SET_WORD(do_gadget_gadgettype
, 0);
1160 SET_LONG(do_gadget_gadgetrender
, BOOL_YES
);
1164 SET_LONG(do_gadget_selectrender
, BOOL_YES
);
1168 SET_LONG(do_gadget_selectrender
, BOOL_NO
);
1171 SET_LONG(do_gadget_gadgettext
, 0);
1172 SET_LONG(do_gadget_mutualexclude
, 0);
1173 SET_LONG(do_gadget_specialinfo
, 0);
1174 SET_WORD(do_gadget_gadgetid
, 0);
1175 SET_LONG(do_gadget_userdata
, 1); /* full drawer data */
1177 SET_BYTE(do_type
, typeoption
);
1178 SET_BYTE(do_pad
, 0);
1180 if (defaulttooloption
)
1182 SET_LONG(do_defaulttool
, BOOL_YES
);
1186 SET_LONG(do_defaulttool
, BOOL_NO
);
1189 if (tooltypesoption
)
1191 SET_LONG(do_tooltypes
, BOOL_YES
);
1195 SET_LONG(do_tooltypes
, BOOL_NO
);
1198 SET_LONG(do_currentx
, iconleftoption
);
1199 SET_LONG(do_currenty
, icontopoption
);
1201 if (drawerdataoption
)
1203 SET_LONG(do_drawerdata
, BOOL_YES
);
1207 SET_LONG(do_drawerdata
, BOOL_NO
);
1211 SET_LONG(do_toolwindow
, 0);
1212 SET_LONG(do_stacksize
, stackoption
);
1214 if (fwrite(&dobj
, 1, sizeof(dobj
), outfile
) != sizeof(dobj
))
1216 cleanup("Error writing diskobject structure to outfile!", 1);
1220 /****************************************************************************************/
1222 static void writeolddrawerdata(void)
1224 struct olddrawerdata dd
;
1226 if (!drawerdataoption
) return;
1229 #define ACT_STRUCT dd
1231 SET_WORD(dd_newwindow_leftedge
, drawerleftoption
);
1232 SET_WORD(dd_newwindow_topedge
, drawertopoption
);
1233 SET_WORD(dd_newwindow_width
, drawerwidthoption
);
1234 SET_WORD(dd_newwindow_height
, drawerheightoption
);
1235 SET_BYTE(dd_newwindow_detailpen
, 0);
1236 SET_BYTE(dd_newwindow_blockpen
, 0);
1237 SET_LONG(dd_newwindow_idcmpflags
, 0);
1238 SET_LONG(dd_newwindow_flags
, 0);
1239 SET_LONG(dd_newwindow_firstgadget
, 0);
1240 SET_LONG(dd_newwindow_checkmark
, 0);
1241 SET_LONG(dd_newwindow_title
, 0);
1242 SET_LONG(dd_newwindow_screen
, 0);
1243 SET_LONG(dd_newwindow_bitmap
, 0);
1244 SET_WORD(dd_newwindow_minwidth
, 0);
1245 SET_WORD(dd_newwindow_minheight
, 0);
1246 SET_WORD(dd_newwindow_maxwidth
, 0);
1247 SET_WORD(dd_newwindow_maxheight
, 0);
1248 SET_WORD(dd_newwindow_type
, 0);
1249 SET_LONG(dd_currentx
, drawervleftoption
);
1250 SET_LONG(dd_currenty
, drawervtopoption
);
1252 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1254 cleanup("Error writing olddrawerdata structure to outfile!", 1);
1260 /****************************************************************************************/
1262 static void writenewdrawerdata(void)
1264 struct newdrawerdata dd
;
1266 if (!drawerdataoption
) return;
1269 #define ACT_STRUCT dd
1271 SET_LONG(dd_flags
, drawershowoption
);
1272 SET_WORD(dd_viewmodes
, drawershowasoption
);
1274 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1276 cleanup("Error writing newdrawerdata structure to outfile!", 1);
1281 /****************************************************************************************/
1283 static void writelong(LONG l
)
1287 f
[0] = (l
>> 24) & 0xFF;
1288 f
[1] = (l
>> 16) & 0xFF;
1289 f
[2] = (l
>> 8) & 0xFF;
1292 if (fwrite(f
, 1, 4, outfile
) != 4)
1294 cleanup("Error writing string long value!", 1);
1299 /****************************************************************************************/
1301 static void writenormalstring(char *s
)
1303 int len
= strlen(s
) + 1;
1305 if (fwrite(s
, 1, len
, outfile
) != len
)
1307 cleanup("Error writing string!", 1);
1312 /****************************************************************************************/
1314 static void writestring(char *s
)
1316 int len
= strlen(s
) + 1;
1320 if (fwrite(s
, 1, len
, outfile
) != len
)
1322 cleanup("Error writing string!", 1);
1327 /****************************************************************************************/
1329 static void writeimage(struct ILBMImage
*img
)
1335 #define ACT_STRUCT i
1337 SET_WORD(leftedge
, 0);
1338 SET_WORD(topedge
, 0);
1339 SET_WORD(width
, img
->planarbmh
.bmh_Width
);
1340 SET_WORD(height
, img
->planarbmh
.bmh_Height
);
1341 SET_WORD(depth
, img
->planarbmh
.bmh_Depth
);
1342 SET_LONG(imagedata
, BOOL_YES
);
1343 SET_BYTE(planepick
, (1 << img
->planarbmh
.bmh_Depth
) - 1);
1344 SET_BYTE(planeonoff
, 0);
1345 SET_LONG(nextimage
, 0);
1347 if (fwrite(&i
, 1, sizeof(i
), outfile
) != sizeof(i
))
1349 cleanup("Error writing image structure to outfile!", 1);
1352 for(d
= 0; d
< img
->planarbmh
.bmh_Depth
; d
++)
1354 UBYTE
*dat
= img
->planarbuffer
+ img
->bpr
* d
;
1356 for(y
= 0; y
< img
->planarbmh
.bmh_Height
; y
++)
1358 if(fwrite(dat
, 1, img
->bpr
, outfile
) != img
->bpr
)
1360 cleanup("Error writing image data to outfile!", 1);
1362 dat
+= (img
->planarbmh
.bmh_Depth
* img
->bpr
);
1368 /****************************************************************************************/
1376 UBYTE fc_maxpalettebytes
[2];
1379 /****************************************************************************************/
1383 UBYTE ic_transparentcolour
;
1384 UBYTE ic_numcolours
;
1386 UBYTE ic_imageformat
;
1387 UBYTE ic_paletteformat
;
1389 UBYTE ic_numimagebytes
[2];
1390 UBYTE ic_numpalettebytes
[2];
1393 /****************************************************************************************/
1395 static LONG
writefacechunk(void)
1397 struct facechunk fc
;
1401 #define ACT_STRUCT fc
1404 writelong(sizeof(struct facechunk
));
1406 SET_BYTE(fc_width
, img1
.bmh
.bmh_Width
- 1);
1407 SET_BYTE(fc_height
, img1
.bmh
.bmh_Height
- 1);
1408 SET_BYTE(fc_flags
, 0);
1409 SET_BYTE(fc_aspect
, 0); // 0x11);
1411 palbytes
= (img1
.cmapentries
> img2
.cmapentries
) ? img1
.cmapentries
: img2
.cmapentries
;
1412 palbytes
= palbytes
* 3;
1414 SET_WORD(fc_maxpalettebytes
, palbytes
- 1);
1416 if (fwrite(&fc
, 1, sizeof(fc
), outfile
) != sizeof(fc
))
1418 cleanup("Error writing face chunk!", 1);
1421 return sizeof(struct facechunk
) + 8;
1424 /****************************************************************************************/
1426 /* createrle() based on ModifyIcon source by Dirk Stöcker */
1428 /****************************************************************************************/
1430 static char * createrle(unsigned long depth
, unsigned char *dtype
, LONG
*dsize
, unsigned long size
,
1434 unsigned long bitbuf
, numbits
;
1436 long ressize
, numcopy
, numequal
;
1438 buf
= malloc(size
* 2);
1439 if (!buf
) return NULL
;
1446 k
= 0; /* the really output pointer */
1447 for(i
= 1; numequal
|| numcopy
;)
1449 if(i
< size
&& numequal
&& (src
[i
-1] == src
[i
]))
1453 else if(i
< size
&& numequal
*depth
<= 16)
1455 numcopy
+= numequal
; numequal
= 1; ++i
;
1459 /* care for end case, where it maybe better to join the two */
1460 if(i
== size
&& numcopy
+ numequal
<= 128 && (numequal
-1)*depth
<= 8)
1462 numcopy
+= numequal
; numequal
= 0;
1466 if((j
= numcopy
) > 128) j
= 128;
1467 bitbuf
= (bitbuf
<<8) | (j
-1);
1472 if((j
= numequal
) > 128) j
= 128;
1473 bitbuf
= (bitbuf
<<8) | (256-(j
-1));
1478 buf
[ressize
++] = (bitbuf
>> numbits
);
1482 bitbuf
= (bitbuf
<<depth
) | src
[k
++];
1486 buf
[ressize
++] = (bitbuf
>> numbits
);
1489 if(i
< size
&& !numcopy
&& !numequal
)
1496 buf
[ressize
++] = bitbuf
<< (8-numbits
);
1498 if(ressize
> size
) /* no RLE */
1502 for(i
= 0; i
< size
; ++i
)
1513 /****************************************************************************************/
1515 static LONG
writeimagchunk(struct ILBMImage
*img
)
1517 struct imagchunk ic
;
1519 UBYTE skippalette
= 0;
1521 LONG palsize
, gfxsize
;
1522 UBYTE palpacked
, gfxpacked
;
1524 imagsize
= sizeof(struct imagchunk
);
1526 /* if this is second image check whether palette is identical to
1527 the one of first image */
1531 if (img1
.cmapentries
== img2
.cmapentries
)
1535 for (i
= 0; i
< img1
.cmapentries
; i
++)
1537 if (img1
.rgb
[i
][0] != img2
.rgb
[i
][0]) break;
1538 if (img1
.rgb
[i
][1] != img2
.rgb
[i
][1]) break;
1539 if (img1
.rgb
[i
][2] != img2
.rgb
[i
][2]) break;
1542 if (i
== img1
.cmapentries
) skippalette
= 1;
1551 img
->cmapentries
* 3,
1552 (unsigned char *)img
->rgb
);
1554 imagsize
+= palsize
;
1557 gfx
= createrle(img
->bmh
.bmh_Depth
,
1560 img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
,
1563 imagsize
+= gfxsize
;
1566 #define ACT_STRUCT ic
1568 SET_BYTE(ic_transparentcolour
, transparentoption
);
1571 SET_BYTE(ic_numcolours
, 0);
1572 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 1 : 0); /* 1 = HasTransparentColour */
1573 SET_BYTE(ic_paletteformat
, 0);
1574 SET_WORD(ic_numpalettebytes
, 0);
1578 SET_BYTE(ic_numcolours
, img
->cmapentries
- 1);
1579 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 3 : 2); /* 2 = HasPalette */
1580 SET_BYTE(ic_paletteformat
, palpacked
);
1581 SET_WORD(ic_numpalettebytes
, palsize
- 1);
1584 SET_BYTE(ic_imageformat
, gfxpacked
);
1585 SET_BYTE(ic_depth
, img
->bmh
.bmh_Depth
);
1586 SET_WORD(ic_numimagebytes
, gfxsize
- 1);
1589 writelong(imagsize
);
1591 if (fwrite(&ic
, 1, sizeof(ic
), outfile
) != sizeof(ic
))
1593 cleanup("Error writing imag chunk!", 1);
1596 if (fwrite(gfx
, 1, gfxsize
, outfile
) != gfxsize
)
1598 cleanup("Error write gfx data in imag chunk!", 1);
1603 if (fwrite(pal
, 1, palsize
, outfile
) != palsize
)
1605 cleanup("Error write palette data in imag chunk!", 1);
1613 if (fwrite(&dummy
, 1, 1, outfile
) != 1)
1615 cleanup("Error writing imag chunk!", 1);
1621 return imagsize
+ 8;
1624 /****************************************************************************************/
1626 static void write35data(void)
1632 formsizeseek
= ftell(outfile
);
1633 writelong(0x12345678);
1636 formsize
+= writefacechunk();
1637 formsize
+= writeimagchunk(&img1
);
1638 if (image2option
) formsize
+= writeimagchunk(&img2
);
1640 fseek(outfile
, formsizeseek
, SEEK_SET
);
1641 writelong(formsize
);
1644 /****************************************************************************************/
1646 static void writeicon(void)
1648 struct diskobject dobj
;
1650 outfile
= fopen(outfilename
, "wb");
1651 if (!outfile
) cleanup("Can't open output file for writing!", 1);
1654 writeolddrawerdata();
1657 if (image2option
) writeimage(&img2
);
1659 if (defaulttooloption
) writestring(defaulttooloption
);
1661 if (tooltypesoption
)
1664 LONG numtooltypes
= 0;
1666 for(strarray
= tooltypesoption
; *strarray
; strarray
++, numtooltypes
++);
1668 writelong((numtooltypes
+ 1) * 4);
1670 for(strarray
= tooltypesoption
; *strarray
; strarray
++)
1672 writestring(*strarray
);
1677 /* toolwindow would have to be saved in between here if there is any */
1679 writenewdrawerdata();
1685 /****************************************************************************************/
1687 /* Table of CRCs of all 8-bit messages. */
1688 unsigned long crc_table
[256];
1690 /* Flag: has the table been computed? Initially false. */
1691 int crc_table_computed
= 0;
1693 /* Make the table for a fast CRC. */
1694 void make_crc_table(void)
1699 for (n
= 0; n
< 256; n
++)
1701 c
= (unsigned long) n
;
1702 for (k
= 0; k
< 8; k
++)
1705 c
= 0xedb88320L
^ (c
>> 1);
1711 crc_table_computed
= 1;
1714 /* Update a running CRC with the bytes buf[0..len-1]--the CRC
1715 should be initialized to all 1's, and the transmitted value
1716 is the 1's complement of the final running CRC (see the
1717 crc() routine below)). */
1719 unsigned long update_crc(unsigned long crc
, unsigned char *buf
,
1722 unsigned long c
= crc
;
1725 if (!crc_table_computed
)
1728 for (n
= 0; n
< len
; n
++)
1730 c
= crc_table
[(c
^ buf
[n
]) & 0xff] ^ (c
>> 8);
1735 /* Return the CRC of the bytes buf[0..len-1]. */
1736 unsigned long crc(unsigned char *buf
, int len
)
1738 return update_crc(0xffffffffL
, buf
, len
) ^ 0xffffffffL
;
1741 /****************************************************************************************/
1743 static void writepngiconattr(ULONG id
, ULONG val
, ULONG
*chunksize
, ULONG
*crc
)
1759 *crc
= update_crc(*crc
, buf
, 8);
1762 /****************************************************************************************/
1764 static void writepngiconstrattr(ULONG id
, char *val
, ULONG
*chunksize
, ULONG
*crc
)
1767 int len
= strlen(val
) + 1;
1775 *crc
= update_crc(*crc
, buf
, 4);
1778 writenormalstring(val
);
1779 *crc
= update_crc(*crc
, val
, len
);
1781 *chunksize
+= 4 + len
;
1785 /****************************************************************************************/
1787 static void writepngiconchunk(void)
1789 ULONG crc
= 0xffffffff;
1790 ULONG chunksize
= 0;
1791 ULONG sizeseek
= ftell(outfile
);
1792 UBYTE iconid
[] = {'i', 'c', 'O', 'n'};
1794 writelong(0x12345678);
1795 writelong(MAKE_ID('i', 'c', 'O', 'n'));
1797 crc
= update_crc(crc
, iconid
, 4);
1799 if (iconleftoption
!= 0x80000000)
1801 writepngiconattr(0x80001001, iconleftoption
, &chunksize
, &crc
);
1804 if (icontopoption
!= 0x80000000)
1806 writepngiconattr(0x80001002, icontopoption
, &chunksize
, &crc
);
1809 if (drawerdataoption
)
1813 writepngiconattr(0x80001003, drawerleftoption
, &chunksize
, &crc
);
1814 writepngiconattr(0x80001004, drawertopoption
, &chunksize
, &crc
);
1815 writepngiconattr(0x80001005, drawerwidthoption
, &chunksize
, &crc
);
1816 writepngiconattr(0x80001006, drawerheightoption
, &chunksize
, &crc
);
1818 if (drawershowoption
== 2) flags
|= 1;
1820 if (drawershowasoption
< 2)
1826 flags
|= ((drawershowasoption
- 2) << 2);
1828 writepngiconattr(0x80001007, flags
, &chunksize
, &crc
);
1831 writepngiconattr(0x80001009, stackoption
, &chunksize
, &crc
);
1833 if (defaulttooloption
)
1835 writepngiconstrattr(0x8000100a, defaulttooloption
, &chunksize
, &crc
);
1838 if (tooltypesoption
)
1842 for(tt
= tooltypesoption
; *tt
; tt
++)
1844 writepngiconstrattr(0x8000100b, *tt
, &chunksize
, &crc
);
1848 writelong(crc
^ 0xffffffff);
1849 fseek(outfile
, sizeseek
, SEEK_SET
);
1850 writelong(chunksize
);
1851 fseek(outfile
, 0, SEEK_END
);
1855 /****************************************************************************************/
1857 static void writepngicon(void)
1862 outfile
= fopen(outfilename
, "wb");
1863 if (!outfile
) cleanup("Can't open output file for writing!", 1);
1865 if (fwrite(filebuffer
, 1, 8, outfile
) != 8)
1867 cleanup("Error writing PNG signature!", 1);
1870 filepos
= filebuffer
+ 8;
1874 ULONG chunksize
= (filepos
[0] << 24) | (filepos
[1] << 16) |
1875 (filepos
[2] << 8) | filepos
[3];
1876 ULONG chunktype
= (filepos
[4] << 24) | (filepos
[5] << 16) |
1877 (filepos
[6] << 8) | filepos
[7];
1881 if (chunktype
== MAKE_ID('I', 'E', 'N', 'D'))
1883 writepngiconchunk();
1887 if (chunktype
!= MAKE_ID('i', 'c', 'O', 'n'))
1889 if (fwrite(filepos
, 1, chunksize
, outfile
) != chunksize
)
1891 cleanup("Error writing PNG icon file!", 1);
1895 filepos
+= chunksize
;
1898 /* Two images: If filenames are different, cat/attach the 2nd
1899 file onto the first one */
1901 if (image2option
&& strcasecmp(image1option
, image2option
))
1905 loadimage(image2option
, &img2
);
1907 if (fwrite(filebuffer
, 1, filesize
, outfile
) != filesize
)
1909 cleanup("Error writing 2nd PNG Image!", 1);
1915 /****************************************************************************************/
1917 static void remapicon(void)
1919 remapplanar(&img1
, &std4colpal
);
1920 if (image2option
) remapplanar(&img2
, &std4colpal
);
1923 /****************************************************************************************/
1925 int main(int argc
, char **argv
)
1927 getarguments(argc
, argv
);
1929 loadimage(image1option
, &img1
);
1932 if (image2option
) loadimage(image2option
, &img2
);
1944 /****************************************************************************************/