2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Tool to convert IFF ILBM images into Amiga icon file.
13 /****************************************************************************************/
22 /****************************************************************************************/
27 #define MAKE_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | ((d)))
29 #define ID_FORM MAKE_ID('F','O','R','M')
30 #define ID_ILBM MAKE_ID('I','L','B','M')
31 #define ID_CMAP MAKE_ID('C','M','A','P')
32 #define ID_BODY MAKE_ID('B','O','D','Y')
33 #define ID_BMHD MAKE_ID('B','M','H','D')
35 #define ID_ICON MAKE_ID('I','C','O','N')
36 #define ID_FACE MAKE_ID('F','A','C','E')
37 #define ID_IMAG MAKE_ID('I','M','A','G')
38 #define ID_PNG MAKE_ID('p','n','g',' ')
39 #define ID_ARGB MAKE_ID('A','R','G','B')
42 #define CMP_BYTERUN1 1
45 #define MSK_HASTRANS 2
47 /****************************************************************************************/
49 /* For this tool it does not really matter if the following types
50 have a bigger sizeof() than on Amiga */
54 typedef unsigned long ULONG
;
56 typedef unsigned short UWORD
;
59 typedef unsigned char UBYTE
;
61 #include <exec/types.h>
64 /****************************************************************************************/
74 UBYTE bmh_Compression
;
76 UWORD bmh_Transparent
;
83 /****************************************************************************************/
87 struct BitMapHeader bmh
;
88 struct BitMapHeader planarbmh
;
89 unsigned char *planarbuffer
, *chunkybuffer
;
90 LONG cmapentries
, bpr
, totdepth
;
92 UBYTE remaptable
[256];
99 /****************************************************************************************/
107 /****************************************************************************************/
109 struct Palette std4colpal
=
113 {0x95, 0x95, 0x95}, /* Gray (and transparent!) */
114 {0x00, 0x00, 0x00}, /* Black */
115 {0xFF, 0xFF, 0xFF}, /* White */
116 {0x3b, 0x67, 0xa2} /* Blue */
120 /****************************************************************************************/
122 struct Palette magicwb8colpal
=
126 {0x95, 0x95, 0x95}, /* Gray (and transparent!) */
127 {0x00, 0x00, 0x00}, /* Black */
128 {0xFF, 0xFF, 0xFF}, /* White */
129 {0x3b, 0x67, 0xa2}, /* Blue */
130 {0x7b, 0x7b, 0x7b}, /* Dk. Gray */
131 {0xaf, 0xaf, 0xaf}, /* Lt. Gray */
132 {0xaa, 0x90, 0x7c}, /* Brown */
133 {0xff, 0xa9, 0x97} /* Pink */
137 /****************************************************************************************/
139 struct Palette scalos16colpal
=
143 { 0x9c, 0x9c, 0x9c }, /* 0 - Gray */
144 { 0x00, 0x00, 0x00 }, /* 1 - Black */
145 { 0xFF, 0xFF, 0xFF }, /* 2 - White */
146 { 0x3a, 0x3a, 0xd7 }, /* 3 - Blue */
147 { 0x75, 0x75, 0x75 }, /* 4 - Med. Gray */
148 { 0xc4, 0xc4, 0xc4 }, /* 5 - Lt. Gray */
149 { 0xd7, 0xb0, 0x75 }, /* 6 - Peach */
150 { 0xeb, 0x62, 0x9c }, /* 7 - Pink */
151 { 0x13, 0x75, 0x27 }, /* 8 - Dk. Green */
152 { 0x75, 0x3a, 0x00 }, /* 9 - Brown */
153 { 0xff, 0xd7, 0x13 }, /* 10 - Yellow */
154 { 0x3a, 0x3a, 0x3a }, /* 11 - Dk. Gray */
155 { 0xc4, 0x13, 0x27 }, /* 12 - Red */
156 { 0x27, 0xb0, 0x3a }, /* 13 - Lt. Green */
157 { 0x3a, 0x75, 0xff }, /* 14 - Lt. Blue */
158 { 0xd7, 0x75, 0x27 }, /* 15 - Orange */
162 /* Convert from DPI to Amiga 'ticks' resolution */
163 #define TPD_X(x) ((11*1280*100/104/(x)+5)/10)
164 #define TPD_Y(y) ((11*1024*100/78/(y)+5)/10)
166 /****************************************************************************************/
168 static char *filename
, *outfilename
, *infilename
;
169 static unsigned char *filebuffer
, *body
;
170 static FILE *file
, *outfile
, *infile
;
171 static long filesize
, bodysize
, bodysize_packed
;
173 static struct ILBMImage img1
, img2
;
174 static BOOL have_bmhd
, have_cmap
, have_body
, is_png
;
176 /* 'ticks' per dot, corresponding to ~72dpi */
177 static ULONG tpdX
= TPD_X(72), tpdY
= TPD_Y(72);
178 static char *image1option
;
179 static char *image2option
;
180 static char *defaulttooloption
;
181 static char *drawerdataoption
;
182 static char **tooltypesoption
;
183 static LONG typeoption
= 3; /* WBTOOL */
184 static LONG iconleftoption
= 0x80000000; /* NO_ICON_POSITION */
185 static LONG icontopoption
= 0x80000000; /* NO_ICON_POSITION */
186 static LONG stackoption
= 4096;
187 static LONG drawerleftoption
= 50;
188 static LONG drawertopoption
= 50;
189 static LONG drawerwidthoption
= 400;
190 static LONG drawerheightoption
= 100;
191 static LONG drawervleftoption
= 0;
192 static LONG drawervtopoption
= 0;
193 static LONG drawershowoption
= 0;
194 static LONG drawershowasoption
= 0;
195 static LONG transparentoption
= -1;
197 static BOOL dualpng
; /* png file contains second image */
198 static unsigned char *dualpngstart
; /* address of 2nd image in filebuffer */
199 static BOOL nosavePNG
; /* Don't save the original PNG data */
200 static BOOL nosaveARGB
; /* Don't ARGB data */
201 static BOOL nosaveIFF
; /* Don't save any IFF data */
203 /****************************************************************************************/
205 static void freeimage(struct ILBMImage
*img
)
207 if (img
->chunkybuffer
)
209 free(img
->chunkybuffer
);
210 img
->chunkybuffer
= NULL
;
213 if (img
->planarbuffer
)
215 free(img
->planarbuffer
);
216 img
->planarbuffer
= NULL
;
240 /****************************************************************************************/
242 static void cleanup(char *msg
, int rc
)
244 if (msg
) fprintf(stderr
, "ilbmtoicon: %s\n", msg
);
249 if (outfile
) fclose(outfile
);
250 if (infile
) fclose(infile
);
255 /****************************************************************************************/
257 static void getarguments(int argc
, char **argv
)
263 for (; argc
> 1 && argv
[1][0] == '-'; argc
--, argv
++) {
264 if (strcmp(argv
[1],"--png") == 0) {
268 if (strcmp(argv
[1],"--no-iff") == 0) {
272 if (strcmp(argv
[1],"--no-argb") == 0) {
276 if (strcmp(argv
[1],"--dpi") == 0) {
281 dpiX
= strtol(argv
[1], &cp
, 0);
284 dpiY
= strtol(cp
, NULL
, 0);
295 if ((argc
!= 4) && (argc
!= 5))
297 fprintf(stderr
, "Wrong number of arguments\n");
298 cleanup("Usage: ilbmtoicon [--png] [--no-argb] [--no-iff] icondescription image1 [image2] filename", 1);
303 infilename
= argv
[1];
304 image1option
= argv
[2];
305 outfilename
= argv
[3];
309 infilename
= argv
[1];
310 image1option
= argv
[2];
311 image2option
= argv
[3];
312 outfilename
= argv
[4];
316 /****************************************************************************************/
318 static char *skipblanks(char *s
)
320 while ((*s
== ' ') || (*s
== '\t')) s
++;
325 /****************************************************************************************/
327 static char *skipword(char *s
)
340 /****************************************************************************************/
342 static char *checkquotes(char *s
)
360 while ((i
< 256) && (s3
[i
] = *s
))
383 /****************************************************************************************/
385 #define KEYWORD_STRING 0
386 #define KEYWORD_INTEGER 1
387 #define KEYWORD_STRINGARRAY 2
388 #define KEYWORD_CYCLE 3
390 #define MAX_ARRAY_SIZE 200
392 /****************************************************************************************/
400 struct cycle typecycles
[] =
412 struct cycle showcycles
[] =
421 struct cycle showascycles
[] =
434 /****************************************************************************************/
445 {KEYWORD_STRING
, "DEFAULTTOOL" , &defaulttooloption
, NULL
},
446 {KEYWORD_STRING
, "DRAWERDATA" , &drawerdataoption
, NULL
},
447 {KEYWORD_CYCLE
, "TYPE" , &typeoption
, typecycles
},
448 {KEYWORD_STRINGARRAY
, "TOOLTYPE" , &tooltypesoption
, NULL
},
449 {KEYWORD_INTEGER
, "STACK" , &stackoption
, NULL
},
450 {KEYWORD_INTEGER
, "ICONLEFTPOS" , &iconleftoption
, NULL
},
451 {KEYWORD_INTEGER
, "ICONTOPPOS" , &icontopoption
, NULL
},
452 {KEYWORD_INTEGER
, "DRAWERLEFTPOS" , &drawerleftoption
, NULL
},
453 {KEYWORD_INTEGER
, "DRAWERTOPPOS" , &drawertopoption
, NULL
},
454 {KEYWORD_INTEGER
, "DRAWERWIDTH" , &drawerwidthoption
, NULL
},
455 {KEYWORD_INTEGER
, "DRAWERHEIGHT" , &drawerheightoption
, NULL
},
456 {KEYWORD_INTEGER
, "DRAWERVIEWLEFT" , &drawervleftoption
, NULL
},
457 {KEYWORD_INTEGER
, "DRAWERVIEWTOP" , &drawervtopoption
, NULL
},
458 {KEYWORD_CYCLE
, "DRAWERSHOW" , &drawershowoption
, showcycles
},
459 {KEYWORD_CYCLE
, "DRAWERSHOWAS" , &drawershowoption
, showascycles
},
460 {KEYWORD_INTEGER
, "TRANSPARENT" , &transparentoption
, NULL
},
465 /****************************************************************************************/
467 static void handleoption(char *keyword
, char *keyvalue
)
472 D(printf("Keyword %s, value %s\n", keyword
, keyvalue
));
474 for(kw
= keywordtable
; kw
->keyword
; kw
++)
476 if (strcasecmp(kw
->keyword
, keyword
) == 0)
481 *(char **)kw
->store
= strdup(keyvalue
);
482 if (!(*(char **)kw
->store
)) cleanup("Out of memory!", 1);
485 case KEYWORD_INTEGER
:
486 *(LONG
*)kw
->store
= strtol(keyvalue
, 0, 0);
490 for(cy
= (struct cycle
*)kw
->extra
; cy
->keyword
; cy
++)
492 if (strcasecmp(keyvalue
, cy
->keyword
) == 0)
494 *(LONG
*)kw
->store
= cy
->value
;
500 case KEYWORD_STRINGARRAY
:
501 if (!(*(char ***)kw
->store
))
503 *(char ***)kw
->store
= (char **)malloc(MAX_ARRAY_SIZE
* sizeof(char *));
504 if (!(*(char ***)kw
->store
)) cleanup("Out of memory!", 1);
506 memset(*(char ***)kw
->store
, 0, MAX_ARRAY_SIZE
* sizeof(char *));
511 char **strarray
= *(char ***)kw
->store
;
514 dupvalue
= strdup(keyvalue
);
515 if (!dupvalue
) cleanup("Out of memory!", 1);
523 if (i
>= MAX_ARRAY_SIZE
- 1) cleanup("Array overflow!", 1);
525 *strarray
= dupvalue
;
528 } /* switch(kw->type) */
532 } /* if (strcasecmp(kw->keyword, keyword) == 0) */
534 } /* for(kw = keywordtable; kw->keyword; kw++) */
538 /****************************************************************************************/
540 static void parseline(char *s
)
543 char *keyvalue
= NULL
;
547 if (*s
== '#') return;
548 if (*s
== ';') return;
553 if (*s
== '\0') return;
556 s
= skipblanks(s
+ 1);
558 if (*s
== '=') s
= skipblanks(s
+ 1);
559 if (*s
== '\0') return;
561 keyvalue
= checkquotes(s
);
563 handleoption(keyword
, keyvalue
);
566 /****************************************************************************************/
568 static void parseiconsource(void)
572 infile
= fopen(infilename
, "r");
575 while(fgets(s
, sizeof(s
), infile
))
577 D(printf("Read line: %s\n", s
));
586 /****************************************************************************************/
588 static void showoptions(void)
592 printf("image1: %s\n", image1option
? image1option
: "(NULL)");
593 printf("image2: %s\n", image2option
? image2option
: "(NULL)");
594 printf("type: %ld\n", typeoption
);
596 strarray
= tooltypesoption
;
599 printf("tooltypes:\n");
602 printf(" %s\n", *strarray
++);
607 /****************************************************************************************/
609 static ULONG
getlong(void)
613 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
615 ret
= filebuffer
[filepos
++] * 0x1000000;
616 ret
+= filebuffer
[filepos
++] * 0x10000;
617 ret
+= filebuffer
[filepos
++] * 0x100;
618 ret
+= filebuffer
[filepos
++];
623 /****************************************************************************************/
625 static UWORD
getword(void)
629 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
631 ret
= filebuffer
[filepos
++] * 0x100;
632 ret
+= filebuffer
[filepos
++];
637 /****************************************************************************************/
639 static UBYTE
getbyte(void)
643 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
644 ret
= filebuffer
[filepos
++];
649 /****************************************************************************************/
651 static void skipbytes(ULONG howmany
)
656 /****************************************************************************************/
658 static void openimage(struct ILBMImage
*img
)
660 file
= fopen(filename
, "rb");
661 if (!file
) cleanup("Can't open file!", 1);
663 fseek(file
, 0, SEEK_END
);
664 filesize
= ftell(file
);
666 if (filesize
< 12) cleanup("Bad file size!", 1);
668 //fprintf(stderr, "Filesize is %d\n", filesize);
670 fseek(file
, 0, SEEK_SET
);
672 filebuffer
= malloc(filesize
+ 10);
673 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
675 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
676 cleanup("Error reading file!", 1);
678 fclose(file
); file
= NULL
;
681 /****************************************************************************************/
683 static void checkimage(struct ILBMImage
*img
)
685 static UBYTE pngsig
[8] = {137, 80, 78, 71, 13, 10, 26, 10};
691 img
->png
= dualpngstart
;
692 img
->png_size
= filesize
- (dualpngstart
- filebuffer
);
696 if (memcmp(filebuffer
, pngsig
, 8) == 0)
699 img
->png
= filebuffer
;
701 /* search for second image */
704 dualpngstart
= filebuffer
+ 8 ;
705 dualpngstart
< filebuffer
+ filesize
- 8 ;
709 if (memcmp(dualpngstart
, pngsig
, 8) == 0)
716 img
->png_size
= dualpngstart
- filebuffer
;
718 img
->png_size
= filesize
;
720 else if (is_png
== 0)
723 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
726 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
729 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
731 else if (is_png
== 1)
733 cleanup("Second image must be a PNG image, too!", 1);
738 /****************************************************************************************/
740 static void my_read_fn(png_structp png_ptr
, png_bytep data
, png_size_t length
)
742 png_bytep
*pdata
= png_get_io_ptr(png_ptr
);
744 if (*pdata
-filebuffer
>= filesize
)
745 png_error(png_ptr
, "Read past end of file");
747 memcpy(data
, *pdata
, length
);
751 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
);
753 static void loadpng(struct ILBMImage
*img
, struct Palette
*pal
)
756 png_infop info_ptr
, end_info
;
757 png_bytep fpos
, *row_pointers
;
762 if (png_sig_cmp(img
->png
, 0, img
->png_size
) != 0)
763 cleanup("I thought it was a PNG, but I was wrong.", 1);
765 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
,
770 cleanup("png_create_read_struct() failed", 1);
772 info_ptr
= png_create_info_struct(png_ptr
);
774 png_destroy_read_struct(&png_ptr
, NULL
, NULL
);
775 cleanup("png_create_info_struct() failed", 1);
778 end_info
= png_create_info_struct(png_ptr
);
780 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
781 cleanup("png_create_info_struct() failed", 1);
785 png_set_read_fn(png_ptr
, &fpos
, my_read_fn
);
787 if (setjmp(png_jmpbuf(png_ptr
))) {
788 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
789 cleanup("png read failed", 1);
792 /* Read the PNG as RGBA */
793 png_set_add_alpha(png_ptr
, 255, PNG_FILLER_AFTER
);
794 png_read_png(png_ptr
, info_ptr
, PNG_TRANSFORM_EXPAND
| PNG_TRANSFORM_STRIP_16
, NULL
);
796 row_pointers
= png_get_rows(png_ptr
, info_ptr
);
798 width
= png_get_image_width(png_ptr
, info_ptr
);
799 height
= png_get_image_height(png_ptr
, info_ptr
);
801 img
->bmh
.bmh_Width
= width
;
802 img
->bmh
.bmh_Height
= height
;
803 img
->bmh
.bmh_Left
= 0;
804 img
->bmh
.bmh_Top
= 0;
805 img
->bmh
.bmh_Depth
= 8;
806 img
->bmh
.bmh_Masking
= MSK_HASTRANS
;
807 img
->bmh
.bmh_Compression
= CMP_NONE
;
808 img
->bmh
.bmh_Pad
= 0;
809 img
->bmh
.bmh_XAspect
= 1;
810 img
->bmh
.bmh_YAspect
= 1;
811 img
->bmh
.bmh_PageWidth
= 320;
812 img
->bmh
.bmh_PageHeight
= 200;
815 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
818 /* Transform the RGBA data into chunky */
819 img
->cmapentries
= pal
->numentries
;
820 memcpy(img
->rgb
, pal
->rgb
, sizeof(img
->rgb
[0])*pal
->numentries
);
822 img
->chunkybuffer
= malloc(width
* height
* sizeof(UBYTE
));
823 if (!img
->chunkybuffer
)
824 cleanup("Can't allocate the chunky buffer", 1);
826 chunkrow
= img
->chunkybuffer
;
827 img
->argb_size
= width
* height
* sizeof(UBYTE
) * 4;
828 img
->argb
= malloc(img
->argb_size
);
830 cleanup("Can't allocate the ARGB buffer", 1);
832 for (y
= 0; y
< height
; y
++) {
833 png_bytep row
= row_pointers
[y
];
834 UBYTE
*ap
= img
->argb
+ (width
* sizeof(UBYTE
) * 4) * y
;
835 for (x
= 0; x
< width
; x
++, row
+= 4, ap
+= 4, chunkrow
++) {
843 /* Opacity of 0? Use the transparency color */
845 if (transparentoption
< 0)
846 transparentoption
= 0;
847 *chunkrow
= transparentoption
;
853 *chunkrow
= findcolor(pal
, r
, g
, b
, TRUE
);
858 img
->bmh
.bmh_Transparent
= transparentoption
;
860 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
864 /****************************************************************************************/
866 static void scanimage(struct ILBMImage
*img
)
875 /* Load the PNG, using the Scalos 16-color pallette,
876 * into the Chunky buffer.
878 loadpng(img
, &scalos16colpal
);
890 //fprintf(stderr, "Chunk: %c%c%c%c Size: %d\n", id >> 24, id >> 16, id >> 8, id, size);
895 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
897 img
->bmh
.bmh_Width
= getword();
898 img
->bmh
.bmh_Height
= getword();
899 img
->bmh
.bmh_Left
= (WORD
)getword();
900 img
->bmh
.bmh_Top
= (WORD
)getword();
901 img
->bmh
.bmh_Depth
= getbyte();
902 img
->bmh
.bmh_Masking
= getbyte();
903 img
->bmh
.bmh_Compression
= getbyte();
904 img
->bmh
.bmh_Pad
= getbyte();
905 img
->bmh
.bmh_Transparent
= getword();
906 img
->bmh
.bmh_XAspect
= getbyte();
907 img
->bmh
.bmh_YAspect
= getbyte();
908 img
->bmh
.bmh_PageWidth
= (WORD
)getword();
909 img
->bmh
.bmh_PageHeight
= (WORD
)getword();
911 if (img
->bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
912 if ((img
->bmh
.bmh_Compression
!= CMP_NONE
) && (img
->bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
916 img
->totdepth
= img
->bmh
.bmh_Depth
+ ((img
->bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
918 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
920 /*fprintf(stderr, "BMHD: %d x %d x %d (%d)\n", img->bmh.bmh_Width,
924 img
->planarbmh
= img
->bmh
;
928 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
930 img
->cmapentries
= size
/ 3;
931 if (size
& 1) size
++;
933 if ((img
->cmapentries
< 2) || (img
->cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
935 for(i
= 0; i
< img
->cmapentries
; i
++)
937 img
->rgb
[i
][0] = getbyte();
938 img
->rgb
[i
][1] = getbyte();
939 img
->rgb
[i
][2] = getbyte();
950 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
951 body
= &filebuffer
[filepos
];
954 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
956 LONG shouldbesize
= img
->totdepth
* img
->bpr
* img
->bmh
.bmh_Height
;
957 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
964 if (size
& 1) size
++;
969 if (filepos
== filesize
) break;
970 if (have_bmhd
&& have_body
&& have_cmap
) break;
973 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
974 if (!have_body
) cleanup("BODY chunk missing!", 1);
977 /****************************************************************************************/
979 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
986 c
= (signed char)(*source
++);
992 if (--unpackedsize
<= 0) return source
;
1003 if (--unpackedsize
<= 0) return source
;
1010 /****************************************************************************************/
1012 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
1013 unsigned char **dest
, LONG
*checksize
)
1015 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
1021 if (step
> 127) step
= 127;
1026 if (*checksize
<= 0) return 0;
1035 *(*dest
)++ = *(*source_backup
)++;
1045 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
1047 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
1053 if (step
> 127) step
= 127;
1058 if (*checksize
<= 0) return 0;
1060 *(*dest
)++ = (unsigned char)step
;
1067 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
1068 LONG size
, LONG check_size
, LONG
*packsize
)
1070 unsigned char *source_backup
, *dest_backup
;
1071 LONG samebytes_counter
, samebytes
, count
;
1072 LONG checksize
= check_size
;
1073 unsigned char oldbyte
, actbyte
;
1075 if (checksize
< 0) checksize
= 0x7FFFFFFF;
1078 samebytes_counter
= 0;
1079 source_backup
= source
;
1084 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
1085 if (--size
< 0) break;
1086 actbyte
= *source
++;
1087 if (actbyte
== oldbyte
)
1089 samebytes_counter
++;
1095 samebytes
= samebytes_counter
;
1096 samebytes_counter
= 1;
1098 if (samebytes
< 3) continue;
1100 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
1101 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1103 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1105 source_backup
= source
- 1;
1107 //fprintf(stderr, "done\n");
1109 if (samebytes_counter
>= 3)
1111 samebytes
= samebytes_counter
;
1112 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
1113 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1114 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1118 count
= (LONG
)(source
- source_backup
- 1);
1119 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1121 //fprintf(stderr, "realdone\n");
1123 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
1128 /****************************************************************************************/
1130 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
1131 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
1133 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1135 alignedwidth
= (width
+ 15) & ~15;
1136 bpr
= alignedwidth
/ 8;
1137 bpl
= bpr
* totplanes
;
1139 for(y
= 0; y
< height
; y
++)
1141 for(x
= 0; x
< width
; x
++)
1143 LONG mask
= 0x80 >> (x
& 7);
1144 LONG offset
= x
/ 8;
1145 unsigned char chunkypix
= 0;
1147 for(p
= 0; p
< wantplanes
; p
++)
1149 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
1151 dest
[x
] = chunkypix
;
1161 /****************************************************************************************/
1163 static void c2p(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
, LONG planes
)
1165 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1167 alignedwidth
= (width
+ 15) & ~15;
1168 bpr
= alignedwidth
/ 8;
1171 for(y
= 0; y
< height
; y
++)
1173 for(x
= 0; x
< width
; x
++)
1175 LONG mask
= 0x80 >> (x
& 7);
1176 LONG offset
= x
/ 8;
1177 unsigned char chunkypix
= source
[x
];
1179 for(p
= 0; p
< planes
; p
++)
1181 if (chunkypix
& (1 << p
))
1182 dest
[p
* bpr
+ offset
] |= mask
;
1184 dest
[p
* bpr
+ offset
] &= ~mask
;
1194 /****************************************************************************************/
1196 static void convertbody(struct ILBMImage
*img
)
1198 LONG unpackedsize
= img
->bpr
* img
->bmh
.bmh_Height
* img
->totdepth
;
1203 img
->planarbuffer
= malloc(unpackedsize
);
1204 if (!img
->planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
1206 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
1208 memcpy(img
->planarbuffer
, body
, unpackedsize
);
1212 unpack_byterun1(body
, img
->planarbuffer
, unpackedsize
);
1215 img
->chunkybuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1216 if (!img
->chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
1218 p2c(img
->planarbuffer
,
1221 img
->bmh
.bmh_Height
,
1224 img
->bmh
.bmh_Width
);
1227 /****************************************************************************************/
1229 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
)
1231 ULONG dist
, bestdist
= 0xFFFFFFFF;
1234 for(i
= 0; i
< pal
->numentries
; i
++)
1236 LONG r1
, g1
, b1
, r2
, g2
, b2
, dr
, dg
, db
;
1238 if (notrans
&& i
== transparentoption
)
1245 r2
= (LONG
)pal
->rgb
[i
][0];
1246 g2
= (LONG
)pal
->rgb
[i
][1];
1247 b2
= (LONG
)pal
->rgb
[i
][2];
1253 dist
= (dr
* dr
) + (dg
* dg
) + (db
* db
);
1254 if (dist
< bestdist
)
1265 /****************************************************************************************/
1267 static void remapplanar(struct ILBMImage
*img
, struct Palette
*pal
)
1270 LONG i
, x
, y
, highestcol
= 0, newdepth
= 0;
1272 remapbuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1273 if (!remapbuffer
) cleanup("Error allocating remap buffer!", 1);
1275 for(i
= 0; i
< img
->cmapentries
; i
++)
1277 img
->remaptable
[i
] = findcolor(pal
, img
->rgb
[i
][0], img
->rgb
[i
][1], img
->rgb
[i
][2], FALSE
);
1280 for(i
= 0; i
< img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
; i
++)
1282 remapbuffer
[i
] = img
->remaptable
[img
->chunkybuffer
[i
]];
1284 if (remapbuffer
[i
] > highestcol
)
1285 highestcol
= remapbuffer
[i
];
1288 for(i
= highestcol
; i
; i
>>= 1) newdepth
++;
1289 if (newdepth
== 0) newdepth
= 1;
1291 if (newdepth
> img
->totdepth
)
1293 if (img
->planarbuffer
)
1294 free(img
->planarbuffer
);
1296 img
->planarbuffer
= malloc(img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1297 if (!img
->planarbuffer
)
1300 cleanup("Error re-allocating planar buffer!", 1);
1304 img
->planarbmh
.bmh_Width
= img
->bmh
.bmh_Width
;
1305 img
->planarbmh
.bmh_Height
= img
->bmh
.bmh_Height
;
1306 img
->planarbmh
.bmh_Depth
= newdepth
;
1308 memset(img
->planarbuffer
, 0, img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1310 c2p(remapbuffer
, img
->planarbuffer
, img
->bmh
.bmh_Width
, img
->bmh
.bmh_Height
, newdepth
);
1315 /****************************************************************************************/
1317 static void loadimage(char *name
, struct ILBMImage
*img
)
1329 /****************************************************************************************/
1334 UBYTE do_version
[2];
1335 UBYTE do_gadget_nextgadget
[4];
1336 UBYTE do_gadget_leftedge
[2];
1337 UBYTE do_gadget_topedge
[2];
1338 UBYTE do_gadget_width
[2];
1339 UBYTE do_gadget_height
[2];
1340 UBYTE do_gadget_flags
[2];
1341 UBYTE do_gadget_activation
[2];
1342 UBYTE do_gadget_gadgettype
[2];
1343 UBYTE do_gadget_gadgetrender
[4];
1344 UBYTE do_gadget_selectrender
[4];
1345 UBYTE do_gadget_gadgettext
[4];
1346 UBYTE do_gadget_mutualexclude
[4];
1347 UBYTE do_gadget_specialinfo
[4];
1348 UBYTE do_gadget_gadgetid
[2];
1349 UBYTE do_gadget_userdata
[4];
1352 UBYTE do_defaulttool
[4];
1353 UBYTE do_tooltypes
[4];
1354 UBYTE do_currentx
[4];
1355 UBYTE do_currenty
[4];
1356 UBYTE do_drawerdata
[4];
1357 UBYTE do_toolwindow
[4];
1358 UBYTE do_stacksize
[4];
1361 /****************************************************************************************/
1363 struct olddrawerdata
1365 UBYTE dd_newwindow_leftedge
[2];
1366 UBYTE dd_newwindow_topedge
[2];
1367 UBYTE dd_newwindow_width
[2];
1368 UBYTE dd_newwindow_height
[2];
1369 UBYTE dd_newwindow_detailpen
;
1370 UBYTE dd_newwindow_blockpen
;
1371 UBYTE dd_newwindow_idcmpflags
[4];
1372 UBYTE dd_newwindow_flags
[4];
1373 UBYTE dd_newwindow_firstgadget
[4];
1374 UBYTE dd_newwindow_checkmark
[4];
1375 UBYTE dd_newwindow_title
[4];
1376 UBYTE dd_newwindow_screen
[4];
1377 UBYTE dd_newwindow_bitmap
[4];
1378 UBYTE dd_newwindow_minwidth
[2];
1379 UBYTE dd_newwindow_minheight
[2];
1380 UBYTE dd_newwindow_maxwidth
[2];
1381 UBYTE dd_newwindow_maxheight
[2];
1382 UBYTE dd_newwindow_type
[2];
1383 UBYTE dd_currentx
[4];
1384 UBYTE dd_currenty
[4];
1387 /****************************************************************************************/
1389 struct newdrawerdata
1392 UBYTE dd_viewmodes
[2];
1395 /****************************************************************************************/
1410 /****************************************************************************************/
1412 #define SET_BYTE(field,value) \
1413 ACT_STRUCT.field = value
1415 #define SET_WORD(field, value) \
1416 ACT_STRUCT.field[0] = ((value) >> 8) & 0xFF; \
1417 ACT_STRUCT.field[1] = (value) & 0xFF;
1419 #define SET_LONG(field,value) \
1420 ACT_STRUCT.field[0] = ((value) >> 24) & 0xFF; \
1421 ACT_STRUCT.field[1] = ((value) >> 16) & 0xFF; \
1422 ACT_STRUCT.field[2] = ((value) >> 8) & 0xFF; \
1423 ACT_STRUCT.field[3] = (value) & 0xFF;
1425 #define BOOL_YES 0x2A2A2A2A
1426 #define BOOL_NO 0x00000000
1428 static void writediskobject(void)
1430 struct diskobject dobj
;
1432 if (typeoption
== 2) /* DRAWER */
1434 drawerdataoption
= "YES";
1437 #define ACT_STRUCT dobj
1439 SET_WORD(do_magic
, 0xE310);
1440 SET_WORD(do_version
, 1);
1441 SET_LONG(do_gadget_nextgadget
, 0);
1442 SET_WORD(do_gadget_leftedge
, 0);
1443 SET_WORD(do_gadget_topedge
, 0);
1444 SET_WORD(do_gadget_width
, img1
.bmh
.bmh_Width
);
1445 SET_WORD(do_gadget_height
, img1
.bmh
.bmh_Height
);
1449 /* GFLG_GADGHIMAGE + GFLG_GADGIMAGE */
1450 SET_WORD(do_gadget_flags
, 4 + 2);
1454 /* GFLG_GADGIMAGE */
1455 SET_WORD(do_gadget_flags
, 4);
1458 SET_WORD(do_gadget_activation
, 1);
1459 SET_WORD(do_gadget_gadgettype
, 1);
1460 SET_LONG(do_gadget_gadgetrender
, BOOL_YES
);
1464 SET_LONG(do_gadget_selectrender
, BOOL_YES
);
1468 SET_LONG(do_gadget_selectrender
, BOOL_NO
);
1471 SET_LONG(do_gadget_gadgettext
, 0);
1472 SET_LONG(do_gadget_mutualexclude
, (1 << 31) | (tpdX
<< 8) | (tpdY
<< 0));
1473 SET_LONG(do_gadget_specialinfo
, 0);
1474 SET_WORD(do_gadget_gadgetid
, 0);
1475 SET_LONG(do_gadget_userdata
, 1); /* full drawer data */
1477 SET_BYTE(do_type
, typeoption
);
1478 SET_BYTE(do_pad
, 0);
1480 if (defaulttooloption
)
1482 SET_LONG(do_defaulttool
, BOOL_YES
);
1486 SET_LONG(do_defaulttool
, BOOL_NO
);
1489 if (tooltypesoption
)
1491 SET_LONG(do_tooltypes
, BOOL_YES
);
1495 SET_LONG(do_tooltypes
, BOOL_NO
);
1498 SET_LONG(do_currentx
, iconleftoption
);
1499 SET_LONG(do_currenty
, icontopoption
);
1501 if (drawerdataoption
)
1503 SET_LONG(do_drawerdata
, BOOL_YES
);
1507 SET_LONG(do_drawerdata
, BOOL_NO
);
1511 SET_LONG(do_toolwindow
, 0);
1512 SET_LONG(do_stacksize
, stackoption
);
1514 if (fwrite(&dobj
, 1, sizeof(dobj
), outfile
) != sizeof(dobj
))
1516 cleanup("Error writing diskobject structure to outfile!", 1);
1520 /****************************************************************************************/
1522 static void writeolddrawerdata(void)
1524 struct olddrawerdata dd
;
1526 if (!drawerdataoption
) return;
1529 #define ACT_STRUCT dd
1531 SET_WORD(dd_newwindow_leftedge
, drawerleftoption
);
1532 SET_WORD(dd_newwindow_topedge
, drawertopoption
);
1533 SET_WORD(dd_newwindow_width
, drawerwidthoption
);
1534 SET_WORD(dd_newwindow_height
, drawerheightoption
);
1535 SET_BYTE(dd_newwindow_detailpen
, 255);
1536 SET_BYTE(dd_newwindow_blockpen
, 255);
1537 SET_LONG(dd_newwindow_idcmpflags
, 0);
1538 SET_LONG(dd_newwindow_flags
, 0x240027f);
1539 SET_LONG(dd_newwindow_firstgadget
, 0);
1540 SET_LONG(dd_newwindow_checkmark
, 0);
1541 SET_LONG(dd_newwindow_title
, 0);
1542 SET_LONG(dd_newwindow_screen
, 0);
1543 SET_LONG(dd_newwindow_bitmap
, 0);
1544 SET_WORD(dd_newwindow_minwidth
, 90);
1545 SET_WORD(dd_newwindow_minheight
, 40);
1546 SET_WORD(dd_newwindow_maxwidth
, 65535);
1547 SET_WORD(dd_newwindow_maxheight
, 65535);
1548 SET_WORD(dd_newwindow_type
, 1);
1549 SET_LONG(dd_currentx
, drawervleftoption
);
1550 SET_LONG(dd_currenty
, drawervtopoption
);
1552 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1554 cleanup("Error writing olddrawerdata structure to outfile!", 1);
1560 /****************************************************************************************/
1562 static void writenewdrawerdata(void)
1564 struct newdrawerdata dd
;
1566 if (!drawerdataoption
) return;
1569 #define ACT_STRUCT dd
1571 SET_LONG(dd_flags
, drawershowoption
);
1572 SET_WORD(dd_viewmodes
, drawershowasoption
);
1574 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1576 cleanup("Error writing newdrawerdata structure to outfile!", 1);
1581 /****************************************************************************************/
1583 static void writeword(WORD l
)
1587 f
[1] = (l
>> 8) & 0xFF;
1590 if (fwrite(f
, 1, 2, outfile
) != 2)
1592 cleanup("Error writing word value!", 1);
1597 /****************************************************************************************/
1599 static void writelong(LONG l
)
1603 f
[0] = (l
>> 24) & 0xFF;
1604 f
[1] = (l
>> 16) & 0xFF;
1605 f
[2] = (l
>> 8) & 0xFF;
1608 if (fwrite(f
, 1, 4, outfile
) != 4)
1610 cleanup("Error writing long value!", 1);
1615 /****************************************************************************************/
1617 static void writenormalstring(char *s
)
1619 int len
= strlen(s
) + 1;
1621 if (fwrite(s
, 1, len
, outfile
) != len
)
1623 cleanup("Error writing string!", 1);
1628 /****************************************************************************************/
1630 static void writestring(char *s
)
1632 int len
= strlen(s
) + 1;
1634 D(printf("String: \"%s\", length %d\n", s
, len
));
1638 if (fwrite(s
, 1, len
, outfile
) != len
)
1640 cleanup("Error writing string!", 1);
1645 /****************************************************************************************/
1647 static void writeimage(struct ILBMImage
*img
)
1653 #define ACT_STRUCT i
1655 SET_WORD(leftedge
, 0);
1656 SET_WORD(topedge
, 0);
1657 SET_WORD(width
, img
->planarbmh
.bmh_Width
);
1658 SET_WORD(height
, img
->planarbmh
.bmh_Height
);
1659 SET_WORD(depth
, img
->planarbmh
.bmh_Depth
);
1660 SET_LONG(imagedata
, BOOL_YES
);
1661 SET_BYTE(planepick
, (1 << img
->planarbmh
.bmh_Depth
) - 1);
1662 SET_BYTE(planeonoff
, 0);
1663 SET_LONG(nextimage
, 0);
1665 if (fwrite(&i
, 1, sizeof(i
), outfile
) != sizeof(i
))
1667 cleanup("Error writing image structure to outfile!", 1);
1670 for(d
= 0; d
< img
->planarbmh
.bmh_Depth
; d
++)
1672 UBYTE
*dat
= img
->planarbuffer
+ img
->bpr
* d
;
1674 for(y
= 0; y
< img
->planarbmh
.bmh_Height
; y
++)
1676 if(fwrite(dat
, 1, img
->bpr
, outfile
) != img
->bpr
)
1678 cleanup("Error writing image data to outfile!", 1);
1680 dat
+= (img
->planarbmh
.bmh_Depth
* img
->bpr
);
1686 /****************************************************************************************/
1694 UBYTE fc_maxpalettebytes
[2];
1697 /****************************************************************************************/
1701 UBYTE ic_transparentcolour
;
1702 UBYTE ic_numcolours
;
1704 UBYTE ic_imageformat
;
1705 UBYTE ic_paletteformat
;
1707 UBYTE ic_numimagebytes
[2];
1708 UBYTE ic_numpalettebytes
[2];
1711 /****************************************************************************************/
1713 static LONG
writefacechunk(void)
1715 struct facechunk fc
;
1719 #define ACT_STRUCT fc
1722 writelong(sizeof(struct facechunk
));
1724 SET_BYTE(fc_width
, img1
.bmh
.bmh_Width
- 1);
1725 SET_BYTE(fc_height
, img1
.bmh
.bmh_Height
- 1);
1726 SET_BYTE(fc_flags
, 0);
1727 SET_BYTE(fc_aspect
, 0); // 0x11);
1729 palbytes
= (img1
.cmapentries
> img2
.cmapentries
) ? img1
.cmapentries
: img2
.cmapentries
;
1730 palbytes
= palbytes
* 3;
1732 SET_WORD(fc_maxpalettebytes
, palbytes
- 1);
1734 if (fwrite(&fc
, 1, sizeof(fc
), outfile
) != sizeof(fc
))
1736 cleanup("Error writing face chunk!", 1);
1739 return sizeof(struct facechunk
) + 8;
1742 /****************************************************************************************/
1744 /* createrle() based on ModifyIcon source by Dirk Stöcker */
1746 /****************************************************************************************/
1748 static char * createrle(unsigned long depth
, unsigned char *dtype
, LONG
*dsize
, unsigned long size
,
1752 unsigned long bitbuf
, numbits
;
1754 long ressize
, numcopy
, numequal
;
1756 buf
= malloc(size
* 2);
1757 if (!buf
) return NULL
;
1764 k
= 0; /* the really output pointer */
1765 for(i
= 1; numequal
|| numcopy
;)
1767 if(i
< size
&& numequal
&& (src
[i
-1] == src
[i
]))
1771 else if(i
< size
&& numequal
*depth
<= 16)
1773 numcopy
+= numequal
; numequal
= 1; ++i
;
1777 /* care for end case, where it maybe better to join the two */
1778 if(i
== size
&& numcopy
+ numequal
<= 128 && (numequal
-1)*depth
<= 8)
1780 numcopy
+= numequal
; numequal
= 0;
1784 if((j
= numcopy
) > 128) j
= 128;
1785 bitbuf
= (bitbuf
<<8) | (j
-1);
1790 if((j
= numequal
) > 128) j
= 128;
1791 bitbuf
= (bitbuf
<<8) | (256-(j
-1));
1796 buf
[ressize
++] = (bitbuf
>> numbits
);
1800 bitbuf
= (bitbuf
<<depth
) | src
[k
++];
1804 buf
[ressize
++] = (bitbuf
>> numbits
);
1807 if(i
< size
&& !numcopy
&& !numequal
)
1814 buf
[ressize
++] = bitbuf
<< (8-numbits
);
1816 if(ressize
> size
) /* no RLE */
1820 for(i
= 0; i
< size
; ++i
)
1831 /****************************************************************************************/
1833 static LONG
writeimagchunk(struct ILBMImage
*img
)
1835 struct imagchunk ic
;
1837 UBYTE skippalette
= 0;
1839 LONG palsize
, gfxsize
;
1840 UBYTE palpacked
, gfxpacked
;
1842 imagsize
= sizeof(struct imagchunk
);
1844 /* if this is second image check whether palette is identical to
1845 the one of first image */
1849 if (img1
.cmapentries
== img2
.cmapentries
)
1853 for (i
= 0; i
< img1
.cmapentries
; i
++)
1855 if (img1
.rgb
[i
][0] != img2
.rgb
[i
][0]) break;
1856 if (img1
.rgb
[i
][1] != img2
.rgb
[i
][1]) break;
1857 if (img1
.rgb
[i
][2] != img2
.rgb
[i
][2]) break;
1860 if (i
== img1
.cmapentries
) skippalette
= 1;
1869 img
->cmapentries
* 3,
1870 (unsigned char *)img
->rgb
);
1872 imagsize
+= palsize
;
1875 gfx
= createrle(img
->bmh
.bmh_Depth
,
1878 img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
,
1881 imagsize
+= gfxsize
;
1884 #define ACT_STRUCT ic
1886 SET_BYTE(ic_transparentcolour
, transparentoption
);
1889 SET_BYTE(ic_numcolours
, 0);
1890 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 1 : 0); /* 1 = HasTransparentColour */
1891 SET_BYTE(ic_paletteformat
, 0);
1892 SET_WORD(ic_numpalettebytes
, 0);
1896 SET_BYTE(ic_numcolours
, img
->cmapentries
- 1);
1897 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 3 : 2); /* 2 = HasPalette */
1898 SET_BYTE(ic_paletteformat
, palpacked
);
1899 SET_WORD(ic_numpalettebytes
, palsize
- 1);
1902 SET_BYTE(ic_imageformat
, gfxpacked
);
1903 SET_BYTE(ic_depth
, img
->bmh
.bmh_Depth
);
1904 SET_WORD(ic_numimagebytes
, gfxsize
- 1);
1907 writelong(imagsize
);
1909 if (fwrite(&ic
, 1, sizeof(ic
), outfile
) != sizeof(ic
))
1911 cleanup("Error writing imag chunk!", 1);
1914 if (fwrite(gfx
, 1, gfxsize
, outfile
) != gfxsize
)
1916 cleanup("Error write gfx data in imag chunk!", 1);
1921 if (fwrite(pal
, 1, palsize
, outfile
) != palsize
)
1923 cleanup("Error write palette data in imag chunk!", 1);
1931 if (fwrite(&dummy
, 1, 1, outfile
) != 1)
1933 cleanup("Error writing imag chunk!", 1);
1939 return imagsize
+ 8;
1942 /****************************************************************************************/
1943 static LONG
writeargb(APTR argb
, ULONG argb_size
)
1946 struct ARGB35_Header
{
1947 ULONG ztype
; /* Always 1 */
1948 ULONG zsize
; /* Compressed size, or -1 */
1949 UWORD resv
; /* Always 0 */
1955 zsize
= size
= argb_size
;
1957 zdest
= malloc(zsize
);
1961 err
= compress(zdest
, &zsize
, argb
, size
);
1968 formsize
= 10 + zsize
;
1971 writelong(formsize
);
1975 fwrite(zdest
, 1, zsize
, outfile
);
1978 fwrite(&c
, 1, 1, outfile
);
1983 return 8 + formsize
;
1986 /****************************************************************************************/
1988 static void write35data(void)
1997 formsizeseek
= ftell(outfile
);
1998 writelong(0x12345678);
2001 formsize
+= writefacechunk();
2002 formsize
+= writeimagchunk(&img1
);
2003 if (image2option
) formsize
+= writeimagchunk(&img2
);
2005 if (!nosaveARGB
&& img1
.argb
) {
2006 formsize
+= writeargb(img1
.argb
, img1
.argb_size
);
2009 if (!nosaveARGB
&& img2
.argb
) {
2010 formsize
+= writeargb(img2
.argb
, img2
.argb_size
);
2013 if (!nosavePNG
&& img1
.png
) {
2015 writelong(img1
.png_size
);
2016 fwrite(img1
.png
, 1, img1
.png_size
, outfile
);
2017 if (img1
.png_size
& 1) {
2019 fwrite(&c
, 1, 1, outfile
);
2022 formsize
+= 8 + img1
.png_size
;
2025 if (!nosavePNG
&& img2
.png
) {
2027 writelong(img2
.png_size
);
2028 fwrite(img2
.png
, 1, img2
.png_size
, outfile
);
2029 if (img2
.png_size
& 1) {
2031 fwrite(&c
, 1, 1, outfile
);
2034 formsize
+= 8 + img2
.png_size
;
2037 fseek(outfile
, formsizeseek
, SEEK_SET
);
2038 writelong(formsize
);
2041 /****************************************************************************************/
2043 static void writeicon(void)
2045 struct diskobject dobj
;
2047 outfile
= fopen(outfilename
, "wb");
2048 if (!outfile
) cleanup("Can't open output file for writing!", 1);
2051 writeolddrawerdata();
2054 if (image2option
) writeimage(&img2
);
2056 if (defaulttooloption
) writestring(defaulttooloption
);
2058 if (tooltypesoption
)
2061 LONG numtooltypes
= 0;
2063 for(strarray
= tooltypesoption
; *strarray
; strarray
++, numtooltypes
++);
2065 writelong((numtooltypes
+ 1) * 4);
2067 for(strarray
= tooltypesoption
; *strarray
; strarray
++)
2069 writestring(*strarray
);
2074 /* toolwindow would have to be saved in between here if there is any */
2076 writenewdrawerdata();
2082 /****************************************************************************************/
2084 static void remapicon(void)
2086 remapplanar(&img1
, &std4colpal
);
2087 if (image2option
) remapplanar(&img2
, &std4colpal
);
2090 /****************************************************************************************/
2092 int main(int argc
, char **argv
)
2094 getarguments(argc
, argv
);
2096 loadimage(image1option
, &img1
);
2097 if (image2option
) loadimage(image2option
, &img2
);
2104 /****************************************************************************************/