13 typedef struct Icon Icon;
19 uchar w; /* icon width */
20 uchar h; /* icon height */
21 ushort ncolor; /* number of colors */
22 ushort nplane; /* number of bit planes */
23 ushort bits; /* bits per pixel */
24 ulong len; /* length of data */
25 ulong offset; /* file offset to data */
26 uchar map[4*256]; /* color map */
36 typedef struct Header Header;
45 Bputs(Biobuf *b, ushort x)
52 Bputl(Biobuf *b, ulong x)
61 void mk8bit(Icon*, int);
62 void mkxorand(Icon*, int);
66 main(int argc, char **argv)
77 /* read in all the images */
78 display = initdisplay(nil, nil, nil);
82 for(i = 0; i < argc; i++)
86 /* create the .ico file */
90 /* offset to first icon */
91 offset = FileHdrLen + h.n*IconDescrLen;
98 /* icon description */
99 for(icon = h.first; icon != nil; icon = icon->next){
102 Bputc(b, icon->ncolor);
104 Bputs(b, icon->nplane);
105 Bputs(b, icon->bits);
106 len = IconHdrLen + icon->ncolor*4 + icon->xorlen + icon->andlen;
113 for(icon = h.first; icon != nil; icon = icon->next){
114 /* icon header (BMP like) */
115 Bputl(b, IconHdrLen);
118 Bputs(b, icon->nplane);
119 Bputs(b, icon->bits);
120 Bputl(b, 0); /* compression info */
128 if(Bwrite(b, icon->map, 4*icon->ncolor) < 0)
129 sysfatal("writing color map: %r");
132 if(Bwrite(b, icon->xor, icon->xorlen) < 0)
133 sysfatal("writing xor bits: %r");
136 if(Bwrite(b, icon->and, icon->andlen) < 0)
137 sysfatal("writing and bits: %r");
150 fd = open(file, OREAD);
152 sysfatal("opening %s: %r", file);
153 icon = emalloc(sizeof(Icon));
154 icon->img = readimage(display, fd, 0);
156 sysfatal("reading image %s: %r", file);
166 icon->h = Dy(icon->img->r);
167 icon->w = Dx(icon->img->r);
168 icon->bits = 1<<icon->img->depth;
171 /* convert to 8 bits per pixel */
172 switch(icon->img->chan){
188 /* create xor/and masks, minimizing bits per pixel */
189 mkxorand(icon, icon->img->chan == GREY8);
199 sysfatal("memory: %r");
203 /* convert to 8 bit */
205 mk8bit(Icon *icon, int grey)
209 img = allocimage(display, icon->img->r, grey ? GREY8 : CMAP8, 0, DNofill);
211 sysfatal("can't allocimage: %r");
212 draw(img, img->r, icon->img, nil, ZP);
213 freeimage(icon->img);
217 /* make xor and and mask */
219 mkxorand(Icon *icon, int grey)
229 uchar andbyte, xorbyte;
233 ndata = icon->h * icon->w;
234 data = emalloc(ndata);
235 if(unloadimage(icon->img, icon->img->r, data, ndata) < 0)
236 sysfatal("can't unload %s: %r", icon->file);
239 /* find colors used */
240 memset(xx, 0, sizeof xx);
241 for(p = data; p < e; p++)
244 /* count the colors and create a mapping from plan 9 */
247 for(i = 0; i < 256; i++){
266 /* get minimum number of pixels per bit (with a color map) */
270 } else if(ncolor <= 4){
273 } else if(ncolor <= 16){
281 icon->ncolor = ncolor;
283 /* the xor mask rows are justified to a 32 bit boundary */
284 /* the and mask is 1 bit grey */
285 xorrl = 4*((bits*icon->w + 31)/32);
286 andrl = 4*((icon->w + 31)/32);
287 icon->xor = emalloc(xorrl * icon->h);
288 icon->and = emalloc(andrl * icon->h);
289 icon->xorlen = xorrl*icon->h;
290 icon->andlen = andrl*icon->h;
292 /* make both masks. they're upside down relative to plan9 ones */
294 for(y = 0; y < icon->h; y++){
298 xto = icon->xor + (icon->h-1-y)*xorrl;
299 ato = icon->and + (icon->h-1-y)*andrl;
300 for(x = 0; x < icon->w; x++){