9 typedef struct Icon Icon;
14 uchar w; /* icon width */
15 uchar h; /* icon height */
16 ushort ncolor; /* number of colors */
17 ushort nplane; /* number of bit planes */
18 ushort bits; /* bits per pixel */
19 ulong len; /* length of data */
20 ulong offset; /* file offset to data */
25 Rectangle r; /* relative */
26 Rectangle sr; /* abs */
29 typedef struct Header Header;
46 return p[0] | (p[1]<<8);
52 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
56 Bgetheader(Biobuf *b, Header *h)
62 memset(h, 0, sizeof(*h));
63 if(Bread(b, buf, 6) != 6)
65 if(gets(&buf[0]) != 0)
67 if(gets(&buf[2]) != 1)
70 for(i = 0; i < h->n; i++){
71 icon = mallocz(sizeof(*icon), 1);
73 sysfatal("malloc: %r");
74 if(Bread(b, buf, 16) != 16)
76 icon->w = buf[0] == 0 ? 256 : buf[0];
77 icon->h = buf[1] == 0 ? 256 : buf[1];
78 icon->ncolor = buf[2] == 0 ? 256 : buf[2];
79 icon->nplane = gets(&buf[4]);
80 icon->bits = gets(&buf[6]);
81 icon->len = getl(&buf[8]);
82 icon->offset = getl(&buf[12]);
92 werrstr("unexpected EOF");
95 werrstr("unknown header format");
100 transcmap(Icon *icon, int ncolor, uchar *map)
105 p = m = mallocz(sizeof(int)*(1<<icon->bits), 1);
107 sysfatal("malloc: %r");
108 for(i = 0; i < ncolor; i++){
109 *p++ = rgb2cmap(map[2], map[1], map[0]);
116 xor2img(Icon *icon, long chan, uchar *xor, uchar *map)
125 inxlen = 4*((icon->bits*icon->w+31)/32);
126 img = allocmemimage(Rect(0,0,icon->w,icon->h), chan);
131 from = xor + icon->h*inxlen;
132 for(y = 0; y < icon->h; y++){
134 loadmemimage(img, Rect(0,y,icon->w,y+1), from, inxlen);
139 to = data = malloc(icon->w*icon->h);
145 /* rotate around the y axis, go to 8 bits, and convert color */
146 mask = (1<<icon->bits)-1;
147 for(y = 0; y < icon->h; y++){
150 from = xor + (icon->h - 1 - y)*inxlen;
151 for(x = 0; x < icon->w; x++){
156 *to++ = map[(byte>>s) & mask];
160 /* stick in an image */
161 loadmemimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);
167 and2img(Icon *icon, uchar *and)
176 inxlen = 4*((icon->w+31)/32);
177 to = data = malloc(inxlen*icon->h);
181 /* rotate around the y axis and invert bits */
182 outxlen = (icon->w+7)/8;
183 for(y = 0; y < icon->h; y++){
184 from = and + (icon->h - 1 - y)*inxlen;
185 for(x = 0; x < outxlen; x++)
189 /* stick in an image */
190 if(img = allocmemimage(Rect(0,0,icon->w,icon->h), GREY1))
191 loadmemimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*outxlen);
198 Bgeticon(Biobuf *b, Icon *icon)
211 werrstr("bad icon header length");
214 Bseek(b, icon->offset, 0);
215 buf = malloc(icon->len);
218 if(Bread(b, buf, icon->len) != icon->len){
219 werrstr("unexpected EOF");
222 /* this header's info takes precedence over previous one */
224 werrstr("bad icon header");
229 icon->w = getl(buf+4);
230 icon->h = getl(buf+8)>>1;
231 icon->nplane = gets(buf+12);
232 icon->bits = gets(buf+14);
234 /* limit what we handle */
240 ncolor = icon->ncolor;
241 if(ncolor > (1<<icon->bits))
242 ncolor = 1<<icon->bits;
256 werrstr("don't support %d bit pixels", icon->bits);
259 if(icon->nplane != 1){
260 werrstr("don't support %d planes", icon->nplane);
267 end = xor + icon->h*4*((icon->bits*icon->w+31)/32);
268 if(end < buf || end > buf+icon->len){
269 werrstr("bad icon length %lux != %lux", end - buf, icon->len);
273 /* translate the color map to a plan 9 one */
276 map2map = transcmap(icon, ncolor, cm);
278 /* convert the images */
279 icon->img = xor2img(icon, chan, xor, map2map);
280 if(icon->img == nil){
281 werrstr("xor2img: %r");
286 /* check for and mask */
288 end += icon->h*4*((icon->w+31)/32);
289 if(end <= buf+icon->len)
290 icon->mask = and2img(icon, and);
292 /* so that we save an image with a white background */
293 if(img = allocmemimage(icon->img->r, icon->img->chan)){
294 memfillcolor(img, DWhite);
295 memimagedraw(img, icon->img->r, icon->img, ZP, icon->mask, ZP, SoverD);
296 freememimage(icon->img);
308 fprint(2, "usage: %s [ -c ] [ file ]\n", argv0);
323 [Mimage] "write image",
324 [Mmask] "write mask",
335 {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
336 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
337 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
338 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,},
339 {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
340 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
341 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
342 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,}
348 while((mouse.buttons==0) != ud)
357 static char obuf[1024];
360 vseprint(buf, buf+sizeof(buf), fmt, arg);
362 string(screen, screen->r.min, background, ZP, font, obuf);
363 string(screen, screen->r.min, display->white, ZP, font, buf);
375 snprint(file, sizeof(file), "%dx%d.img", icon->w, icon->h);
376 fd = create(file, OWRITE, 0664);
378 rv = writememimage(fd, icon->img);
382 mesg("error writing %s: %r", file);
384 mesg("created %s", file);
395 snprint(file, sizeof(file), "%dx%d.mask", icon->w, icon->h);
396 fd = create(file, OWRITE, 0664);
398 rv = writememimage(fd, icon->mask);
402 mesg("error writing %s: %r", file);
404 mesg("created %s", file);
408 apply(void (*f)(Icon*))
414 if(mouse.buttons == 4)
415 for(icon = h.first; icon; icon = icon->next)
416 if(ptinrect(mouse.xy, icon->sr)){
430 sel = emenuhit(3, &mouse, &menu3);
449 for(icon = h.first; icon; icon = icon->next)
450 if(ptinrect(mouse.xy, icon->sr)){
451 mesg("%dx%d", icon->w, icon->h);
463 screenimage(Memimage *m)
468 if(i = allocimage(display, m->r, m->chan, 0, DNofill)){
470 while(r.min.y < m->r.max.y){
472 loadimage(i, r, byteaddr(m, r.min), bytesperline(r, m->depth));
486 if(new && getwindow(display, Refnone) < 0)
487 sysfatal("can't reattach to window");
488 draw(screen, screen->clipr, background, nil, ZP);
489 r.max.x = screen->r.min.x;
490 r.min.y = screen->r.min.y + font->height + 2*BORDER;
491 for(icon = h.first; icon != nil; icon = icon->next){
492 r.min.x = r.max.x + BORDER;
493 r.max.x = r.min.x + Dx(icon->img->r);
494 r.max.y = r.min.y + Dy(icon->img->r);
495 if(i = screenimage(icon->img)){
496 draw(screen, r, i, nil, ZP);
499 border(screen, r, -BORDER, display->black, ZP);
502 flushimage(display, 1);
506 main(int argc, char **argv)
531 fd = open(argv[0], OREAD);
533 sysfatal("opening: %r");
541 Binit(&in, fd, OREAD);
543 if(Bgetheader(&in, &h) < 0)
544 sysfatal("reading header: %r");
548 for(icon = h.first; icon != nil; icon = icon->next){
549 if(Bgeticon(&in, icon) < 0){
550 fprint(2, "%s: read fail: %r\n", argv0);
554 fprint(2, "w %ud h %ud ncolor %ud bits %ud len %lud offset %lud\n",
555 icon->w, icon->h, icon->ncolor, icon->bits, icon->len, icon->offset);
556 r.max = addpt(r.min, Pt(icon->w, icon->h));
559 writememimage(1, icon->img);
566 if(num == 0 || cflag)
567 sysfatal("no images");
569 initdraw(nil, nil, "ico");
570 background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x808080FF);
572 einit(Emouse|Ekeyboard);
579 if(mouse.buttons & 4)