2 Copyright © 1995-2015, 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
;
174 static long bodysize_packed
;
177 static struct ILBMImage img1
, img2
;
178 static BOOL have_bmhd
, have_cmap
, have_body
, is_png
;
180 /* 'ticks' per dot, corresponding to ~72dpi */
181 static ULONG tpdX
= TPD_X(72), tpdY
= TPD_Y(72);
182 static char *image1option
;
183 static char *image2option
;
184 static char *defaulttooloption
;
185 static char *drawerdataoption
;
186 static char **tooltypesoption
;
187 static LONG typeoption
= 3; /* WBTOOL */
188 static LONG iconleftoption
= 0x80000000; /* NO_ICON_POSITION */
189 static LONG icontopoption
= 0x80000000; /* NO_ICON_POSITION */
190 static LONG stackoption
= 4096;
191 static LONG drawerleftoption
= 50;
192 static LONG drawertopoption
= 50;
193 static LONG drawerwidthoption
= 400;
194 static LONG drawerheightoption
= 100;
195 static LONG drawervleftoption
= 0;
196 static LONG drawervtopoption
= 0;
197 static LONG drawershowoption
= 0;
198 static LONG drawershowasoption
= 0;
199 static LONG transparentoption
= -1;
201 static BOOL dualpng
; /* png file contains second image */
202 static unsigned char *dualpngstart
; /* address of 2nd image in filebuffer */
203 static BOOL nosavePNG
; /* Don't save the original PNG data */
204 static BOOL nosaveARGB
; /* Don't ARGB data */
205 static BOOL nosaveIFF
; /* Don't save any IFF data */
207 /****************************************************************************************/
209 static void freeimage(struct ILBMImage
*img
)
211 if (img
->chunkybuffer
)
213 free(img
->chunkybuffer
);
214 img
->chunkybuffer
= NULL
;
217 if (img
->planarbuffer
)
219 free(img
->planarbuffer
);
220 img
->planarbuffer
= NULL
;
244 /****************************************************************************************/
246 static void cleanup(char *msg
, int rc
)
248 if (msg
) fprintf(stderr
, "ilbmtoicon: %s\n", msg
);
253 if (outfile
) fclose(outfile
);
254 if (infile
) fclose(infile
);
259 /****************************************************************************************/
261 static void getarguments(int argc
, char **argv
)
269 for (; argc
> 1 && argv
[1][0] == '-'; argc
--, argv
++) {
270 if (strcmp(argv
[1],"--png") == 0) {
274 if (strcmp(argv
[1],"--no-iff") == 0) {
278 if (strcmp(argv
[1],"--no-argb") == 0) {
282 if (strcmp(argv
[1],"--dpi") == 0) {
287 dpiX
= strtol(argv
[1], &cp
, 0);
290 dpiY
= strtol(cp
, NULL
, 0);
301 if ((argc
!= 4) && (argc
!= 5))
303 fprintf(stderr
, "Wrong number of arguments\n");
304 cleanup("Usage: ilbmtoicon [--png] [--no-argb] [--no-iff] icondescription image1 [image2] filename", 1);
309 infilename
= argv
[1];
310 image1option
= argv
[2];
311 outfilename
= argv
[3];
315 infilename
= argv
[1];
316 image1option
= argv
[2];
317 image2option
= argv
[3];
318 outfilename
= argv
[4];
322 /****************************************************************************************/
324 static char *skipblanks(char *s
)
326 while ((*s
== ' ') || (*s
== '\t')) s
++;
331 /****************************************************************************************/
333 static char *skipword(char *s
)
346 /****************************************************************************************/
348 static char *checkquotes(char *s
)
366 while ((i
< 256) && (s3
[i
] = *s
))
389 /****************************************************************************************/
391 #define KEYWORD_STRING 0
392 #define KEYWORD_INTEGER 1
393 #define KEYWORD_STRINGARRAY 2
394 #define KEYWORD_CYCLE 3
396 #define MAX_ARRAY_SIZE 200
398 /****************************************************************************************/
406 struct cycle typecycles
[] =
418 struct cycle showcycles
[] =
427 struct cycle showascycles
[] =
440 /****************************************************************************************/
451 {KEYWORD_STRING
, "DEFAULTTOOL" , &defaulttooloption
, NULL
},
452 {KEYWORD_STRING
, "DRAWERDATA" , &drawerdataoption
, NULL
},
453 {KEYWORD_CYCLE
, "TYPE" , &typeoption
, typecycles
},
454 {KEYWORD_STRINGARRAY
, "TOOLTYPE" , &tooltypesoption
, NULL
},
455 {KEYWORD_INTEGER
, "STACK" , &stackoption
, NULL
},
456 {KEYWORD_INTEGER
, "ICONLEFTPOS" , &iconleftoption
, NULL
},
457 {KEYWORD_INTEGER
, "ICONTOPPOS" , &icontopoption
, NULL
},
458 {KEYWORD_INTEGER
, "DRAWERLEFTPOS" , &drawerleftoption
, NULL
},
459 {KEYWORD_INTEGER
, "DRAWERTOPPOS" , &drawertopoption
, NULL
},
460 {KEYWORD_INTEGER
, "DRAWERWIDTH" , &drawerwidthoption
, NULL
},
461 {KEYWORD_INTEGER
, "DRAWERHEIGHT" , &drawerheightoption
, NULL
},
462 {KEYWORD_INTEGER
, "DRAWERVIEWLEFT" , &drawervleftoption
, NULL
},
463 {KEYWORD_INTEGER
, "DRAWERVIEWTOP" , &drawervtopoption
, NULL
},
464 {KEYWORD_CYCLE
, "DRAWERSHOW" , &drawershowoption
, showcycles
},
465 {KEYWORD_CYCLE
, "DRAWERSHOWAS" , &drawershowoption
, showascycles
},
466 {KEYWORD_INTEGER
, "TRANSPARENT" , &transparentoption
, NULL
},
471 /****************************************************************************************/
473 static void handleoption(char *keyword
, char *keyvalue
)
478 D(printf("Keyword %s, value %s\n", keyword
, keyvalue
));
480 for(kw
= keywordtable
; kw
->keyword
; kw
++)
482 if (strcasecmp(kw
->keyword
, keyword
) == 0)
487 *(char **)kw
->store
= strdup(keyvalue
);
488 if (!(*(char **)kw
->store
)) cleanup("Out of memory!", 1);
491 case KEYWORD_INTEGER
:
492 *(LONG
*)kw
->store
= strtol(keyvalue
, 0, 0);
496 for(cy
= (struct cycle
*)kw
->extra
; cy
->keyword
; cy
++)
498 if (strcasecmp(keyvalue
, cy
->keyword
) == 0)
500 *(LONG
*)kw
->store
= cy
->value
;
506 case KEYWORD_STRINGARRAY
:
507 if (!(*(char ***)kw
->store
))
509 *(char ***)kw
->store
= (char **)malloc(MAX_ARRAY_SIZE
* sizeof(char *));
510 if (!(*(char ***)kw
->store
)) cleanup("Out of memory!", 1);
512 memset(*(char ***)kw
->store
, 0, MAX_ARRAY_SIZE
* sizeof(char *));
517 char **strarray
= *(char ***)kw
->store
;
520 dupvalue
= strdup(keyvalue
);
521 if (!dupvalue
) cleanup("Out of memory!", 1);
529 if (i
>= MAX_ARRAY_SIZE
- 1) cleanup("Array overflow!", 1);
531 *strarray
= dupvalue
;
534 } /* switch(kw->type) */
538 } /* if (strcasecmp(kw->keyword, keyword) == 0) */
540 } /* for(kw = keywordtable; kw->keyword; kw++) */
544 /****************************************************************************************/
546 static void parseline(char *s
)
549 char *keyvalue
= NULL
;
553 if (*s
== '#') return;
554 if (*s
== ';') return;
559 if (*s
== '\0') return;
562 s
= skipblanks(s
+ 1);
564 if (*s
== '=') s
= skipblanks(s
+ 1);
565 if (*s
== '\0') return;
567 keyvalue
= checkquotes(s
);
569 handleoption(keyword
, keyvalue
);
572 /****************************************************************************************/
574 static void parseiconsource(void)
578 infile
= fopen(infilename
, "r");
581 while(fgets(s
, sizeof(s
), infile
))
583 D(printf("Read line: %s\n", s
));
592 /****************************************************************************************/
595 static void showoptions(void)
599 printf("image1: %s\n", image1option
? image1option
: "(NULL)");
600 printf("image2: %s\n", image2option
? image2option
: "(NULL)");
601 printf("type: %ld\n", typeoption
);
603 strarray
= tooltypesoption
;
606 printf("tooltypes:\n");
609 printf(" %s\n", *strarray
++);
615 /****************************************************************************************/
617 static ULONG
getlong(void)
621 if (filepos
> filesize
- 4) cleanup("Tried to read over file end!", 1);
623 ret
= filebuffer
[filepos
++] * 0x1000000;
624 ret
+= filebuffer
[filepos
++] * 0x10000;
625 ret
+= filebuffer
[filepos
++] * 0x100;
626 ret
+= filebuffer
[filepos
++];
631 /****************************************************************************************/
633 static UWORD
getword(void)
637 if (filepos
> filesize
- 2) cleanup("Tried to read over file end!", 1);
639 ret
= filebuffer
[filepos
++] * 0x100;
640 ret
+= filebuffer
[filepos
++];
645 /****************************************************************************************/
647 static UBYTE
getbyte(void)
651 if (filepos
> filesize
- 1) cleanup("Tried to read over file end!", 1);
652 ret
= filebuffer
[filepos
++];
657 /****************************************************************************************/
659 static void skipbytes(ULONG howmany
)
664 /****************************************************************************************/
666 static void openimage(struct ILBMImage
*img
)
668 file
= fopen(filename
, "rb");
669 if (!file
) cleanup("Can't open file!", 1);
671 fseek(file
, 0, SEEK_END
);
672 filesize
= ftell(file
);
674 if (filesize
< 12) cleanup("Bad file size!", 1);
676 //fprintf(stderr, "Filesize is %d\n", filesize);
678 fseek(file
, 0, SEEK_SET
);
680 filebuffer
= malloc(filesize
+ 10);
681 if (!filebuffer
) cleanup("Memory allocation for file buffer failed!", 1);
683 if (fread(filebuffer
, 1, filesize
, file
) != filesize
)
684 cleanup("Error reading file!", 1);
686 fclose(file
); file
= NULL
;
689 /****************************************************************************************/
691 static void checkimage(struct ILBMImage
*img
)
693 static UBYTE pngsig
[8] = {137, 80, 78, 71, 13, 10, 26, 10};
699 img
->png
= dualpngstart
;
700 img
->png_size
= filesize
- (dualpngstart
- filebuffer
);
704 if (memcmp(filebuffer
, pngsig
, 8) == 0)
707 img
->png
= filebuffer
;
709 /* search for second image */
712 dualpngstart
= filebuffer
+ 8 ;
713 dualpngstart
< filebuffer
+ filesize
- 8 ;
717 if (memcmp(dualpngstart
, pngsig
, 8) == 0)
724 img
->png_size
= dualpngstart
- filebuffer
;
726 img
->png_size
= filesize
;
728 else if (is_png
== 0)
731 if (id
!= ID_FORM
) cleanup("File is not an IFF file!", 1);
734 if (size
!= filesize
- 8) cleanup("File is IFF, but has bad size in IFF header!", 1);
737 if (id
!= ID_ILBM
) cleanup("File is IFF, but not of type ILBM!", 1);
739 else if (is_png
== 1)
741 cleanup("Second image must be a PNG image, too!", 1);
746 /****************************************************************************************/
748 static void my_read_fn(png_structp png_ptr
, png_bytep data
, png_size_t length
)
750 png_bytep
*pdata
= png_get_io_ptr(png_ptr
);
752 if (*pdata
-filebuffer
>= filesize
)
753 png_error(png_ptr
, "Read past end of file");
755 memcpy(data
, *pdata
, length
);
759 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
);
761 static void loadpng(struct ILBMImage
*img
, struct Palette
*pal
)
764 png_infop info_ptr
, end_info
;
765 png_bytep fpos
, *row_pointers
;
770 if (png_sig_cmp(img
->png
, 0, img
->png_size
) != 0)
771 cleanup("I thought it was a PNG, but I was wrong.", 1);
773 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
,
778 cleanup("png_create_read_struct() failed", 1);
780 info_ptr
= png_create_info_struct(png_ptr
);
782 png_destroy_read_struct(&png_ptr
, NULL
, NULL
);
783 cleanup("png_create_info_struct() failed", 1);
786 end_info
= png_create_info_struct(png_ptr
);
788 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
789 cleanup("png_create_info_struct() failed", 1);
793 png_set_read_fn(png_ptr
, &fpos
, my_read_fn
);
795 if (setjmp(png_jmpbuf(png_ptr
))) {
796 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
797 cleanup("png read failed", 1);
800 /* Read the PNG as RGBA */
801 png_set_add_alpha(png_ptr
, 255, PNG_FILLER_AFTER
);
802 png_read_png(png_ptr
, info_ptr
, PNG_TRANSFORM_EXPAND
| PNG_TRANSFORM_STRIP_16
, NULL
);
804 row_pointers
= png_get_rows(png_ptr
, info_ptr
);
806 width
= png_get_image_width(png_ptr
, info_ptr
);
807 height
= png_get_image_height(png_ptr
, info_ptr
);
809 img
->bmh
.bmh_Width
= width
;
810 img
->bmh
.bmh_Height
= height
;
811 img
->bmh
.bmh_Left
= 0;
812 img
->bmh
.bmh_Top
= 0;
813 img
->bmh
.bmh_Depth
= 8;
814 img
->bmh
.bmh_Masking
= MSK_HASTRANS
;
815 img
->bmh
.bmh_Compression
= CMP_NONE
;
816 img
->bmh
.bmh_Pad
= 0;
817 img
->bmh
.bmh_XAspect
= 1;
818 img
->bmh
.bmh_YAspect
= 1;
819 img
->bmh
.bmh_PageWidth
= 320;
820 img
->bmh
.bmh_PageHeight
= 200;
825 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
828 /* Transform the RGBA data into chunky */
829 img
->cmapentries
= pal
->numentries
;
830 memcpy(img
->rgb
, pal
->rgb
, sizeof(img
->rgb
[0])*pal
->numentries
);
832 img
->chunkybuffer
= malloc(width
* height
* sizeof(UBYTE
));
833 if (!img
->chunkybuffer
)
834 cleanup("Can't allocate the chunky buffer", 1);
836 chunkrow
= img
->chunkybuffer
;
837 img
->argb_size
= width
* height
* sizeof(UBYTE
) * 4;
838 img
->argb
= malloc(img
->argb_size
);
840 cleanup("Can't allocate the ARGB buffer", 1);
842 for (y
= 0; y
< height
; y
++) {
843 png_bytep row
= row_pointers
[y
];
844 UBYTE
*ap
= img
->argb
+ (width
* sizeof(UBYTE
) * 4) * y
;
845 for (x
= 0; x
< width
; x
++, row
+= 4, ap
+= 4, chunkrow
++) {
853 /* Opacity of 0? Use the transparency color */
855 if (transparentoption
< 0)
856 transparentoption
= 0;
857 *chunkrow
= transparentoption
;
863 *chunkrow
= findcolor(pal
, r
, g
, b
, TRUE
);
868 img
->bmh
.bmh_Transparent
= transparentoption
;
870 png_destroy_read_struct(&png_ptr
, &info_ptr
, &end_info
);
874 /****************************************************************************************/
876 static void scanimage(struct ILBMImage
*img
)
885 /* Load the PNG, using the Scalos 16-color pallette,
886 * into the Chunky buffer.
888 loadpng(img
, &scalos16colpal
);
900 //fprintf(stderr, "Chunk: %c%c%c%c Size: %d\n", id >> 24, id >> 16, id >> 8, id, size);
905 if (size
!= 20) cleanup("Bad BMHD chunk size!", 1);
907 img
->bmh
.bmh_Width
= getword();
908 img
->bmh
.bmh_Height
= getword();
909 img
->bmh
.bmh_Left
= (WORD
)getword();
910 img
->bmh
.bmh_Top
= (WORD
)getword();
911 img
->bmh
.bmh_Depth
= getbyte();
912 img
->bmh
.bmh_Masking
= getbyte();
913 img
->bmh
.bmh_Compression
= getbyte();
914 img
->bmh
.bmh_Pad
= getbyte();
915 img
->bmh
.bmh_Transparent
= getword();
916 img
->bmh
.bmh_XAspect
= getbyte();
917 img
->bmh
.bmh_YAspect
= getbyte();
918 img
->bmh
.bmh_PageWidth
= (WORD
)getword();
919 img
->bmh
.bmh_PageHeight
= (WORD
)getword();
921 if (img
->bmh
.bmh_Depth
> 8) cleanup("ILBM file has too many colors!", 1);
922 if ((img
->bmh
.bmh_Compression
!= CMP_NONE
) && (img
->bmh
.bmh_Compression
!= CMP_BYTERUN1
)) cleanup("Compression method unsupported!", 1);
926 img
->totdepth
= img
->bmh
.bmh_Depth
+ ((img
->bmh
.bmh_Masking
== MSK_HASMASK
) ? 1 : 0);
928 img
->bpr
= ((img
->bmh
.bmh_Width
+ 15) & ~15) / 8;
930 /*fprintf(stderr, "BMHD: %d x %d x %d (%d)\n", img->bmh.bmh_Width,
934 img
->planarbmh
= img
->bmh
;
938 if (!have_bmhd
) cleanup("CMAP chunk before BMHD chunk (or no BMHD chunk at all!", 1);
940 img
->cmapentries
= size
/ 3;
941 if (size
& 1) size
++;
943 if ((img
->cmapentries
< 2) || (img
->cmapentries
> 256)) cleanup("CMAP chunk has bad number of entries!", 1);
945 for(i
= 0; i
< img
->cmapentries
; i
++)
947 img
->rgb
[i
][0] = getbyte();
948 img
->rgb
[i
][1] = getbyte();
949 img
->rgb
[i
][2] = getbyte();
960 if (!have_bmhd
) cleanup("BODY chunk before BMHD chunk (or no BMHD chunk at all!", 1);
961 body
= &filebuffer
[filepos
];
964 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
966 LONG shouldbesize
= img
->totdepth
* img
->bpr
* img
->bmh
.bmh_Height
;
967 if (bodysize
!= shouldbesize
) cleanup("BODY chunk size seems to be wrong!", 1);
974 if (size
& 1) size
++;
979 if (filepos
== filesize
) break;
980 if (have_bmhd
&& have_body
&& have_cmap
) break;
983 if (!have_bmhd
) cleanup("BMHD chunk missing!", 1);
984 if (!have_body
) cleanup("BODY chunk missing!", 1);
987 /****************************************************************************************/
989 static unsigned char *unpack_byterun1(unsigned char *source
, unsigned char *dest
, LONG unpackedsize
)
996 c
= (signed char)(*source
++);
1001 *dest
++ = *source
++;
1002 if (--unpackedsize
<= 0) return source
;
1013 if (--unpackedsize
<= 0) return source
;
1020 /****************************************************************************************/
1023 static BOOL
norm1(LONG count
, unsigned char **source_backup
,
1024 unsigned char **dest
, LONG
*checksize
)
1026 //if (count >= 0) fprintf(stderr, "XX: non packable %d\n",count);
1032 if (step
> 127) step
= 127;
1037 if (*checksize
<= 0) return 0;
1046 *(*dest
)++ = *(*source_backup
)++;
1056 static BOOL
copy1(unsigned char r
, LONG count
, unsigned char **dest
, LONG
*checksize
)
1058 //if (count >= 1) fprintf(stderr, "XX: repeat %02x x %d\n", r, count);
1064 if (step
> 127) step
= 127;
1069 if (*checksize
<= 0) return 0;
1071 *(*dest
)++ = (unsigned char)step
;
1078 static BOOL
pack_byterun1(unsigned char *source
, unsigned char *dest
,
1079 LONG size
, LONG check_size
, LONG
*packsize
)
1081 unsigned char *source_backup
, *dest_backup
;
1082 LONG samebytes_counter
, samebytes
, count
;
1083 LONG checksize
= check_size
;
1084 unsigned char oldbyte
, actbyte
;
1086 if (checksize
< 0) checksize
= 0x7FFFFFFF;
1089 samebytes_counter
= 0;
1090 source_backup
= source
;
1095 //fprintf(stderr, "size = %d. checksize = %d\n", size, checksize);
1096 if (--size
< 0) break;
1097 actbyte
= *source
++;
1098 if (actbyte
== oldbyte
)
1100 samebytes_counter
++;
1106 samebytes
= samebytes_counter
;
1107 samebytes_counter
= 1;
1109 if (samebytes
< 3) continue;
1111 count
= (LONG
)(source
- source_backup
- samebytes
- 2);
1112 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1114 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1116 source_backup
= source
- 1;
1118 //fprintf(stderr, "done\n");
1120 if (samebytes_counter
>= 3)
1122 samebytes
= samebytes_counter
;
1123 count
= (LONG
)(source
- source_backup
- samebytes
- 1);
1124 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1125 if (!copy1(source
[-2], samebytes
, &dest
, &checksize
)) return 0;
1129 count
= (LONG
)(source
- source_backup
- 1);
1130 if (!norm1(count
, &source_backup
, &dest
, &checksize
)) return 0;
1132 //fprintf(stderr, "realdone\n");
1134 if (packsize
) *packsize
= (LONG
)(dest
- dest_backup
);
1140 /****************************************************************************************/
1142 static void p2c(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
,
1143 LONG totplanes
, LONG wantplanes
, LONG chunkybpr
)
1145 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1147 alignedwidth
= (width
+ 15) & ~15;
1148 bpr
= alignedwidth
/ 8;
1149 bpl
= bpr
* totplanes
;
1151 for(y
= 0; y
< height
; y
++)
1153 for(x
= 0; x
< width
; x
++)
1155 LONG mask
= 0x80 >> (x
& 7);
1156 LONG offset
= x
/ 8;
1157 unsigned char chunkypix
= 0;
1159 for(p
= 0; p
< wantplanes
; p
++)
1161 if (source
[p
* bpr
+ offset
] & mask
) chunkypix
|= (1 << p
);
1163 dest
[x
] = chunkypix
;
1173 /****************************************************************************************/
1175 static void c2p(unsigned char *source
, unsigned char *dest
, LONG width
, LONG height
, LONG planes
)
1177 LONG alignedwidth
, x
, y
, p
, bpr
, bpl
;
1179 alignedwidth
= (width
+ 15) & ~15;
1180 bpr
= alignedwidth
/ 8;
1183 for(y
= 0; y
< height
; y
++)
1185 for(x
= 0; x
< width
; x
++)
1187 LONG mask
= 0x80 >> (x
& 7);
1188 LONG offset
= x
/ 8;
1189 unsigned char chunkypix
= source
[x
];
1191 for(p
= 0; p
< planes
; p
++)
1193 if (chunkypix
& (1 << p
))
1194 dest
[p
* bpr
+ offset
] |= mask
;
1196 dest
[p
* bpr
+ offset
] &= ~mask
;
1206 /****************************************************************************************/
1208 static void convertbody(struct ILBMImage
*img
)
1210 LONG unpackedsize
= img
->bpr
* img
->bmh
.bmh_Height
* img
->totdepth
;
1215 img
->planarbuffer
= malloc(unpackedsize
);
1216 if (!img
->planarbuffer
) cleanup("Memory allocation for planar buffer failed!", 1);
1218 if (img
->bmh
.bmh_Compression
== CMP_NONE
)
1220 memcpy(img
->planarbuffer
, body
, unpackedsize
);
1224 unpack_byterun1(body
, img
->planarbuffer
, unpackedsize
);
1227 img
->chunkybuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1228 if (!img
->chunkybuffer
) cleanup("Memory allocation for chunky buffer failed!", 1);
1230 p2c(img
->planarbuffer
,
1233 img
->bmh
.bmh_Height
,
1236 img
->bmh
.bmh_Width
);
1239 /****************************************************************************************/
1241 static UBYTE
findcolor(struct Palette
*pal
, ULONG r
, ULONG g
, ULONG b
, BOOL notrans
)
1243 ULONG dist
, bestdist
= 0xFFFFFFFF;
1246 for(i
= 0; i
< pal
->numentries
; i
++)
1248 LONG r1
, g1
, b1
, r2
, g2
, b2
, dr
, dg
, db
;
1250 if (notrans
&& i
== transparentoption
)
1257 r2
= (LONG
)pal
->rgb
[i
][0];
1258 g2
= (LONG
)pal
->rgb
[i
][1];
1259 b2
= (LONG
)pal
->rgb
[i
][2];
1265 dist
= (dr
* dr
) + (dg
* dg
) + (db
* db
);
1266 if (dist
< bestdist
)
1277 /****************************************************************************************/
1279 static void remapplanar(struct ILBMImage
*img
, struct Palette
*pal
)
1285 LONG i
, highestcol
= 0, newdepth
= 0;
1287 remapbuffer
= malloc(img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
);
1288 if (!remapbuffer
) cleanup("Error allocating remap buffer!", 1);
1290 for(i
= 0; i
< img
->cmapentries
; i
++)
1292 img
->remaptable
[i
] = findcolor(pal
, img
->rgb
[i
][0], img
->rgb
[i
][1], img
->rgb
[i
][2], FALSE
);
1295 for(i
= 0; i
< img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
; i
++)
1297 remapbuffer
[i
] = img
->remaptable
[img
->chunkybuffer
[i
]];
1299 if (remapbuffer
[i
] > highestcol
)
1300 highestcol
= remapbuffer
[i
];
1303 for(i
= highestcol
; i
; i
>>= 1) newdepth
++;
1304 if (newdepth
== 0) newdepth
= 1;
1306 if (newdepth
> img
->totdepth
)
1308 if (img
->planarbuffer
)
1309 free(img
->planarbuffer
);
1311 img
->planarbuffer
= malloc(img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1312 if (!img
->planarbuffer
)
1315 cleanup("Error re-allocating planar buffer!", 1);
1319 img
->planarbmh
.bmh_Width
= img
->bmh
.bmh_Width
;
1320 img
->planarbmh
.bmh_Height
= img
->bmh
.bmh_Height
;
1321 img
->planarbmh
.bmh_Depth
= newdepth
;
1323 memset(img
->planarbuffer
, 0, img
->bpr
* img
->bmh
.bmh_Height
* newdepth
);
1325 c2p(remapbuffer
, img
->planarbuffer
, img
->bmh
.bmh_Width
, img
->bmh
.bmh_Height
, newdepth
);
1330 /****************************************************************************************/
1332 static void loadimage(char *name
, struct ILBMImage
*img
)
1344 /****************************************************************************************/
1349 UBYTE do_version
[2];
1350 UBYTE do_gadget_nextgadget
[4];
1351 UBYTE do_gadget_leftedge
[2];
1352 UBYTE do_gadget_topedge
[2];
1353 UBYTE do_gadget_width
[2];
1354 UBYTE do_gadget_height
[2];
1355 UBYTE do_gadget_flags
[2];
1356 UBYTE do_gadget_activation
[2];
1357 UBYTE do_gadget_gadgettype
[2];
1358 UBYTE do_gadget_gadgetrender
[4];
1359 UBYTE do_gadget_selectrender
[4];
1360 UBYTE do_gadget_gadgettext
[4];
1361 UBYTE do_gadget_mutualexclude
[4];
1362 UBYTE do_gadget_specialinfo
[4];
1363 UBYTE do_gadget_gadgetid
[2];
1364 UBYTE do_gadget_userdata
[4];
1367 UBYTE do_defaulttool
[4];
1368 UBYTE do_tooltypes
[4];
1369 UBYTE do_currentx
[4];
1370 UBYTE do_currenty
[4];
1371 UBYTE do_drawerdata
[4];
1372 UBYTE do_toolwindow
[4];
1373 UBYTE do_stacksize
[4];
1376 /****************************************************************************************/
1378 struct olddrawerdata
1380 UBYTE dd_newwindow_leftedge
[2];
1381 UBYTE dd_newwindow_topedge
[2];
1382 UBYTE dd_newwindow_width
[2];
1383 UBYTE dd_newwindow_height
[2];
1384 UBYTE dd_newwindow_detailpen
;
1385 UBYTE dd_newwindow_blockpen
;
1386 UBYTE dd_newwindow_idcmpflags
[4];
1387 UBYTE dd_newwindow_flags
[4];
1388 UBYTE dd_newwindow_firstgadget
[4];
1389 UBYTE dd_newwindow_checkmark
[4];
1390 UBYTE dd_newwindow_title
[4];
1391 UBYTE dd_newwindow_screen
[4];
1392 UBYTE dd_newwindow_bitmap
[4];
1393 UBYTE dd_newwindow_minwidth
[2];
1394 UBYTE dd_newwindow_minheight
[2];
1395 UBYTE dd_newwindow_maxwidth
[2];
1396 UBYTE dd_newwindow_maxheight
[2];
1397 UBYTE dd_newwindow_type
[2];
1398 UBYTE dd_currentx
[4];
1399 UBYTE dd_currenty
[4];
1402 /****************************************************************************************/
1404 struct newdrawerdata
1407 UBYTE dd_viewmodes
[2];
1410 /****************************************************************************************/
1425 /****************************************************************************************/
1427 #define SET_BYTE(field,value) \
1428 ACT_STRUCT.field = value
1430 #define SET_WORD(field, value) \
1431 ACT_STRUCT.field[0] = ((value) >> 8) & 0xFF; \
1432 ACT_STRUCT.field[1] = (value) & 0xFF;
1434 #define SET_LONG(field,value) \
1435 ACT_STRUCT.field[0] = ((value) >> 24) & 0xFF; \
1436 ACT_STRUCT.field[1] = ((value) >> 16) & 0xFF; \
1437 ACT_STRUCT.field[2] = ((value) >> 8) & 0xFF; \
1438 ACT_STRUCT.field[3] = (value) & 0xFF;
1440 #define BOOL_YES 0x2A2A2A2A
1441 #define BOOL_NO 0x00000000
1443 static void writediskobject(void)
1445 struct diskobject dobj
;
1447 if (typeoption
== 2) /* DRAWER */
1449 drawerdataoption
= "YES";
1452 #define ACT_STRUCT dobj
1454 SET_WORD(do_magic
, 0xE310);
1455 SET_WORD(do_version
, 1);
1456 SET_LONG(do_gadget_nextgadget
, 0);
1457 SET_WORD(do_gadget_leftedge
, 0);
1458 SET_WORD(do_gadget_topedge
, 0);
1459 SET_WORD(do_gadget_width
, img1
.bmh
.bmh_Width
);
1460 SET_WORD(do_gadget_height
, img1
.bmh
.bmh_Height
);
1464 /* GFLG_GADGHIMAGE + GFLG_GADGIMAGE */
1465 SET_WORD(do_gadget_flags
, 4 + 2);
1469 /* GFLG_GADGIMAGE */
1470 SET_WORD(do_gadget_flags
, 4);
1473 SET_WORD(do_gadget_activation
, 1);
1474 SET_WORD(do_gadget_gadgettype
, 1);
1475 SET_LONG(do_gadget_gadgetrender
, BOOL_YES
);
1479 SET_LONG(do_gadget_selectrender
, BOOL_YES
);
1483 SET_LONG(do_gadget_selectrender
, BOOL_NO
);
1486 SET_LONG(do_gadget_gadgettext
, 0);
1487 SET_LONG(do_gadget_mutualexclude
, (1 << 31) | (tpdX
<< 8) | (tpdY
<< 0));
1488 SET_LONG(do_gadget_specialinfo
, 0);
1489 SET_WORD(do_gadget_gadgetid
, 0);
1490 SET_LONG(do_gadget_userdata
, 1); /* full drawer data */
1492 SET_BYTE(do_type
, typeoption
);
1493 SET_BYTE(do_pad
, 0);
1495 if (defaulttooloption
)
1497 SET_LONG(do_defaulttool
, BOOL_YES
);
1501 SET_LONG(do_defaulttool
, BOOL_NO
);
1504 if (tooltypesoption
)
1506 SET_LONG(do_tooltypes
, BOOL_YES
);
1510 SET_LONG(do_tooltypes
, BOOL_NO
);
1513 SET_LONG(do_currentx
, iconleftoption
);
1514 SET_LONG(do_currenty
, icontopoption
);
1516 if (drawerdataoption
)
1518 SET_LONG(do_drawerdata
, BOOL_YES
);
1522 SET_LONG(do_drawerdata
, BOOL_NO
);
1526 SET_LONG(do_toolwindow
, 0);
1527 SET_LONG(do_stacksize
, stackoption
);
1529 if (fwrite(&dobj
, 1, sizeof(dobj
), outfile
) != sizeof(dobj
))
1531 cleanup("Error writing diskobject structure to outfile!", 1);
1535 /****************************************************************************************/
1537 static void writeolddrawerdata(void)
1539 struct olddrawerdata dd
;
1541 if (!drawerdataoption
) return;
1544 #define ACT_STRUCT dd
1546 SET_WORD(dd_newwindow_leftedge
, drawerleftoption
);
1547 SET_WORD(dd_newwindow_topedge
, drawertopoption
);
1548 SET_WORD(dd_newwindow_width
, drawerwidthoption
);
1549 SET_WORD(dd_newwindow_height
, drawerheightoption
);
1550 SET_BYTE(dd_newwindow_detailpen
, 255);
1551 SET_BYTE(dd_newwindow_blockpen
, 255);
1552 SET_LONG(dd_newwindow_idcmpflags
, 0);
1553 SET_LONG(dd_newwindow_flags
, 0x240027f);
1554 SET_LONG(dd_newwindow_firstgadget
, 0);
1555 SET_LONG(dd_newwindow_checkmark
, 0);
1556 SET_LONG(dd_newwindow_title
, 0);
1557 SET_LONG(dd_newwindow_screen
, 0);
1558 SET_LONG(dd_newwindow_bitmap
, 0);
1559 SET_WORD(dd_newwindow_minwidth
, 90);
1560 SET_WORD(dd_newwindow_minheight
, 40);
1561 SET_WORD(dd_newwindow_maxwidth
, 65535);
1562 SET_WORD(dd_newwindow_maxheight
, 65535);
1563 SET_WORD(dd_newwindow_type
, 1);
1564 SET_LONG(dd_currentx
, drawervleftoption
);
1565 SET_LONG(dd_currenty
, drawervtopoption
);
1567 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1569 cleanup("Error writing olddrawerdata structure to outfile!", 1);
1575 /****************************************************************************************/
1577 static void writenewdrawerdata(void)
1579 struct newdrawerdata dd
;
1581 if (!drawerdataoption
) return;
1584 #define ACT_STRUCT dd
1586 SET_LONG(dd_flags
, drawershowoption
);
1587 SET_WORD(dd_viewmodes
, drawershowasoption
);
1589 if (fwrite(&dd
, 1, sizeof(dd
), outfile
) != sizeof(dd
))
1591 cleanup("Error writing newdrawerdata structure to outfile!", 1);
1596 /****************************************************************************************/
1598 static void writeword(WORD l
)
1602 f
[0] = (l
>> 8) & 0xFF;
1605 if (fwrite(f
, 1, 2, outfile
) != 2)
1607 cleanup("Error writing word value!", 1);
1612 /****************************************************************************************/
1614 static void writelong(LONG l
)
1618 f
[0] = (l
>> 24) & 0xFF;
1619 f
[1] = (l
>> 16) & 0xFF;
1620 f
[2] = (l
>> 8) & 0xFF;
1623 if (fwrite(f
, 1, 4, outfile
) != 4)
1625 cleanup("Error writing long value!", 1);
1630 /****************************************************************************************/
1633 static void writenormalstring(char *s
)
1635 int len
= strlen(s
) + 1;
1637 if (fwrite(s
, 1, len
, outfile
) != len
)
1639 cleanup("Error writing string!", 1);
1644 /****************************************************************************************/
1646 static void writestring(char *s
)
1648 int len
= strlen(s
) + 1;
1650 D(printf("String: \"%s\", length %d\n", s
, len
));
1654 if (fwrite(s
, 1, len
, outfile
) != len
)
1656 cleanup("Error writing string!", 1);
1661 /****************************************************************************************/
1663 static void writeimage(struct ILBMImage
*img
)
1669 #define ACT_STRUCT i
1671 SET_WORD(leftedge
, 0);
1672 SET_WORD(topedge
, 0);
1673 SET_WORD(width
, img
->planarbmh
.bmh_Width
);
1674 SET_WORD(height
, img
->planarbmh
.bmh_Height
);
1675 SET_WORD(depth
, img
->planarbmh
.bmh_Depth
);
1676 SET_LONG(imagedata
, BOOL_YES
);
1677 SET_BYTE(planepick
, (1 << img
->planarbmh
.bmh_Depth
) - 1);
1678 SET_BYTE(planeonoff
, 0);
1679 SET_LONG(nextimage
, 0);
1681 if (fwrite(&i
, 1, sizeof(i
), outfile
) != sizeof(i
))
1683 cleanup("Error writing image structure to outfile!", 1);
1686 for(d
= 0; d
< img
->planarbmh
.bmh_Depth
; d
++)
1688 UBYTE
*dat
= img
->planarbuffer
+ img
->bpr
* d
;
1690 for(y
= 0; y
< img
->planarbmh
.bmh_Height
; y
++)
1692 if(fwrite(dat
, 1, img
->bpr
, outfile
) != img
->bpr
)
1694 cleanup("Error writing image data to outfile!", 1);
1696 dat
+= (img
->planarbmh
.bmh_Depth
* img
->bpr
);
1702 /****************************************************************************************/
1710 UBYTE fc_maxpalettebytes
[2];
1713 /****************************************************************************************/
1717 UBYTE ic_transparentcolour
;
1718 UBYTE ic_numcolours
;
1720 UBYTE ic_imageformat
;
1721 UBYTE ic_paletteformat
;
1723 UBYTE ic_numimagebytes
[2];
1724 UBYTE ic_numpalettebytes
[2];
1727 /****************************************************************************************/
1729 static LONG
writefacechunk(void)
1731 struct facechunk fc
;
1735 #define ACT_STRUCT fc
1738 writelong(sizeof(struct facechunk
));
1740 SET_BYTE(fc_width
, img1
.bmh
.bmh_Width
- 1);
1741 SET_BYTE(fc_height
, img1
.bmh
.bmh_Height
- 1);
1742 SET_BYTE(fc_flags
, 0);
1743 SET_BYTE(fc_aspect
, 0); // 0x11);
1745 palbytes
= (img1
.cmapentries
> img2
.cmapentries
) ? img1
.cmapentries
: img2
.cmapentries
;
1746 palbytes
= palbytes
* 3;
1748 SET_WORD(fc_maxpalettebytes
, palbytes
- 1);
1750 if (fwrite(&fc
, 1, sizeof(fc
), outfile
) != sizeof(fc
))
1752 cleanup("Error writing face chunk!", 1);
1755 return sizeof(struct facechunk
) + 8;
1758 /****************************************************************************************/
1760 /* createrle() based on ModifyIcon source by Dirk Stöcker */
1762 /****************************************************************************************/
1764 static char * createrle(unsigned long depth
, unsigned char *dtype
, LONG
*dsize
, unsigned long size
,
1768 unsigned long bitbuf
, numbits
;
1770 long ressize
, numcopy
, numequal
;
1772 buf
= malloc(size
* 2);
1773 if (!buf
) return NULL
;
1780 k
= 0; /* the really output pointer */
1781 for(i
= 1; numequal
|| numcopy
;)
1783 if(i
< size
&& numequal
&& (src
[i
-1] == src
[i
]))
1787 else if(i
< size
&& numequal
*depth
<= 16)
1789 numcopy
+= numequal
; numequal
= 1; ++i
;
1793 /* care for end case, where it maybe better to join the two */
1794 if(i
== size
&& numcopy
+ numequal
<= 128 && (numequal
-1)*depth
<= 8)
1796 numcopy
+= numequal
; numequal
= 0;
1800 if((j
= numcopy
) > 128) j
= 128;
1801 bitbuf
= (bitbuf
<<8) | (j
-1);
1806 if((j
= numequal
) > 128) j
= 128;
1807 bitbuf
= (bitbuf
<<8) | (256-(j
-1));
1812 buf
[ressize
++] = (bitbuf
>> numbits
);
1816 bitbuf
= (bitbuf
<<depth
) | src
[k
++];
1820 buf
[ressize
++] = (bitbuf
>> numbits
);
1823 if(i
< size
&& !numcopy
&& !numequal
)
1830 buf
[ressize
++] = bitbuf
<< (8-numbits
);
1832 if(ressize
> size
) /* no RLE */
1836 for(i
= 0; i
< size
; ++i
)
1847 /****************************************************************************************/
1849 static LONG
writeimagchunk(struct ILBMImage
*img
)
1851 struct imagchunk ic
;
1853 UBYTE skippalette
= 0;
1855 LONG palsize
, gfxsize
;
1856 UBYTE palpacked
, gfxpacked
;
1858 imagsize
= sizeof(struct imagchunk
);
1860 /* if this is second image check whether palette is identical to
1861 the one of first image */
1865 if (img1
.cmapentries
== img2
.cmapentries
)
1869 for (i
= 0; i
< img1
.cmapentries
; i
++)
1871 if (img1
.rgb
[i
][0] != img2
.rgb
[i
][0]) break;
1872 if (img1
.rgb
[i
][1] != img2
.rgb
[i
][1]) break;
1873 if (img1
.rgb
[i
][2] != img2
.rgb
[i
][2]) break;
1876 if (i
== img1
.cmapentries
) skippalette
= 1;
1885 img
->cmapentries
* 3,
1886 (unsigned char *)img
->rgb
);
1888 imagsize
+= palsize
;
1891 gfx
= createrle(img
->bmh
.bmh_Depth
,
1894 img
->bmh
.bmh_Width
* img
->bmh
.bmh_Height
,
1897 imagsize
+= gfxsize
;
1900 #define ACT_STRUCT ic
1902 SET_BYTE(ic_transparentcolour
, transparentoption
);
1905 SET_BYTE(ic_numcolours
, 0);
1906 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 1 : 0); /* 1 = HasTransparentColour */
1907 SET_BYTE(ic_paletteformat
, 0);
1908 SET_WORD(ic_numpalettebytes
, 0);
1912 SET_BYTE(ic_numcolours
, img
->cmapentries
- 1);
1913 SET_BYTE(ic_flags
, (transparentoption
!= -1) ? 3 : 2); /* 2 = HasPalette */
1914 SET_BYTE(ic_paletteformat
, palpacked
);
1915 SET_WORD(ic_numpalettebytes
, palsize
- 1);
1918 SET_BYTE(ic_imageformat
, gfxpacked
);
1919 SET_BYTE(ic_depth
, img
->bmh
.bmh_Depth
);
1920 SET_WORD(ic_numimagebytes
, gfxsize
- 1);
1923 writelong(imagsize
);
1925 if (fwrite(&ic
, 1, sizeof(ic
), outfile
) != sizeof(ic
))
1927 cleanup("Error writing imag chunk!", 1);
1930 if (fwrite(gfx
, 1, gfxsize
, outfile
) != gfxsize
)
1932 cleanup("Error write gfx data in imag chunk!", 1);
1937 if (fwrite(pal
, 1, palsize
, outfile
) != palsize
)
1939 cleanup("Error write palette data in imag chunk!", 1);
1947 if (fwrite(&dummy
, 1, 1, outfile
) != 1)
1949 cleanup("Error writing imag chunk!", 1);
1955 return imagsize
+ 8;
1958 /****************************************************************************************/
1959 static LONG
writeargb(APTR argb
, ULONG argb_size
)
1963 struct ARGB35_Header
{
1964 ULONG ztype
; /* Always 1 */
1965 ULONG zsize
; /* Compressed size, or -1 */
1966 UWORD resv
; /* Always 0 */
1973 zsize
= size
= argb_size
;
1975 zdest
= malloc(zsize
);
1979 err
= compress(zdest
, &zsize
, argb
, size
);
1985 D(printf("ARGB: Compressed %d => %d\n", size
, zsize
));
1988 formsize
= 10 + zsize
;
1989 writelong(formsize
);
1993 fwrite(zdest
, 1, zsize
, outfile
);
1996 fwrite(&c
, 1, 1, outfile
);
2003 return 8 + formsize
;
2006 /****************************************************************************************/
2008 static void write35data(void)
2017 formsizeseek
= ftell(outfile
);
2018 writelong(0x12345678);
2021 formsize
+= writefacechunk();
2022 formsize
+= writeimagchunk(&img1
);
2023 if (image2option
) formsize
+= writeimagchunk(&img2
);
2025 if (!nosaveARGB
&& img1
.argb
) {
2026 formsize
+= writeargb(img1
.argb
, img1
.argb_size
);
2029 if (!nosaveARGB
&& img2
.argb
) {
2030 formsize
+= writeargb(img2
.argb
, img2
.argb_size
);
2033 if (!nosavePNG
&& img1
.png
) {
2035 writelong(img1
.png_size
);
2036 fwrite(img1
.png
, 1, img1
.png_size
, outfile
);
2037 if (img1
.png_size
& 1) {
2039 fwrite(&c
, 1, 1, outfile
);
2042 formsize
+= 8 + img1
.png_size
;
2045 if (!nosavePNG
&& img2
.png
) {
2047 writelong(img2
.png_size
);
2048 fwrite(img2
.png
, 1, img2
.png_size
, outfile
);
2049 if (img2
.png_size
& 1) {
2051 fwrite(&c
, 1, 1, outfile
);
2054 formsize
+= 8 + img2
.png_size
;
2057 fseek(outfile
, formsizeseek
, SEEK_SET
);
2058 writelong(formsize
);
2061 /****************************************************************************************/
2063 static void writeicon(void)
2066 struct diskobject dobj
;
2069 D(printf("Writing %s\n", outfilename
));
2070 outfile
= fopen(outfilename
, "wb");
2071 if (!outfile
) cleanup("Can't open output file for writing!", 1);
2074 writeolddrawerdata();
2077 if (image2option
) writeimage(&img2
);
2079 if (defaulttooloption
) writestring(defaulttooloption
);
2081 if (tooltypesoption
)
2084 LONG numtooltypes
= 0;
2086 for(strarray
= tooltypesoption
; *strarray
; strarray
++, numtooltypes
++);
2088 writelong((numtooltypes
+ 1) * 4);
2090 for(strarray
= tooltypesoption
; *strarray
; strarray
++)
2092 writestring(*strarray
);
2097 /* toolwindow would have to be saved in between here if there is any */
2099 writenewdrawerdata();
2105 /****************************************************************************************/
2107 static void remapicon(void)
2109 remapplanar(&img1
, &std4colpal
);
2110 if (image2option
) remapplanar(&img2
, &std4colpal
);
2113 /****************************************************************************************/
2115 int main(int argc
, char **argv
)
2117 getarguments(argc
, argv
);
2119 loadimage(image1option
, &img1
);
2121 loadimage(image2option
, &img2
);
2122 if ((img2
.bmh
.bmh_Width
&& img2
.bmh
.bmh_Width
!= img1
.bmh
.bmh_Width
) ||
2123 (img2
.bmh
.bmh_Height
&& img2
.bmh
.bmh_Height
!= img1
.bmh
.bmh_Height
)) {
2124 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
);
2136 /****************************************************************************************/