1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Allegro bitmap -> Windows icon converter.
12 *
13 * By Elias Pschernig.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #define ALLEGRO_USE_CONSOLE
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <allegro.h>
25
26
27 #define ICON_MAX 16
28
29
30
31 /* save_ico:
32 * Saves <num> bitmaps as an .ico, using <pal> as palette for 8-bit bitmaps.
33 * Other color depths are saved as 24-bit.
34 */
save_ico(AL_CONST char * filename,BITMAP * bmp[],int num,PALETTE pal[])35 int save_ico(AL_CONST char *filename, BITMAP *bmp[], int num, PALETTE pal[])
36 {
37 PACKFILE *f;
38 int depth, bpp, bw, bitsw;
39 int size, offset, n, i;
40 int c, x, y, b, m, v;
41
42 errno = 0;
43
44 f = pack_fopen(filename, F_WRITE);
45 if (!f)
46 return errno;
47
48 offset = 6 + num * 16; /* ICONDIR + ICONDIRENTRYs */
49
50 /* ICONDIR */
51 pack_iputw(0, f); /* reserved */
52 pack_iputw(1, f); /* resource type: ICON */
53 pack_iputw(num, f); /* number of icons */
54
55 for(n = 0; n < num; n++) {
56 depth = bitmap_color_depth(bmp[n]);
57 bpp = (depth == 8) ? 8 : 24;
58 bw = (((bmp[n]->w * bpp / 8) + 3) / 4) * 4;
59 bitsw = ((((bmp[n]->w + 7) / 8) + 3) / 4) * 4;
60 size = bmp[n]->h * (bw + bitsw) + 40;
61
62 if (bpp == 8)
63 size += 256 * 4;
64
65 /* ICONDIRENTRY */
66 pack_putc(bmp[n]->w, f); /* width */
67 pack_putc(bmp[n]->h, f); /* height */
68 pack_putc(0, f); /* color count */
69 pack_putc(0, f); /* reserved */
70 pack_iputw(1, f); /* color planes */
71 pack_iputw(bpp, f); /* bits per pixel */
72 pack_iputl(size, f); /* size in bytes of image data */
73 pack_iputl(offset, f); /* file offset to image data */
74
75 offset += size;
76 }
77
78 for(n = 0; n < num; n++) {
79 depth = bitmap_color_depth(bmp[n]);
80 bpp = (depth == 8) ? 8 : 24;
81 bw = (((bmp[n]->w * bpp / 8) + 3) / 4) * 4;
82 bitsw = ((((bmp[n]->w + 7) / 8) + 3) / 4) * 4;
83 size = bmp[n]->h * (bw + bitsw) + 40;
84
85 if (bpp == 8)
86 size += 256 * 4;
87
88 /* BITMAPINFOHEADER */
89 pack_iputl(40, f); /* size */
90 pack_iputl(bmp[n]->w, f); /* width */
91 pack_iputl(bmp[n]->h * 2, f); /* height x 2 */
92 pack_iputw(1, f); /* planes */
93 pack_iputw(bpp, f); /* bitcount */
94 pack_iputl(0, f); /* unused for ico */
95 pack_iputl(size, f); /* size */
96 pack_iputl(0, f); /* unused for ico */
97 pack_iputl(0, f); /* unused for ico */
98 pack_iputl(0, f); /* unused for ico */
99 pack_iputl(0, f); /* unused for ico */
100
101 /* PALETTE */
102 if (bpp == 8) {
103 pack_iputl(0, f); /* color 0 is black, so the XOR mask works */
104
105 for (i = 1; i<256; i++) {
106 if (pal[n]) {
107 pack_putc(_rgb_scale_6[pal[n][i].b], f);
108 pack_putc(_rgb_scale_6[pal[n][i].g], f);
109 pack_putc(_rgb_scale_6[pal[n][i].r], f);
110 pack_putc(0, f);
111 }
112 else {
113 pack_iputl(0, f);
114 }
115 }
116 }
117
118 /* XOR MASK */
119 for (y = bmp[n]->h - 1; y >= 0; y--) {
120 for (x = 0; x < bmp[n]->w; x++) {
121 if (bpp == 8) {
122 pack_putc(getpixel(bmp[n], x, y), f);
123 }
124 else {
125 c = getpixel(bmp[n], x, y);
126 pack_putc(getb_depth(depth, c), f);
127 pack_putc(getg_depth(depth, c), f);
128 pack_putc(getr_depth(depth, c), f);
129 }
130 }
131
132 /* every scanline must be 32-bit aligned */
133 while (x&3) {
134 pack_putc(0, f);
135 x++;
136 }
137 }
138
139 /* AND MASK */
140 for (y = bmp[n]->h - 1; y >= 0; y--) {
141 for (x = 0; x < (bmp[n]->w + 7)/8; x++) {
142 m = 0;
143 v = 128;
144
145 for (b = 0; b < 8; b++) {
146 c = getpixel(bmp[n], x * 8 + b, y);
147 if (c == bitmap_mask_color(bmp[n]))
148 m += v;
149 v /= 2;
150 }
151
152 pack_putc(m, f);
153 }
154
155 /* every scanline must be 32-bit aligned */
156 while (x&3) {
157 pack_putc(0, f);
158 x++;
159 }
160 }
161 }
162
163 pack_fclose(f);
164
165 return errno;
166 }
167
168
169
usage(void)170 void usage(void)
171 {
172 printf("\nWindows icon converter for Allegro " ALLEGRO_VERSION_STR "\n");
173 printf("By Elias Pschernig, " ALLEGRO_DATE_STR "\n\n");
174 printf("Usage: wfixicon icon [-r[o]] bitmap [bitmap...]\n");
175 printf(" or\n");
176 printf(" wfixicon icon [-r[o]] -d datafile object [palette] [object...]\n");
177 printf(" where each 'object' is a bitmap or a RLE sprite.\n");
178 printf("Options:\n");
179 printf(" -r output .rc file for the icon\n");
180 printf(" -ro call the resource compiler on the .rc file\n");
181
182 exit(1);
183 }
184
185
186
main(int argc,char * argv[])187 int main(int argc, char *argv[])
188 {
189 char dat_name[128], rc_name[128], res_name[128], str[256];
190 int icon_num = 0, pal_start = 0;
191 int create_rc = FALSE, call_windres = FALSE;
192 int i, j, arg;
193 BITMAP *bmp[ICON_MAX];
194 PALETTE pal[ICON_MAX];
195 RLE_SPRITE *sprite;
196 DATAFILE *dat;
197 PACKFILE *f;
198
199 if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0)
200 exit(EXIT_FAILURE);
201 set_color_conversion(COLORCONV_NONE);
202
203 if (argc < 3)
204 usage();
205
206 dat_name[0] = '\0';
207
208 for (arg = 2; arg < argc; arg++) {
209
210 if (argv[arg][0] == '-') {
211
212 switch(argv[arg][1]) {
213
214 case 'd': /* datafile argument */
215 if (argc < arg+2)
216 usage();
217
218 strcpy(dat_name, argv[++arg]);
219 pal_start = icon_num;
220 break;
221
222 case 'r':
223 create_rc = TRUE;
224
225 if (argv[arg][2] == 'o') {
226 call_windres = TRUE;
227 }
228 break;
229
230 default:
231 usage();
232 }
233 } /* end of '-' handling */
234 else {
235 if (dat_name[0]) {
236 dat = load_datafile_object(dat_name, argv[arg]);
237
238 if (!dat) {
239 printf("Error reading %s from %s.\n", argv[arg], dat_name);
240 exit(EXIT_FAILURE);
241 }
242
243 switch (dat->type) {
244
245 case DAT_BITMAP:
246 bmp[icon_num] = (BITMAP *)dat->dat;
247 icon_num++;
248 break;
249
250 case DAT_RLE_SPRITE:
251 sprite = (RLE_SPRITE *)dat->dat;
252 bmp[icon_num] = create_bitmap_ex(sprite->color_depth, sprite->w, sprite->h);
253 clear_to_color(bmp[icon_num], bitmap_mask_color(bmp[icon_num]));
254 draw_rle_sprite(bmp[icon_num], sprite, 0, 0);
255 icon_num++;
256 break;
257
258 case DAT_PALETTE:
259 if (pal_start == icon_num)
260 usage();
261
262 for (j = pal_start; j < icon_num; j++)
263 for (i = 0; i < PAL_SIZE; i++)
264 pal[j][i] = ((RGB *)dat->dat)[i];
265
266 pal_start = icon_num;
267 break;
268
269 default:
270 usage();
271 }
272 }
273 else {
274 bmp[icon_num] = load_bitmap(argv[arg], pal[icon_num]);
275 if (!bmp[icon_num]) {
276 printf("Error reading %s.\n", argv[arg]);
277 exit(EXIT_FAILURE);
278 }
279
280 icon_num++;
281 }
282
283 if (icon_num == ICON_MAX)
284 break;
285 } /* end of normal argument handling */
286 }
287
288 if (icon_num == 0)
289 usage();
290
291 /* do the hard work */
292 if (save_ico(argv[1], bmp, icon_num, pal) != 0) {
293 printf("Error writing %s.\n", argv[1]);
294 exit(EXIT_FAILURE);
295 }
296
297 /* output a .rc file along with the ico, to be processed by the resource compiler */
298 if (create_rc) {
299 replace_extension(rc_name, argv[1], "rc", sizeof(rc_name));
300
301 f = pack_fopen(rc_name, F_WRITE);
302
303 sprintf(str, "allegro_icon ICON %s\n", argv[1]);
304 pack_fwrite(str, strlen(str), f);
305
306 pack_fclose(f);
307
308 if (call_windres) {
309 replace_extension(res_name, argv[1], "res", sizeof(res_name));
310
311 #if defined ALLEGRO_MINGW32
312 sprintf(str, "windres -O coff -o %s -i %s", res_name, rc_name);
313 #elif defined ALLEGRO_MSVC
314 sprintf(str, "rc -fo %s %s", res_name, rc_name);
315 #elif defined ALLEGRO_BCC32
316 sprintf(str, "brc32 -r -fo %s %s", res_name, rc_name);
317 #endif
318
319 system(str);
320 delete_file(argv[1]);
321 delete_file(rc_name);
322 }
323 }
324
325 return 0;
326 }
327