ico: support > 8bit color icons
This commit is contained in:
parent
c785315d64
commit
05be074413
1 changed files with 52 additions and 23 deletions
|
@ -73,11 +73,9 @@ Bgetheader(Biobuf *b, Header *h)
|
||||||
sysfatal("malloc: %r");
|
sysfatal("malloc: %r");
|
||||||
if(Breadn(b, buf, 16) != 16)
|
if(Breadn(b, buf, 16) != 16)
|
||||||
goto eof;
|
goto eof;
|
||||||
icon->w = buf[0];
|
icon->w = buf[0] == 0 ? 256 : buf[0];
|
||||||
icon->h = buf[1];
|
icon->h = buf[1] == 0 ? 256 : buf[1];
|
||||||
icon->ncolor = buf[2] == 0 ? 256 : buf[2];
|
icon->ncolor = buf[2] == 0 ? 256 : buf[2];
|
||||||
if(buf[3] != 0)
|
|
||||||
goto header;
|
|
||||||
icon->nplane = gets(&buf[4]);
|
icon->nplane = gets(&buf[4]);
|
||||||
icon->bits = gets(&buf[6]);
|
icon->bits = gets(&buf[6]);
|
||||||
icon->len = getl(&buf[8]);
|
icon->len = getl(&buf[8]);
|
||||||
|
@ -99,13 +97,13 @@ header:
|
||||||
}
|
}
|
||||||
|
|
||||||
uchar*
|
uchar*
|
||||||
transcmap(Icon *icon, uchar *map)
|
transcmap(Icon *icon, int ncolor, uchar *map)
|
||||||
{
|
{
|
||||||
uchar *m, *p;
|
uchar *m, *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = m = malloc(sizeof(int)*(1<<icon->bits));
|
p = m = mallocz(sizeof(int)*(1<<icon->bits), 1);
|
||||||
for(i = 0; i < icon->ncolor; i++){
|
for(i = 0; i < ncolor; i++){
|
||||||
*p++ = rgb2cmap(map[2], map[1], map[0]);
|
*p++ = rgb2cmap(map[2], map[1], map[0]);
|
||||||
map += 4;
|
map += 4;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +111,7 @@ transcmap(Icon *icon, uchar *map)
|
||||||
}
|
}
|
||||||
|
|
||||||
Memimage*
|
Memimage*
|
||||||
xor2img(Icon *icon, uchar *xor, uchar *map)
|
xor2img(Icon *icon, long chan, uchar *xor, uchar *map)
|
||||||
{
|
{
|
||||||
uchar *data;
|
uchar *data;
|
||||||
Memimage *img;
|
Memimage *img;
|
||||||
|
@ -123,8 +121,18 @@ xor2img(Icon *icon, uchar *xor, uchar *map)
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
inxlen = 4*((icon->bits*icon->w+31)/32);
|
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 */
|
/* rotate around the y axis, go to 8 bits, and convert color */
|
||||||
mask = (1<<icon->bits)-1;
|
mask = (1<<icon->bits)-1;
|
||||||
for(y = 0; y < icon->h; y++){
|
for(y = 0; y < icon->h; y++){
|
||||||
|
@ -140,11 +148,8 @@ xor2img(Icon *icon, uchar *xor, uchar *map)
|
||||||
s -= icon->bits;
|
s -= icon->bits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stick in an image */
|
/* 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);
|
loadmemimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +187,6 @@ and2img(Icon *icon, uchar *and)
|
||||||
int
|
int
|
||||||
Bgeticon(Biobuf *b, Icon *icon)
|
Bgeticon(Biobuf *b, Icon *icon)
|
||||||
{
|
{
|
||||||
ulong l;
|
|
||||||
uchar *end;
|
uchar *end;
|
||||||
uchar *xor;
|
uchar *xor;
|
||||||
uchar *and;
|
uchar *and;
|
||||||
|
@ -190,6 +194,8 @@ Bgeticon(Biobuf *b, Icon *icon)
|
||||||
uchar *buf;
|
uchar *buf;
|
||||||
uchar *map2map;
|
uchar *map2map;
|
||||||
Memimage *img;
|
Memimage *img;
|
||||||
|
int ncolor;
|
||||||
|
long chan;
|
||||||
|
|
||||||
if(icon->len < 40){
|
if(icon->len < 40){
|
||||||
werrstr("bad icon header length");
|
werrstr("bad icon header length");
|
||||||
|
@ -208,9 +214,10 @@ Bgeticon(Biobuf *b, Icon *icon)
|
||||||
werrstr("bad icon header");
|
werrstr("bad icon header");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ncolor = 0;
|
||||||
icon->w = getl(buf+4);
|
icon->w = getl(buf+4);
|
||||||
l = getl(buf+8);
|
icon->h = getl(buf+8)>>1;
|
||||||
icon->h = l>>1;
|
|
||||||
icon->nplane = gets(buf+12);
|
icon->nplane = gets(buf+12);
|
||||||
icon->bits = gets(buf+14);
|
icon->bits = gets(buf+14);
|
||||||
|
|
||||||
|
@ -220,6 +227,20 @@ Bgeticon(Biobuf *b, Icon *icon)
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
werrstr("don't support %d bit pixels", icon->bits);
|
werrstr("don't support %d bit pixels", icon->bits);
|
||||||
|
@ -230,21 +251,29 @@ Bgeticon(Biobuf *b, Icon *icon)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cm = buf + 40;
|
xor = cm = buf + 40;
|
||||||
xor = cm + 4*icon->ncolor;
|
if(chan == CMAP8)
|
||||||
and = xor + icon->h*4*((icon->bits*icon->w+31)/32);
|
xor += 4*ncolor;
|
||||||
end = and + icon->h*4*((icon->w+31)/32);
|
end = xor + icon->h*4*((icon->bits*icon->w+31)/32);
|
||||||
if(end < buf || end > buf+icon->len){
|
if(end < buf || end > buf+icon->len){
|
||||||
werrstr("bad icon length %lux != %lux", end - buf, icon->len);
|
werrstr("bad icon length %lux != %lux", end - buf, icon->len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* translate the color map to a plan 9 one */
|
/* 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 */
|
/* convert the images */
|
||||||
icon->img = xor2img(icon, xor, map2map);
|
icon->img = xor2img(icon, chan, xor, map2map);
|
||||||
icon->mask = and2img(icon, and);
|
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 */
|
/* so that we save an image with a white background */
|
||||||
if(img = allocmemimage(icon->img->r, icon->img->chan)){
|
if(img = allocmemimage(icon->img->r, icon->img->chan)){
|
||||||
|
@ -426,7 +455,7 @@ screenimage(Memimage *m)
|
||||||
r = m->r;
|
r = m->r;
|
||||||
while(r.min.y < m->r.max.y){
|
while(r.min.y < m->r.max.y){
|
||||||
r.max.y = r.min.y+1;
|
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++;
|
r.min.y++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue