8 typedef struct Icon Icon;
13 uchar w; /* icon width */
14 uchar h; /* icon height */
15 ushort ncolor; /* number of colors */
16 ushort nplane; /* number of bit planes */
17 ushort bits; /* bits per pixel */
18 ulong len; /* length of data */
19 ulong offset; /* file offset to data */
24 Rectangle r; /* relative */
25 Rectangle sr; /* abs */
28 typedef struct Header Header;
44 return p[0] | (p[1]<<8);
50 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
54 Bgetheader(Biobuf *b, Header *h)
60 memset(h, 0, sizeof(*h));
61 if(Bread(b, buf, 6) != 6)
63 if(gets(&buf[0]) != 0)
65 if(gets(&buf[2]) != 1)
69 for(i = 0; i < h->n; i++){
70 icon = mallocz(sizeof(*icon), 1);
72 sysfatal("malloc: %r");
73 if(Bread(b, buf, 16) != 16)
77 icon->ncolor = buf[2] == 0 ? 256 : buf[2];
80 icon->nplane = gets(&buf[4]);
81 icon->bits = gets(&buf[6]);
82 icon->len = getl(&buf[8]);
83 icon->offset = getl(&buf[12]);
94 werrstr("unexpected EOF");
97 werrstr("unknown header format");
102 transcmap(Icon *icon, uchar *map)
107 p = m = malloc(sizeof(int)*(1<<icon->bits));
108 for(i = 0; i < icon->ncolor; i++){
109 *p++ = rgb2cmap(map[2], map[1], map[0]);
116 xor2img(Icon *icon, uchar *xor, uchar *map)
125 inxlen = 4*((icon->bits*icon->w+31)/32);
126 to = data = malloc(icon->w*icon->h);
128 /* rotate around the y axis, go to 8 bits, and convert color */
129 mask = (1<<icon->bits)-1;
130 for(y = 0; y < icon->h; y++){
133 from = xor + (icon->h - 1 - y)*inxlen;
134 for(x = 0; x < icon->w; x++){
139 *to++ = map[(byte>>s) & mask];
144 /* stick in an image */
145 img = allocimage(display, Rect(0,0,icon->w,icon->h), CMAP8, 0, DNofill);
146 loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);
153 and2img(Icon *icon, uchar *and)
162 inxlen = 4*((icon->w+31)/32);
163 to = data = malloc(inxlen*icon->h);
165 /* rotate around the y axis and invert bits */
166 outxlen = (icon->w+7)/8;
167 for(y = 0; y < icon->h; y++){
168 from = and + (icon->h - 1 - y)*inxlen;
169 for(x = 0; x < outxlen; x++){
174 /* stick in an image */
175 img = allocimage(display, Rect(0,0,icon->w,icon->h), GREY1, 0, DNofill);
176 loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*outxlen);
183 Bgeticon(Biobuf *b, Icon *icon)
194 Bseek(b, icon->offset, 0);
195 buf = malloc(icon->len);
198 if(Bread(b, buf, icon->len) != icon->len){
199 werrstr("unexpected EOF");
203 /* this header's info takes precedence over previous one */
205 werrstr("bad icon header");
215 if(s != icon->nplane)
221 /* limit what we handle */
229 werrstr("don't support %d bit pixels", icon->bits);
232 if(icon->nplane != 1){
233 werrstr("don't support %d planes", icon->nplane);
238 xor = cm + 4*icon->ncolor;
239 and = xor + icon->h*4*((icon->bits*icon->w+31)/32);
241 /* translate the color map to a plan 9 one */
242 map2map = transcmap(icon, cm);
244 /* convert the images */
245 icon->img = xor2img(icon, xor, map2map);
246 icon->mask = and2img(icon, and);
248 /* so that we save an image with a white background */
249 img = allocimage(display, icon->img->r, CMAP8, 0, DWhite);
250 draw(img, icon->img->r, icon->img, icon->mask, ZP);
261 fprint(2, "usage: %s [file]\n", argv0);
276 [Mimage] "write image",
277 [Mmask] "write mask",
288 {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
289 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
290 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
291 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,},
292 {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
293 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
294 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
295 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,}
301 while((mouse.buttons==0) != ud)
310 static char obuf[1024];
313 vseprint(buf, buf+sizeof(buf), fmt, arg);
315 string(screen, screen->r.min, background, ZP, font, obuf);
316 string(screen, screen->r.min, display->white, ZP, font, buf);
328 snprint(file, sizeof(file), "%dx%d.img", icon->w, icon->h);
329 fd = create(file, OWRITE, 0664);
331 rv = writeimage(fd, icon->img, 0);
335 mesg("error writing %s: %r", file);
337 mesg("created %s", file);
348 snprint(file, sizeof(file), "%dx%d.mask", icon->w, icon->h);
349 fd = create(file, OWRITE, 0664);
351 rv = writeimage(fd, icon->mask, 0);
355 mesg("error writing %s: %r", file);
357 mesg("created %s", file);
361 apply(void (*f)(Icon*))
367 if(mouse.buttons == 4)
368 for(icon = h.first; icon; icon = icon->next)
369 if(ptinrect(mouse.xy, icon->sr)){
383 sel = emenuhit(3, &mouse, &menu3);
402 for(icon = h.first; icon; icon = icon->next)
403 if(ptinrect(mouse.xy, icon->sr)){
404 mesg("%dx%d", icon->w, icon->h);
421 if(new && getwindow(display, Refnone) < 0)
422 sysfatal("can't reattach to window");
423 draw(screen, screen->clipr, background, nil, ZP);
424 r.max.x = screen->r.min.x;
425 r.min.y = screen->r.min.y + font->height + 2*BORDER;
426 for(icon = h.first; icon != nil; icon = icon->next){
427 r.min.x = r.max.x + BORDER;
428 r.max.x = r.min.x + Dx(icon->img->r);
429 r.max.y = r.min.y + Dy(icon->img->r);
430 draw(screen, r, icon->img, nil, ZP);
431 border(screen, r, -BORDER, display->black, ZP);
434 flushimage(display, 1);
438 main(int argc, char **argv)
458 fd = open(argv[0], OREAD);
460 sysfatal("opening: %r");
467 Binit(&in, fd, OREAD);
469 if(Bgetheader(&in, &h) < 0)
470 sysfatal("reading header: %r");
472 initdraw(nil, nil, "ico");
473 background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, (128<<24)|(128<<16)|(128<<8)|0xFF);
475 einit(Emouse|Ekeyboard);
479 for(icon = h.first; icon != nil; icon = icon->next){
480 if(Bgeticon(&in, icon) < 0){
481 fprint(2, "%s: read fail: %r\n", argv0);
485 fprint(2, "w %ud h %ud ncolor %ud bits %ud len %lud offset %lud\n",
486 icon->w, icon->h, icon->ncolor, icon->bits, icon->len, icon->offset);
487 r.max = addpt(r.min, Pt(icon->w, icon->h));
503 if(mouse.buttons & 4)