2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
5 Desc: Tool to convert IFF ILBM images into Amiga icon file.
13 /****************************************************************************************/
23 /****************************************************************************************/
28 #define MAKE_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | ((d)))
30 #define ID_FORM MAKE_ID('F','O','R','M')
31 #define ID_ILBM MAKE_ID('I','L','B','M')
32 #define ID_CMAP MAKE_ID('C','M','A','P')
33 #define ID_BODY MAKE_ID('B','O','D','Y')
34 #define ID_BMHD MAKE_ID('B','M','H','D')
36 #define ID_ICON MAKE_ID('I','C','O','N')
37 #define ID_FACE MAKE_ID('F','A','C','E')
38 #define ID_IMAG MAKE_ID('I','M','A','G')
39 #define ID_PNG MAKE_ID('p','n','g',' ')
40 #define ID_ARGB MAKE_ID('A','R','G','B')
43 #define CMP_BYTERUN1 1
46 #define MSK_HASTRANS 2
48 /****************************************************************************************/
50 /* For this tool it does not really matter if the following types
51 have a bigger sizeof() than on Amiga */
55 typedef unsigned long ULONG
;
57 typedef unsigned short UWORD
;
60 typedef unsigned char UBYTE
;
62 #include <exec/types.h>
65 /****************************************************************************************/
75 UBYTE bmh_Compression
;
77 UWORD bmh_Transparent
;
84 /****************************************************************************************/
88 struct BitMapHeader bmh
;
89 struct BitMapHeader planarbmh
;
90 unsigned char *planarbuffer
, *chunkybuffer
;
91 LONG cmapentries
, bpr
, totdepth
;
93 UBYTE remaptable
[256];
100 /****************************************************************************************/
108 /****************************************************************************************/
110 struct Palette std4colpal
=
114 {0x95, 0x95, 0x95}, /* Gray (and transparent!) */
115 {0x00, 0x00, 0x00}, /* Black */
116 {0xFF, 0xFF, 0xFF}, /* White */
117 {0x3b, 0x67, 0xa2} /* Blue */
121 /****************************************************************************************/
123 struct Palette magicwb8colpal
=
127 {0x95, 0x95, 0x95}, /* Gray (and transparent!) */
128 {0x00, 0x00, 0x00}, /* Black */
129 {0xFF, 0xFF, 0xFF}, /* White */
130 {0x3b, 0x67, 0xa2}, /* Blue */
131 {0x7b, 0x7b, 0x7b}, /* Dk. Gray */
132 {0xaf, 0xaf, 0xaf}, /* Lt. Gray */
133 {0xaa, 0x90, 0x7c}, /* Brown */
134 {0xff, 0xa9, 0x97} /* Pink */
138 /****************************************************************************************/
140 struct Palette scalos16colpal
=
144 { 0x9c, 0x9c, 0x9c }, /* 0 - Gray */
145 { 0x00, 0x00, 0x00 }, /* 1 - Black */
146 { 0xFF, 0xFF, 0xFF }, /* 2 - White */
147 { 0x3a, 0x3a, 0xd7 }, /* 3 - Blue */
148 { 0x75, 0x75, 0x75 }, /* 4 - Med. Gray */
149 { 0xc4, 0xc4, 0xc4 }, /* 5 - Lt. Gray */
150 { 0xd7, 0xb0, 0x75 }, /* 6 - Peach */
151 { 0xeb, 0x62, 0x9c }, /* 7 - Pink */
152 { 0x13, 0x75, 0x27 }, /* 8 - Dk. Green */
153 { 0x75, 0x3a, 0x00 }, /* 9 - Brown */
154 { 0xff, 0xd7, 0x13 }, /* 10 - Yellow */
155 { 0x3a, 0x3a, 0x3a }, /* 11 - Dk. Gray */
156 { 0xc4, 0x13, 0x27 }, /* 12 - Red */
157 { 0x27, 0xb0, 0x3a }, /* 13 - Lt. Green */
158 { 0x3a, 0x75, 0xff }, /* 14 - Lt. Blue */
159 { 0xd7, 0x75, 0x27 }, /* 15 - Orange */
163 /* Convert from DPI to Amiga 'ticks' resolution */
164 #define TPD_X(x) ((11*1280*100/104/(x)+5)/10)
165 #define TPD_Y(y) ((11*1024*100/78/(y)+5)/10)
167 /****************************************************************************************/
169 static char *filename
, *outfilename
, *infilename
;
170 static unsigned char *filebuffer
, *body
;
171 static FILE *file
, *outfile
, *infile
;
172 static long filesize
, bodysize
, bodysize_packed
;
174 static struct ILBMImage img1
, img2
;
175 static BOOL have_bmhd
, have_cmap
, have_body
, is_png
;
177 /* 'ticks' per dot, corresponding to ~72dpi */
178 static ULONG tpdX
= TPD_X(72), tpdY
= TPD_Y(72);
179 static char *image1option
;
180 static char *image2option
;
181 static char *defaulttooloption
;
182 static char *drawerdataoption
;
183 static char **tooltypesoption
;
184 static LONG typeoption
= 3; /* WBTOOL */
185 static LONG iconleftoption
= 0x80000000; /* NO_ICON_POSITION */
186 static LONG icontopoption
= 0x80000000; /* NO_ICON_POSITION */
187 static LONG stackoption
= 4096;
188 static LONG drawerleftoption
= 50;
189 static LONG drawertopoption
= 50;
190 static LONG drawerwidthoption
= 400;
191 static LONG drawerheightoption
= 100;
192 static LONG drawervleftoption
= 0;
193 static LONG drawervtopoption
= 0;
194 static LONG drawershowoption
= 0;
195 static LONG drawershowasoption
= 0;
196 static LONG transparentoption
= -1;
198 static BOOL dualpng
; /* png file contains second image */
199 static unsigned char *dualpngstart
; /* address of 2nd image in filebuffer */
200 static BOOL nosavePNG
; /* Don't save the original PNG data */
201 static BOOL nosaveARGB
; /* Don't ARGB data */
202 static BOOL nosaveIFF
; /* Don't save any IFF data */
204 /****************************************************************************************/
206 static void freeimage(struct ILBMImage
*img
)
208 if (img
->chunkybuffer
)
210 free(img
->chunkybuffer
);
211 img
->chunkybuffer
= NULL
;
214 if (img
->planarbuffer
)
216 free(img
->planarbuffer
);
217 img
->planarbuffer
= NULL
;
241 /****************************************************************************************/
243 static void cleanup(char *msg
, int rc
)
245 if (msg
) fprintf(stderr
, "ilbmtoicon: %s\n", msg
);
250 if (outfile
) fclose(outfile
);
251 if (infile
) fclose(infile
);
256 /****************************************************************************************/
258 static void getarguments(int argc
, char **argv
)
264 for (; argc
> 1 && argv
[1][0] == '-'; argc
--, argv
++) {
265 if (strcmp(argv
[1],"--png") == 0) {
269 if (strcmp(argv
[1],"--no-iff") == 0) {
273 if (strcmp(argv
[1],"--no-argb") == 0) {
277 if (strcmp(argv
[1],"--dpi") == 0) {
282 dpiX
= strtol(argv
[1], &cp
, 0);
285 dpiY
= strtol(cp
, NULL
, 0);
296 if ((argc
!= 4) && (argc
!= 5))
298 fprintf(stderr
, "Wrong number of arguments\n");
299 cleanup("Usage: ilbmtoicon [--png] [--no-argb] [--no-iff] icondescription image1 [image2] filename", 1);
304 infilename
= argv
[1];
305 image1option
= argv
[2];
306 outfilename
= argv
[3];
310 infilename
= argv
[1];
311 image1option
= argv
[2];
312 image2option
= argv
[3];
313 outfilename
= argv
[4];
317 /****************************************************************************************/
319 static char *skipblanks(char *s
)
321 while ((*s
== ' ') || (*s
== '\t')) s
++;
326 /****************************************************************************************/
328 static char *skipword(char *s
)
341 /****************************************************************************************/
343 static char *checkquotes(char *s
)
361 while ((i
< 256) && (s3
[i
] = *s
))
384 /****************************************************************************************/
386 #define KEYWORD_STRING 0
387 #define KEYWORD_INTEGER 1
388 #define KEYWORD_STRINGARRAY 2
389 #define KEYWORD_CYCLE 3
391 #define MAX_ARRAY_SIZE 200
393 /****************************************************************************************/
401 struct cycle typecycles
[] =
413 struct cycle showcycles
[] =
422 struct cycle showascycles
[] =
435 /****************************************************************************************/
446 {KEYWORD_STRING
, "DEFAULTTOOL" , &defaulttooloption
, NULL
},
447 {KEYWORD_STRING
, "DRAWERDATA" , &drawerdataoption
, NULL
},
448 {KEYWORD_CYCLE
, "TYPE" , &typeoption
, typecycles
},
449 {KEYWORD_STRINGARRAY
, "TOOLTYPE" , &tooltypesoption
, NULL
},
450 {KEYWORD_INTEGER
, "STACK" , &stackoption
, NULL
},
451 {KEYWORD_INTEGER
, "ICONLEFTPOS" , &iconleftoption
, NULL
},
452 {KEYWORD_INTEGER
, "ICONTOPPOS" , &icontopoption
, NULL
},
453 {KEYWORD_INTEGER
, "DRAWERLEFTPOS" , &drawerleftoption
, NULL
},
454 {KEYWORD_INTEGER
, "DRAWERTOPPOS" , &drawertopoption
, NULL
},
455 {KEYWORD_INTEGER
, "DRAWERWIDTH" , &drawerwidthoption
, NULL
},
456 {KEYWORD_INTEGER
, "DRAWERHEIGHT" , &drawerheightoption
, NULL
},
457 {KEYWORD_INTEGER
, "DRAWERVIEWLEFT" , &drawervleftoption
, NULL
},
458 {KEYWORD_INTEGER
, "DRAWERVIEWTOP" , &drawervtopoption
, NULL
},
459 {KEYWORD_CYCLE
, "DRAWERSHOW" , &drawershowoption
, showcycles
},
460 {KEYWORD_CYCLE
, "DRAWERSHOWAS" , &drawershowoption
, showascycles
},
461 {KEYWORD_INTEGER
, "TRANSPARENT" , &transparentoption
, NULL
},
466 /****************************************************************************************/
468 static void handleoption(char *keyword
, char *keyvalue
)
473 D(printf("Keyword %s, value %s\n", keyword
, keyvalue
));
475 for(kw
= keywordtable
; kw
->keyword
; kw
++)
477 if (strcasecmp(kw
->keyword
, keyword
) == 0)
482 *(char **)kw
->store
= strdup(keyvalue
);
483 if (!(*(char **)kw
->store
)) cleanup("Out of memory!", 1);
486 case KEYWORD_INTEGER
:
487 *(LONG
*)kw
->store
= strtol(keyvalue
, 0, 0);
491 for(cy
= (struct cycle
*)kw
->extra
; cy
->keyword
; cy
++)
493 if (strcasecmp(keyvalue
, cy
->keyword
) == 0)
495 *(LONG
*)kw
->store
= cy
->value
;
501 case KEYWORD_STRINGARRAY
:
502 if (!(*(char ***)kw
->store
))
504 *(char ***)kw
->store
= (char **)malloc(MAX_ARRAY_SIZE
* sizeof(char *));
505 if (!(*(char ***)kw
->store
)) cleanup("Out of memory!", 1);
507 memset(*(char ***)kw
->store
, 0, MAX_ARRAY_SIZE
* sizeof(char *));
512 char **strarray
= *(char ***)kw
->store
;
515 dupvalue
= strdup(keyvalue
);
516 if (!dupvalue
) cleanup("Out of memory!", 1);
524 if (i
>= MAX_ARRAY_SIZE
- 1) cleanup("Array overflow!", 1);
526 *strarray
= dupvalue
;
529 } /* switch(kw->type) */
533 } /* if (strcasecmp(kw->keyword, keyword) == 0) */
535 } /* for(kw = keywordtable; kw->keyword; kw++) */
539 /****************************************************************************************/
541 static void parseline(char *s
)
544 char *keyvalue
= NULL
;
548 if (*s
== '#') return;
549 if (*s
== ';') return;
554 if (*s
== '\0') return;
557 s
= skipblanks(s
+ 1);
559 if (*s
== '=') s
= skipblanks(s
+ 1);
560 if (*s
== '\0') return;
562 keyvalue
= checkquotes(s
);
564 handleoption(keyword
, keyvalue
);
567 /****************************************************************************************/
569 static void parseiconsource(void)
573 infile
= fopen(infilename
, "r");
576 while(fgets(s
, sizeof(s
), infile
))
578 D(printf("Read line: %s\n", s
));
587 /****************************************************************************************/
589 static void showoptions(void)
593 printf("image1: %s\n", image1option
? image1option
: "(NULL)");
594 printf("image2: %s\n", image2option
? image2option
: "(NULL)");
595 printf("type: %ld\n", typeoption
);
597 strarray
= tooltypesoption
;
600 printf("tooltypes:\n");
603 printf(" %s\n", *strarray
++);
608 /****************************************************************************************/
610 static ULONG
getlong(void)
614 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
616 ret
= filebuffer
[filepos
++] * 0x1000000;
617 ret
+= filebuffer
[filepos
++] * 0x10000;
618 ret
+= filebuffer
[filepos
++] * 0x100;
619 ret
+= filebuffer
[filepos
++];
624 /****************************************************************************************/
626 static UWORD
getword(void)
630 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
632 ret
= filebuffer
[filepos
++] * 0x100;
633 ret
+= filebuffer
[filepos
++];
638 /****************************************************************************************/
640 static UBYTE
getbyte(void)
644 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
645 ret
= filebuffer
[filepos
++];
650 /****************************************************************************************/
652 static void skipbytes(ULONG howmany
)
657 /****************************************************************************************/
659 static void openimage(struct ILBMImage
*img
)
661 file
= fopen(filename
, "rb");
662 if (!file
) cleanup("Can't open file!", 1);
664 fseek(file
, 0, SEEK_END
);
665 filesize
= ftell(file
);
667 if (filesize
< 12) cleanup("Bad file size!", 1);
669 //fprintf(stderr, "Filesize is %d\n", filesize);
671 fseek(file
, 0, SEEK_SET
);
673 filebuffer
= malloc(filesize
+ 10);
674 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
676 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
677 cleanup("Error reading file!", 1);
679 fclose(file
); file
= NULL
;
682 /****************************************************************************************/
684 static void checkimage(struct ILBMImage
*img
)
686 static UBYTE pngsig
[8] = {137, 80, 78, 71, 13, 10, 26, 10};
692 img
->png
= dualpngstart
;
693 img
->png_size
= filesize
- (dualpngstart
- filebuffer
);
697 if (memcmp(filebuffer
, pngsig
, 8) == 0)
700 img
->png
= filebuffer
;
702 /* search for second image */
705 dualpngstart
= filebuffer
+ 8 ;
706 dualpngstart
< filebuffer
+ filesize
- 8 ;
710 if (memcmp(dualpngstart
, pngsig
, 8) == 0)
717 img
->png_size
= dualpngstart
- filebuffer
;
719 img
->png_size
= filesize
;
721 else if (is_png
== 0)
724 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
727 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
730 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
732 else if (is_png
== 1)
734 cleanup("Second image must be a PNG image, too!", 1);
739 /****************************************************************************************/
741 static void my_read_fn(png_structp png_ptr
, png_bytep data
, png_size_t length
)
743 png_bytep
*pdata
= png_get_io_ptr(png_ptr
);
745 if (*pdata
-filebuffer
>= filesize
)
746 png_error(png_ptr
, "Read past end of file");
748 memcpy(data
, *pdata
, length
);
752 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
);
754 static void loadpng(struct ILBMImage
*img
, struct Palette
*pal
)
757 png_infop info_ptr
, end_info
;
758 png_bytep fpos
, *row_pointers
;
763 if (png_sig_cmp(img
->png
, 0, img
->png_size
) != 0)
764 cleanup("I thought it was a PNG, but I was wrong.", 1);
766 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
,
771 cleanup("png_create_read_struct() failed", 1);
773 info_ptr
= png_create_info_struct(png_ptr
);
775 png_destroy_read_struct(&png_ptr
, NULL
, NULL
);
776 cleanup("png_create_info_struct() failed", 1);
779 end_info
= png_create_info_struct(png_ptr
);
781 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
782 cleanup("png_create_info_struct() failed", 1);
786 png_set_read_fn(png_ptr
, &fpos
, my_read_fn
);
788 if (setjmp(png_jmpbuf(png_ptr
))) {
789 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
790 cleanup("png read failed", 1);
793 /* Read the PNG as RGBA */
794 png_set_add_alpha(png_ptr
, 255, PNG_FILLER_AFTER
);
795 png_read_png(png_ptr
, info_ptr
, PNG_TRANSFORM_EXPAND
| PNG_TRANSFORM_STRIP_16
, NULL
);
797 row_pointers
= png_get_rows(png_ptr
, info_ptr
);
799 width
= png_get_image_width(png_ptr
, info_ptr
);
800 height
= png_get_image_height(png_ptr
, info_ptr
);
802 img
->bmh
.bmh_Width
= width
;
803 img
->bmh
.bmh_Height
= height
;
804 img
->bmh
.bmh_Left
= 0;
805 img
->bmh
.bmh_Top
= 0;
806 img
->bmh
.bmh_Depth
= 8;
807 img
->bmh
.bmh_Masking
= MSK_HASTRANS
;
808 img
->bmh
.bmh_Compression
= CMP_NONE
;
809 img
->bmh
.bmh_Pad
= 0;
810 img
->bmh
.bmh_XAspect
= 1;
811 img
->bmh
.bmh_YAspect
= 1;
812 img
->bmh
.bmh_PageWidth
= 320;
813 img
->bmh
.bmh_PageHeight
= 200;
816 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
819 /* Transform the RGBA data into chunky */
820 img
->cmapentries
= pal
->numentries
;
821 memcpy(img
->rgb
, pal
->rgb
, sizeof(img
->rgb
[0])*pal
->numentries
);
823 img
->chunkybuffer
= malloc(width
* height
* sizeof(UBYTE
));
824 if (!img
->chunkybuffer
)
825 cleanup("Can't allocate the chunky buffer", 1);
827 chunkrow
= img
->chunkybuffer
;
828 img
->argb_size
= width
* height
* sizeof(UBYTE
) * 4;
829 img
->argb
= malloc(img
->argb_size
);
831 cleanup("Can't allocate the ARGB buffer", 1);
833 for (y
= 0; y
< height
; y
++) {
834 png_bytep row
= row_pointers
[y
];
835 UBYTE
*ap
= img
->argb
+ (width
* sizeof(UBYTE
) * 4) * y
;
836 for (x
= 0; x
< width
; x
++, row
+= 4, ap
+= 4, chunkrow
++) {
844 /* Opacity of 0? Use the transparency color */
846 if (transparentoption
< 0)
847 transparentoption
= 0;
848 *chunkrow
= transparentoption
;
854 *chunkrow
= findcolor(pal
, r
, g
, b
, TRUE
);
859 img
->bmh
.bmh_Transparent
= transparentoption
;
861 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
865 /****************************************************************************************/
867 static void scanimage(struct ILBMImage
*img
)
876 /* Load the PNG, using the Scalos 16-color pallette,
877 * into the Chunky buffer.
879 loadpng(img
, &scalos16colpal
);
891 //fprintf(stderr, "Chunk: %c%c%c%c Size: %d\n", id >> 24, id >> 16, id >> 8, id, size);
896 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
898 img
->bmh
.bmh_Width
= getword();
899 img
->bmh
.bmh_Height
= getword();
900 img
->bmh
.bmh_Left
= (WORD
)getword();
901 img
->bmh
.bmh_Top
= (WORD
)getword();
902 img
->bmh
.bmh_Depth
= getbyte();
903 img
->bmh
.bmh_Masking
= getbyte();
904 img
->bmh
.bmh_Compression
= getbyte();
905 img
->bmh
.bmh_Pad
= getbyte();
906 img
->bmh
.bmh_Transparent
= getword();
907 img
->bmh
.bmh_XAspect
= getbyte();
908 img
->bmh
.bmh_YAspect
= getbyte();
909 img
->bmh
.bmh_PageWidth
= (WORD
)getword();
910 img
->bmh
.bmh_PageHeight
= (WORD
)getword();
912 if (img
->bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
913 if ((img
->bmh
.bmh_Compression
!= CMP_NONE
) && (img
->bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
917 img
->totdepth
= img
->bmh
.bmh_Depth
+ ((img
->bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
919 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
921 /*fprintf(stderr, "BMHD: %d x %d x %d (%d)\n", img->bmh.bmh_Width,
925 img
->planarbmh
= img
->bmh
;
929 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
931 img
->cmapentries
= size
/ 3;
932 if (size
& 1) size
++;
934 if ((img
->cmapentries
< 2) || (img
->cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
936 for(i
= 0; i
< img
->cmapentries
; i
++)
938 img
->rgb
[i
][0] = getbyte();
939 img
->rgb
[i
][1] = getbyte();
940 img
->rgb
[i
][2] = getbyte();
951 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
952 body
= &filebuffer
[filepos
];
955 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
957 LONG shouldbesize
= img
->totdepth
* img
->bpr
* img
->bmh
.bmh_Height
;
958 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
965 if (size
& 1) size
++;
970 if (filepos
== filesize
) break;
971 if (have_bmhd
&& have_body
&& have_cmap
) break;
974 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
975 if (!have_body
) cleanup("BODY chunk missing!", 1);
978 /****************************************************************************************/
980 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
987 c
= (signed char)(*source
++);
993 if (--unpackedsize
<= 0) return source
;
1004 if (--unpackedsize
<= 0) return source
;
1011 /****************************************************************************************/
1013 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
1014 unsigned char **dest
, LONG
*checksize
)
1016 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
1022 if (step
> 127) step
= 127;
1027 if (*checksize
<= 0) return 0;
1036 *(*dest
)++ = *(*source_backup
)++;
1046 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
1048 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
1054 if (step
> 127) step
= 127;
1059 if (*checksize
<= 0) return 0;
1061 *(*dest
)++ = (unsigned char)step
;
1068 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
1069 LONG size
, LONG check_size
, LONG
*packsize
)
1071 unsigned char *source_backup
, *dest_backup
;
1072 LONG samebytes_counter
, samebytes
, count
;
1073 LONG checksize
= check_size
;
1074 unsigned char oldbyte
, actbyte
;
1076 if (checksize
< 0) checksize
= 0x7FFFFFFF;
1079 samebytes_counter
= 0;
1080 source_backup
= source
;
1085 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
1086 if (--size
< 0) break;
1087 actbyte
= *source
++;
1088 if (actbyte
== oldbyte
)
1090 samebytes_counter
++;
1096 samebytes
= samebytes_counter
;
1097 samebytes_counter
= 1;
1099 if (samebytes
< 3) continue;
1101 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
1102 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1104 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1106 source_backup
= source
- 1;
1108 //fprintf(stderr, "done\n");
1110 if (samebytes_counter
>= 3)
1112 samebytes
= samebytes_counter
;
1113 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
1114 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1115 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1119 count
= (LONG
)(source
- source_backup
- 1);
1120 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1122 //fprintf(stderr, "realdone\n");
1124 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
1129 /****************************************************************************************/
1131 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
1132 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
1134 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1136 alignedwidth
= (width
+ 15) & ~15;
1137 bpr
= alignedwidth
/ 8;
1138 bpl
= bpr
* totplanes
;
1140 for(y
= 0; y
< height
; y
++)
1142 for(x
= 0; x
< width
; x
++)
1144 LONG mask
= 0x80 >> (x
& 7);
1145 LONG offset
= x
/ 8;
1146 unsigned char chunkypix
= 0;
1148 for(p
= 0; p
< wantplanes
; p
++)
1150 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
1152 dest
[x
] = chunkypix
;
1162 /****************************************************************************************/
1164 static void c2p(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
, LONG planes
)
1166 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1168 alignedwidth
= (width
+ 15) & ~15;
1169 bpr
= alignedwidth
/ 8;
1172 for(y
= 0; y
< height
; y
++)
1174 for(x
= 0; x
< width
; x
++)
1176 LONG mask
= 0x80 >> (x
& 7);
1177 LONG offset
= x
/ 8;
1178 unsigned char chunkypix
= source
[x
];
1180 for(p
= 0; p
< planes
; p
++)
1182 if (chunkypix
& (1 << p
))
1183 dest
[p
* bpr
+ offset
] |= mask
;
1185 dest
[p
* bpr
+ offset
] &= ~mask
;
1195 /****************************************************************************************/
1197 static void convertbody(struct ILBMImage
*img
)
1199 LONG unpackedsize
= img
->bpr
* img
->bmh
.bmh_Height
* img
->totdepth
;
1204 img
->planarbuffer
= malloc(unpackedsize
);
1205 if (!img
->planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
1207 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
1209 memcpy(img
->planarbuffer
, body
, unpackedsize
);
1213 unpack_byterun1(body
, img
->planarbuffer
, unpackedsize
);
1216 img
->chunkybuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1217 if (!img
->chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
1219 p2c(img
->planarbuffer
,
1222 img
->bmh
.bmh_Height
,
1225 img
->bmh
.bmh_Width
);
1228 /****************************************************************************************/
1230 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
)
1232 ULONG dist
, bestdist
= 0xFFFFFFFF;
1235 for(i
= 0; i
< pal
->numentries
; i
++)
1237 LONG r1
, g1
, b1
, r2
, g2
, b2
, dr
, dg
, db
;
1239 if (notrans
&& i
== transparentoption
)
1246 r2
= (LONG
)pal
->rgb
[i
][0];
1247 g2
= (LONG
)pal
->rgb
[i
][1];
1248 b2
= (LONG
)pal
->rgb
[i
][2];
1254 dist
= (dr
* dr
) + (dg
* dg
) + (db
* db
);
1255 if (dist
< bestdist
)
1266 /****************************************************************************************/
1268 static void remapplanar(struct ILBMImage
*img
, struct Palette
*pal
)
1271 LONG i
, x
, y
, highestcol
= 0, newdepth
= 0;
1273 remapbuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1274 if (!remapbuffer
) cleanup("Error allocating remap buffer!", 1);
1276 for(i
= 0; i
< img
->cmapentries
; i
++)
1278 img
->remaptable
[i
] = findcolor(pal
, img
->rgb
[i
][0], img
->rgb
[i
][1], img
->rgb
[i
][2], FALSE
);
1281 for(i
= 0; i
< img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
; i
++)
1283 remapbuffer
[i
] = img
->remaptable
[img
->chunkybuffer
[i
]];
1285 if (remapbuffer
[i
] > highestcol
)
1286 highestcol
= remapbuffer
[i
];
1289 for(i
= highestcol
; i
; i
>>= 1) newdepth
++;
1290 if (newdepth
== 0) newdepth
= 1;
1292 if (newdepth
> img
->totdepth
)
1294 if (img
->planarbuffer
)
1295 free(img
->planarbuffer
);
1297 img
->planarbuffer
= malloc(img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1298 if (!img
->planarbuffer
)
1301 cleanup("Error re-allocating planar buffer!", 1);
1305 img
->planarbmh
.bmh_Width
= img
->bmh
.bmh_Width
;
1306 img
->planarbmh
.bmh_Height
= img
->bmh
.bmh_Height
;
1307 img
->planarbmh
.bmh_Depth
= newdepth
;
1309 memset(img
->planarbuffer
, 0, img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1311 c2p(remapbuffer
, img
->planarbuffer
, img
->bmh
.bmh_Width
, img
->bmh
.bmh_Height
, newdepth
);
1316 /****************************************************************************************/
1318 static void loadimage(char *name
, struct ILBMImage
*img
)
1330 /****************************************************************************************/
1335 UBYTE do_version
[2];
1336 UBYTE do_gadget_nextgadget
[4];
1337 UBYTE do_gadget_leftedge
[2];
1338 UBYTE do_gadget_topedge
[2];
1339 UBYTE do_gadget_width
[2];
1340 UBYTE do_gadget_height
[2];
1341 UBYTE do_gadget_flags
[2];
1342 UBYTE do_gadget_activation
[2];
1343 UBYTE do_gadget_gadgettype
[2];
1344 UBYTE do_gadget_gadgetrender
[4];
1345 UBYTE do_gadget_selectrender
[4];
1346 UBYTE do_gadget_gadgettext
[4];
1347 UBYTE do_gadget_mutualexclude
[4];
1348 UBYTE do_gadget_specialinfo
[4];
1349 UBYTE do_gadget_gadgetid
[2];
1350 UBYTE do_gadget_userdata
[4];
1353 UBYTE do_defaulttool
[4];
1354 UBYTE do_tooltypes
[4];
1355 UBYTE do_currentx
[4];
1356 UBYTE do_currenty
[4];
1357 UBYTE do_drawerdata
[4];
1358 UBYTE do_toolwindow
[4];
1359 UBYTE do_stacksize
[4];
1362 /****************************************************************************************/
1364 struct olddrawerdata
1366 UBYTE dd_newwindow_leftedge
[2];
1367 UBYTE dd_newwindow_topedge
[2];
1368 UBYTE dd_newwindow_width
[2];
1369 UBYTE dd_newwindow_height
[2];
1370 UBYTE dd_newwindow_detailpen
;
1371 UBYTE dd_newwindow_blockpen
;
1372 UBYTE dd_newwindow_idcmpflags
[4];
1373 UBYTE dd_newwindow_flags
[4];
1374 UBYTE dd_newwindow_firstgadget
[4];
1375 UBYTE dd_newwindow_checkmark
[4];
1376 UBYTE dd_newwindow_title
[4];
1377 UBYTE dd_newwindow_screen
[4];
1378 UBYTE dd_newwindow_bitmap
[4];
1379 UBYTE dd_newwindow_minwidth
[2];
1380 UBYTE dd_newwindow_minheight
[2];
1381 UBYTE dd_newwindow_maxwidth
[2];
1382 UBYTE dd_newwindow_maxheight
[2];
1383 UBYTE dd_newwindow_type
[2];
1384 UBYTE dd_currentx
[4];
1385 UBYTE dd_currenty
[4];
1388 /****************************************************************************************/
1390 struct newdrawerdata
1393 UBYTE dd_viewmodes
[2];
1396 /****************************************************************************************/
1411 /****************************************************************************************/
1413 #define SET_BYTE(field,value) \
1414 ACT_STRUCT.field = value
1416 #define SET_WORD(field, value) \
1417 ACT_STRUCT.field[0] = ((value) >> 8) & 0xFF; \
1418 ACT_STRUCT.field[1] = (value) & 0xFF;
1420 #define SET_LONG(field,value) \
1421 ACT_STRUCT.field[0] = ((value) >> 24) & 0xFF; \
1422 ACT_STRUCT.field[1] = ((value) >> 16) & 0xFF; \
1423 ACT_STRUCT.field[2] = ((value) >> 8) & 0xFF; \
1424 ACT_STRUCT.field[3] = (value) & 0xFF;
1426 #define BOOL_YES 0x2A2A2A2A
1427 #define BOOL_NO 0x00000000
1429 static void writediskobject(void)
1431 struct diskobject dobj
;
1433 if (typeoption
== 2) /* DRAWER */
1435 drawerdataoption
= "YES";
1438 #define ACT_STRUCT dobj
1440 SET_WORD(do_magic
, 0xE310);
1441 SET_WORD(do_version
, 1);
1442 SET_LONG(do_gadget_nextgadget
, 0);
1443 SET_WORD(do_gadget_leftedge
, 0);
1444 SET_WORD(do_gadget_topedge
, 0);
1445 SET_WORD(do_gadget_width
, img1
.bmh
.bmh_Width
);
1446 SET_WORD(do_gadget_height
, img1
.bmh
.bmh_Height
);
1450 /* GFLG_GADGHIMAGE + GFLG_GADGIMAGE */
1451 SET_WORD(do_gadget_flags
, 4 + 2);
1455 /* GFLG_GADGIMAGE */
1456 SET_WORD(do_gadget_flags
, 4);
1459 SET_WORD(do_gadget_activation
, 1);
1460 SET_WORD(do_gadget_gadgettype
, 1);
1461 SET_LONG(do_gadget_gadgetrender
, BOOL_YES
);
1465 SET_LONG(do_gadget_selectrender
, BOOL_YES
);
1469 SET_LONG(do_gadget_selectrender
, BOOL_NO
);
1472 SET_LONG(do_gadget_gadgettext
, 0);
1473 SET_LONG(do_gadget_mutualexclude
, (1 << 31) | (tpdX
<< 8) | (tpdY
<< 0));
1474 SET_LONG(do_gadget_specialinfo
, 0);
1475 SET_WORD(do_gadget_gadgetid
, 0);
1476 SET_LONG(do_gadget_userdata
, 1); /* full drawer data */
1478 SET_BYTE(do_type
, typeoption
);
1479 SET_BYTE(do_pad
, 0);
1481 if (defaulttooloption
)
1483 SET_LONG(do_defaulttool
, BOOL_YES
);
1487 SET_LONG(do_defaulttool
, BOOL_NO
);
1490 if (tooltypesoption
)
1492 SET_LONG(do_tooltypes
, BOOL_YES
);
1496 SET_LONG(do_tooltypes
, BOOL_NO
);
1499 SET_LONG(do_currentx
, iconleftoption
);
1500 SET_LONG(do_currenty
, icontopoption
);
1502 if (drawerdataoption
)
1504 SET_LONG(do_drawerdata
, BOOL_YES
);
1508 SET_LONG(do_drawerdata
, BOOL_NO
);
1512 SET_LONG(do_toolwindow
, 0);
1513 SET_LONG(do_stacksize
, stackoption
);
1515 if (fwrite(&dobj
, 1, sizeof(dobj
), outfile
) != sizeof(dobj
))
1517 cleanup("Error writing diskobject structure to outfile!", 1);
1521 /****************************************************************************************/
1523 static void writeolddrawerdata(void)
1525 struct olddrawerdata dd
;
1527 if (!drawerdataoption
) return;
1530 #define ACT_STRUCT dd
1532 SET_WORD(dd_newwindow_leftedge
, drawerleftoption
);
1533 SET_WORD(dd_newwindow_topedge
, drawertopoption
);
1534 SET_WORD(dd_newwindow_width
, drawerwidthoption
);
1535 SET_WORD(dd_newwindow_height
, drawerheightoption
);
1536 SET_BYTE(dd_newwindow_detailpen
, 255);
1537 SET_BYTE(dd_newwindow_blockpen
, 255);
1538 SET_LONG(dd_newwindow_idcmpflags
, 0);
1539 SET_LONG(dd_newwindow_flags
, 0x240027f);
1540 SET_LONG(dd_newwindow_firstgadget
, 0);
1541 SET_LONG(dd_newwindow_checkmark
, 0);
1542 SET_LONG(dd_newwindow_title
, 0);
1543 SET_LONG(dd_newwindow_screen
, 0);
1544 SET_LONG(dd_newwindow_bitmap
, 0);
1545 SET_WORD(dd_newwindow_minwidth
, 90);
1546 SET_WORD(dd_newwindow_minheight
, 40);
1547 SET_WORD(dd_newwindow_maxwidth
, 65535);
1548 SET_WORD(dd_newwindow_maxheight
, 65535);
1549 SET_WORD(dd_newwindow_type
, 1);
1550 SET_LONG(dd_currentx
, drawervleftoption
);
1551 SET_LONG(dd_currenty
, drawervtopoption
);
1553 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1555 cleanup("Error writing olddrawerdata structure to outfile!", 1);
1561 /****************************************************************************************/
1563 static void writenewdrawerdata(void)
1565 struct newdrawerdata dd
;
1567 if (!drawerdataoption
) return;
1570 #define ACT_STRUCT dd
1572 SET_LONG(dd_flags
, drawershowoption
);
1573 SET_WORD(dd_viewmodes
, drawershowasoption
);
1575 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1577 cleanup("Error writing newdrawerdata structure to outfile!", 1);
1582 /****************************************************************************************/
1584 static void writeword(WORD l
)
1588 f
[0] = (l
>> 8) & 0xFF;
1591 if (fwrite(f
, 1, 2, outfile
) != 2)
1593 cleanup("Error writing word value!", 1);
1598 /****************************************************************************************/
1600 static void writelong(LONG l
)
1604 f
[0] = (l
>> 24) & 0xFF;
1605 f
[1] = (l
>> 16) & 0xFF;
1606 f
[2] = (l
>> 8) & 0xFF;
1609 if (fwrite(f
, 1, 4, outfile
) != 4)
1611 cleanup("Error writing long value!", 1);
1616 /****************************************************************************************/
1618 static void writenormalstring(char *s
)
1620 int len
= strlen(s
) + 1;
1622 if (fwrite(s
, 1, len
, outfile
) != len
)
1624 cleanup("Error writing string!", 1);
1629 /****************************************************************************************/
1631 static void writestring(char *s
)
1633 int len
= strlen(s
) + 1;
1635 D(printf("String: \"%s\", length %d\n", s
, len
));
1639 if (fwrite(s
, 1, len
, outfile
) != len
)
1641 cleanup("Error writing string!", 1);
1646 /****************************************************************************************/
1648 static void writeimage(struct ILBMImage
*img
)
1654 #define ACT_STRUCT i
1656 SET_WORD(leftedge
, 0);
1657 SET_WORD(topedge
, 0);
1658 SET_WORD(width
, img
->planarbmh
.bmh_Width
);
1659 SET_WORD(height
, img
->planarbmh
.bmh_Height
);
1660 SET_WORD(depth
, img
->planarbmh
.bmh_Depth
);
1661 SET_LONG(imagedata
, BOOL_YES
);
1662 SET_BYTE(planepick
, (1 << img
->planarbmh
.bmh_Depth
) - 1);
1663 SET_BYTE(planeonoff
, 0);
1664 SET_LONG(nextimage
, 0);
1666 if (fwrite(&i
, 1, sizeof(i
), outfile
) != sizeof(i
))
1668 cleanup("Error writing image structure to outfile!", 1);
1671 for(d
= 0; d
< img
->planarbmh
.bmh_Depth
; d
++)
1673 UBYTE
*dat
= img
->planarbuffer
+ img
->bpr
* d
;
1675 for(y
= 0; y
< img
->planarbmh
.bmh_Height
; y
++)
1677 if(fwrite(dat
, 1, img
->bpr
, outfile
) != img
->bpr
)
1679 cleanup("Error writing image data to outfile!", 1);
1681 dat
+= (img
->planarbmh
.bmh_Depth
* img
->bpr
);
1687 /****************************************************************************************/
1695 UBYTE fc_maxpalettebytes
[2];
1698 /****************************************************************************************/
1702 UBYTE ic_transparentcolour
;
1703 UBYTE ic_numcolours
;
1705 UBYTE ic_imageformat
;
1706 UBYTE ic_paletteformat
;
1708 UBYTE ic_numimagebytes
[2];
1709 UBYTE ic_numpalettebytes
[2];
1712 /****************************************************************************************/
1714 static LONG
writefacechunk(void)
1716 struct facechunk fc
;
1720 #define ACT_STRUCT fc
1723 writelong(sizeof(struct facechunk
));
1725 SET_BYTE(fc_width
, img1
.bmh
.bmh_Width
- 1);
1726 SET_BYTE(fc_height
, img1
.bmh
.bmh_Height
- 1);
1727 SET_BYTE(fc_flags
, 0);
1728 SET_BYTE(fc_aspect
, 0); // 0x11);
1730 palbytes
= (img1
.cmapentries
> img2
.cmapentries
) ? img1
.cmapentries
: img2
.cmapentries
;
1731 palbytes
= palbytes
* 3;
1733 SET_WORD(fc_maxpalettebytes
, palbytes
- 1);
1735 if (fwrite(&fc
, 1, sizeof(fc
), outfile
) != sizeof(fc
))
1737 cleanup("Error writing face chunk!", 1);
1740 return sizeof(struct facechunk
) + 8;
1743 /****************************************************************************************/
1745 /* createrle() based on ModifyIcon source by Dirk Stöcker */
1747 /****************************************************************************************/
1749 static char * createrle(unsigned long depth
, unsigned char *dtype
, LONG
*dsize
, unsigned long size
,
1753 unsigned long bitbuf
, numbits
;
1755 long ressize
, numcopy
, numequal
;
1757 buf
= malloc(size
* 2);
1758 if (!buf
) return NULL
;
1765 k
= 0; /* the really output pointer */
1766 for(i
= 1; numequal
|| numcopy
;)
1768 if(i
< size
&& numequal
&& (src
[i
-1] == src
[i
]))
1772 else if(i
< size
&& numequal
*depth
<= 16)
1774 numcopy
+= numequal
; numequal
= 1; ++i
;
1778 /* care for end case, where it maybe better to join the two */
1779 if(i
== size
&& numcopy
+ numequal
<= 128 && (numequal
-1)*depth
<= 8)
1781 numcopy
+= numequal
; numequal
= 0;
1785 if((j
= numcopy
) > 128) j
= 128;
1786 bitbuf
= (bitbuf
<<8) | (j
-1);
1791 if((j
= numequal
) > 128) j
= 128;
1792 bitbuf
= (bitbuf
<<8) | (256-(j
-1));
1797 buf
[ressize
++] = (bitbuf
>> numbits
);
1801 bitbuf
= (bitbuf
<<depth
) | src
[k
++];
1805 buf
[ressize
++] = (bitbuf
>> numbits
);
1808 if(i
< size
&& !numcopy
&& !numequal
)
1815 buf
[ressize
++] = bitbuf
<< (8-numbits
);
1817 if(ressize
> size
) /* no RLE */
1821 for(i
= 0; i
< size
; ++i
)
1832 /****************************************************************************************/
1834 static LONG
writeimagchunk(struct ILBMImage
*img
)
1836 struct imagchunk ic
;
1838 UBYTE skippalette
= 0;
1840 LONG palsize
, gfxsize
;
1841 UBYTE palpacked
, gfxpacked
;
1843 imagsize
= sizeof(struct imagchunk
);
1845 /* if this is second image check whether palette is identical to
1846 the one of first image */
1850 if (img1
.cmapentries
== img2
.cmapentries
)
1854 for (i
= 0; i
< img1
.cmapentries
; i
++)
1856 if (img1
.rgb
[i
][0] != img2
.rgb
[i
][0]) break;
1857 if (img1
.rgb
[i
][1] != img2
.rgb
[i
][1]) break;
1858 if (img1
.rgb
[i
][2] != img2
.rgb
[i
][2]) break;
1861 if (i
== img1
.cmapentries
) skippalette
= 1;
1870 img
->cmapentries
* 3,
1871 (unsigned char *)img
->rgb
);
1873 imagsize
+= palsize
;
1876 gfx
= createrle(img
->bmh
.bmh_Depth
,
1879 img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
,
1882 imagsize
+= gfxsize
;
1885 #define ACT_STRUCT ic
1887 SET_BYTE(ic_transparentcolour
, transparentoption
);
1890 SET_BYTE(ic_numcolours
, 0);
1891 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 1 : 0); /* 1 = HasTransparentColour */
1892 SET_BYTE(ic_paletteformat
, 0);
1893 SET_WORD(ic_numpalettebytes
, 0);
1897 SET_BYTE(ic_numcolours
, img
->cmapentries
- 1);
1898 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 3 : 2); /* 2 = HasPalette */
1899 SET_BYTE(ic_paletteformat
, palpacked
);
1900 SET_WORD(ic_numpalettebytes
, palsize
- 1);
1903 SET_BYTE(ic_imageformat
, gfxpacked
);
1904 SET_BYTE(ic_depth
, img
->bmh
.bmh_Depth
);
1905 SET_WORD(ic_numimagebytes
, gfxsize
- 1);
1908 writelong(imagsize
);
1910 if (fwrite(&ic
, 1, sizeof(ic
), outfile
) != sizeof(ic
))
1912 cleanup("Error writing imag chunk!", 1);
1915 if (fwrite(gfx
, 1, gfxsize
, outfile
) != gfxsize
)
1917 cleanup("Error write gfx data in imag chunk!", 1);
1922 if (fwrite(pal
, 1, palsize
, outfile
) != palsize
)
1924 cleanup("Error write palette data in imag chunk!", 1);
1932 if (fwrite(&dummy
, 1, 1, outfile
) != 1)
1934 cleanup("Error writing imag chunk!", 1);
1940 return imagsize
+ 8;
1943 /****************************************************************************************/
1944 static LONG
writeargb(APTR argb
, ULONG argb_size
)
1947 struct ARGB35_Header
{
1948 ULONG ztype
; /* Always 1 */
1949 ULONG zsize
; /* Compressed size, or -1 */
1950 UWORD resv
; /* Always 0 */
1956 zsize
= size
= argb_size
;
1958 zdest
= malloc(zsize
);
1962 err
= compress(zdest
, &zsize
, argb
, size
);
1968 D(printf("ARGB: Compressed %d => %d\n", size
, zsize
));
1971 formsize
= 10 + zsize
;
1972 writelong(formsize
);
1976 fwrite(zdest
, 1, zsize
, outfile
);
1979 fwrite(&c
, 1, 1, outfile
);
1986 return 8 + formsize
;
1989 /****************************************************************************************/
1991 static void write35data(void)
2000 formsizeseek
= ftell(outfile
);
2001 writelong(0x12345678);
2004 formsize
+= writefacechunk();
2005 formsize
+= writeimagchunk(&img1
);
2006 if (image2option
) formsize
+= writeimagchunk(&img2
);
2008 if (!nosaveARGB
&& img1
.argb
) {
2009 formsize
+= writeargb(img1
.argb
, img1
.argb_size
);
2012 if (!nosaveARGB
&& img2
.argb
) {
2013 formsize
+= writeargb(img2
.argb
, img2
.argb_size
);
2016 if (!nosavePNG
&& img1
.png
) {
2018 writelong(img1
.png_size
);
2019 fwrite(img1
.png
, 1, img1
.png_size
, outfile
);
2020 if (img1
.png_size
& 1) {
2022 fwrite(&c
, 1, 1, outfile
);
2025 formsize
+= 8 + img1
.png_size
;
2028 if (!nosavePNG
&& img2
.png
) {
2030 writelong(img2
.png_size
);
2031 fwrite(img2
.png
, 1, img2
.png_size
, outfile
);
2032 if (img2
.png_size
& 1) {
2034 fwrite(&c
, 1, 1, outfile
);
2037 formsize
+= 8 + img2
.png_size
;
2040 fseek(outfile
, formsizeseek
, SEEK_SET
);
2041 writelong(formsize
);
2044 /****************************************************************************************/
2046 static void writeicon(void)
2048 struct diskobject dobj
;
2050 D(printf("Writing %s\n", outfilename
));
2051 outfile
= fopen(outfilename
, "wb");
2052 if (!outfile
) cleanup("Can't open output file for writing!", 1);
2055 writeolddrawerdata();
2058 if (image2option
) writeimage(&img2
);
2060 if (defaulttooloption
) writestring(defaulttooloption
);
2062 if (tooltypesoption
)
2065 LONG numtooltypes
= 0;
2067 for(strarray
= tooltypesoption
; *strarray
; strarray
++, numtooltypes
++);
2069 writelong((numtooltypes
+ 1) * 4);
2071 for(strarray
= tooltypesoption
; *strarray
; strarray
++)
2073 writestring(*strarray
);
2078 /* toolwindow would have to be saved in between here if there is any */
2080 writenewdrawerdata();
2086 /****************************************************************************************/
2088 static void remapicon(void)
2090 remapplanar(&img1
, &std4colpal
);
2091 if (image2option
) remapplanar(&img2
, &std4colpal
);
2094 /****************************************************************************************/
2096 int main(int argc
, char **argv
)
2098 getarguments(argc
, argv
);
2100 loadimage(image1option
, &img1
);
2102 loadimage(image2option
, &img2
);
2103 if ((img2
.bmh
.bmh_Width
&& img2
.bmh
.bmh_Width
!= img1
.bmh
.bmh_Width
) ||
2104 (img2
.bmh
.bmh_Height
&& img2
.bmh
.bmh_Height
!= img1
.bmh
.bmh_Height
)) {
2105 fprintf(stderr
, "%s: Image %s (%dx%d) is not the same size as Image %s (%dx%d)\n", argv
[0], image1option
, img1
.bmh
.bmh_Width
, img1
.bmh
.bmh_Height
, image2option
, img2
.bmh
.bmh_Width
, img2
.bmh
.bmh_Height
);
2115 /****************************************************************************************/