ref: 81652c664317a96fe28dda30cb647b6d8b93094d
parent: 9e6ebfbb5631b47b6b5a6fcb939ecb5c48828937
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Tue Apr 17 13:32:34 EDT 2012
ico: support > 8bit color icons
--- a/sys/src/cmd/jpg/ico.c
+++ b/sys/src/cmd/jpg/ico.c
@@ -73,11 +73,9 @@
sysfatal("malloc: %r");if(Breadn(b, buf, 16) != 16)
goto eof;
- icon->w = buf[0];
- icon->h = buf[1];
+ icon->w = buf[0] == 0 ? 256 : buf[0];
+ icon->h = buf[1] == 0 ? 256 : buf[1];
icon->ncolor = buf[2] == 0 ? 256 : buf[2];
- if(buf[3] != 0)
- goto header;
icon->nplane = gets(&buf[4]);
icon->bits = gets(&buf[6]);
icon->len = getl(&buf[8]);
@@ -99,13 +97,13 @@
}
uchar*
-transcmap(Icon *icon, uchar *map)
+transcmap(Icon *icon, int ncolor, uchar *map)
{uchar *m, *p;
int i;
- p = m = malloc(sizeof(int)*(1<<icon->bits));
- for(i = 0; i < icon->ncolor; i++){+ p = m = mallocz(sizeof(int)*(1<<icon->bits), 1);
+ for(i = 0; i < ncolor; i++){*p++ = rgb2cmap(map[2], map[1], map[0]);
map += 4;
}
@@ -113,7 +111,7 @@
}
Memimage*
-xor2img(Icon *icon, uchar *xor, uchar *map)
+xor2img(Icon *icon, long chan, uchar *xor, uchar *map)
{uchar *data;
Memimage *img;
@@ -123,8 +121,18 @@
int x, y;
inxlen = 4*((icon->bits*icon->w+31)/32);
- to = data = malloc(icon->w*icon->h);
+ img = allocmemimage(Rect(0,0,icon->w,icon->h), chan);
+ if(chan != CMAP8){+ from = xor + icon->h*inxlen;
+ for(y = 0; y < icon->h; y++){+ from -= inxlen;
+ loadmemimage(img, Rect(0,y,icon->w,y+1), from, inxlen);
+ }
+ return img;
+ }
+
+ to = data = malloc(icon->w*icon->h);
/* rotate around the y axis, go to 8 bits, and convert color */
mask = (1<<icon->bits)-1;
for(y = 0; y < icon->h; y++){@@ -140,11 +148,8 @@
s -= icon->bits;
}
}
-
/* stick in an image */
- img = allocmemimage(Rect(0,0,icon->w,icon->h), CMAP8);
loadmemimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);
-
free(data);
return img;
}
@@ -182,7 +187,6 @@
int
Bgeticon(Biobuf *b, Icon *icon)
{- ulong l;
uchar *end;
uchar *xor;
uchar *and;
@@ -190,6 +194,8 @@
uchar *buf;
uchar *map2map;
Memimage *img;
+ int ncolor;
+ long chan;
if(icon->len < 40){ werrstr("bad icon header length");@@ -208,9 +214,10 @@
werrstr("bad icon header");return -1;
}
+
+ ncolor = 0;
icon->w = getl(buf+4);
- l = getl(buf+8);
- icon->h = l>>1;
+ icon->h = getl(buf+8)>>1;
icon->nplane = gets(buf+12);
icon->bits = gets(buf+14);
@@ -220,7 +227,21 @@
case 2:
case 4:
case 8:
+ ncolor = icon->ncolor;
+ if(ncolor > (1<<icon->bits))
+ ncolor = 1<<icon->bits;
+ chan = CMAP8;
break;
+ case 15:
+ case 16:
+ chan = RGB16;
+ break;
+ case 24:
+ chan = RGB24;
+ break;
+ case 32:
+ chan = ARGB32;
+ break;
default:
werrstr("don't support %d bit pixels", icon->bits);return -1;
@@ -230,10 +251,10 @@
return -1;
}
- cm = buf + 40;
- xor = cm + 4*icon->ncolor;
- and = xor + icon->h*4*((icon->bits*icon->w+31)/32);
- end = and + icon->h*4*((icon->w+31)/32);
+ xor = cm = buf + 40;
+ if(chan == CMAP8)
+ xor += 4*ncolor;
+ end = xor + icon->h*4*((icon->bits*icon->w+31)/32);
if(end < buf || end > buf+icon->len){ werrstr("bad icon length %lux != %lux", end - buf, icon->len);return -1;
@@ -240,12 +261,20 @@
}
/* translate the color map to a plan 9 one */
- map2map = transcmap(icon, cm);
+ map2map = nil;
+ if(chan == CMAP8)
+ map2map = transcmap(icon, ncolor, cm);
/* convert the images */
- icon->img = xor2img(icon, xor, map2map);
- icon->mask = and2img(icon, and);
+ icon->img = xor2img(icon, chan, xor, map2map);
+ icon->mask = nil;
+ /* check for and mask */
+ and = end;
+ end += icon->h*4*((icon->w+31)/32);
+ if(end <= buf+icon->len)
+ icon->mask = and2img(icon, and);
+
/* so that we save an image with a white background */
if(img = allocmemimage(icon->img->r, icon->img->chan)){memfillcolor(img, DWhite);
@@ -426,7 +455,7 @@
r = m->r;
while(r.min.y < m->r.max.y){r.max.y = r.min.y+1;
- loadimage(i, r, byteaddr(m, r.min), Dx(r));
+ loadimage(i, r, byteaddr(m, r.min), bytesperline(r, m->depth));
r.min.y++;
}
}
--
⑨