summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-04-01 04:57:11 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-04-01 04:57:11 +0200
commit0989c2530d03de81c7d340e2f173786590ae967b (patch)
tree8a195b4e59670a76ccb3f2a885130708c420c65e /sys
parentff7d9ab52561605053e69dfa3d7e842318444c03 (diff)
microsoft ico format conversion support
Diffstat (limited to 'sys')
-rw-r--r--sys/man/1/jpg12
-rw-r--r--sys/src/cmd/jpg/ico.c117
-rw-r--r--sys/src/cmd/mothra/getpix.c1
-rw-r--r--sys/src/cmd/mothra/mothra.h1
-rw-r--r--sys/src/cmd/mothra/snoop.c1
-rw-r--r--sys/src/cmd/page.c6
6 files changed, 93 insertions, 45 deletions
diff --git a/sys/man/1/jpg b/sys/man/1/jpg
index 6bbb15ebd..98557cbac 100644
--- a/sys/man/1/jpg
+++ b/sys/man/1/jpg
@@ -98,6 +98,8 @@ jpg, gif, png, ppm, bmp, v210, yuv, ico, tga, togif, toppm, topng, toico \- view
.PP
.B ico
[
+.B -c
+] [
.I file
]
.br
@@ -232,12 +234,18 @@ translates files that contain a `transparency' index by attaching
an alpha channel to the converted image.
.PP
.I Ico
-displays a Windows icon (.ico) file. If no file is
+displays or converts a Windows icon (.ico) file. If no file is
specified,
.I ico
reads from standard input.
Icon files
-contain sets of icons represented by an image and a mask.
+contain sets of icons represented by an image and a mask. The
+.B -c
+option causes
+.I ico
+to convert the first icon in the set and write it to standard
+output in compressed Plan 9 image format. Otherwise, the whole
+icon set is displayed.
Clicking the right button pops up a menu that lets you
write any icon's image as a Plan 9 image (\fIwidth\fBx\fIheight\fB.image\fR),
write any icon's mask as a Plan 9 image (\fIwidth\fBx\fIheight\fB.mask\fR),
diff --git a/sys/src/cmd/jpg/ico.c b/sys/src/cmd/jpg/ico.c
index e9a22633f..27133a777 100644
--- a/sys/src/cmd/jpg/ico.c
+++ b/sys/src/cmd/jpg/ico.c
@@ -2,6 +2,7 @@
#include <libc.h>
#include <bio.h>
#include <draw.h>
+#include <memdraw.h>
#include <event.h>
#include <cursor.h>
@@ -18,8 +19,8 @@ struct Icon
ulong len; /* length of data */
ulong offset; /* file offset to data */
- Image *img;
- Image *mask;
+ Memimage *img;
+ Memimage *mask;
Rectangle r; /* relative */
Rectangle sr; /* abs */
@@ -34,6 +35,7 @@ struct Header
};
int debug;
+int cflag;
Mouse mouse;
Header h;
Image *background;
@@ -53,9 +55,9 @@ getl(uchar *p)
int
Bgetheader(Biobuf *b, Header *h)
{
+ uchar buf[40];
Icon *icon;
int i;
- uchar buf[40];
memset(h, 0, sizeof(*h));
if(Breadn(b, buf, 6) != 6)
@@ -65,7 +67,6 @@ Bgetheader(Biobuf *b, Header *h)
if(gets(&buf[2]) != 1)
goto header;
h->n = gets(&buf[4]);
-
for(i = 0; i < h->n; i++){
icon = mallocz(sizeof(*icon), 1);
if(icon == nil)
@@ -81,7 +82,6 @@ Bgetheader(Biobuf *b, Header *h)
icon->bits = gets(&buf[6]);
icon->len = getl(&buf[8]);
icon->offset = getl(&buf[12]);
-
if(i == 0)
h->first = icon;
else
@@ -112,11 +112,11 @@ transcmap(Icon *icon, uchar *map)
return m;
}
-Image*
+Memimage*
xor2img(Icon *icon, uchar *xor, uchar *map)
{
uchar *data;
- Image *img;
+ Memimage *img;
int inxlen;
uchar *from, *to;
int s, byte, mask;
@@ -142,18 +142,18 @@ xor2img(Icon *icon, uchar *xor, uchar *map)
}
/* stick in an image */
- img = allocimage(display, Rect(0,0,icon->w,icon->h), CMAP8, 0, DNofill);
- loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);
+ 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;
}
-Image*
+Memimage*
and2img(Icon *icon, uchar *and)
{
uchar *data;
- Image *img;
+ Memimage *img;
int inxlen;
int outxlen;
uchar *from, *to;
@@ -172,8 +172,8 @@ and2img(Icon *icon, uchar *and)
}
/* stick in an image */
- img = allocimage(display, Rect(0,0,icon->w,icon->h), GREY1, 0, DNofill);
- loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*outxlen);
+ img = allocmemimage(Rect(0,0,icon->w,icon->h), GREY1);
+ loadmemimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*outxlen);
free(data);
return img;
@@ -183,14 +183,18 @@ int
Bgeticon(Biobuf *b, Icon *icon)
{
ulong l;
- ushort s;
+ uchar *end;
uchar *xor;
uchar *and;
uchar *cm;
uchar *buf;
uchar *map2map;
- Image *img;
+ Memimage *img;
+ if(icon->len < 40){
+ werrstr("bad icon header length");
+ return -1;
+ }
Bseek(b, icon->offset, 0);
buf = malloc(icon->len);
if(buf == nil)
@@ -199,24 +203,16 @@ Bgeticon(Biobuf *b, Icon *icon)
werrstr("unexpected EOF");
return -1;
}
-
/* this header's info takes precedence over previous one */
if(getl(buf) != 40){
werrstr("bad icon header");
return -1;
}
- l = getl(buf+4);
- if(l != icon->w)
- icon->w = l;
+ icon->w = getl(buf+4);
l = getl(buf+8);
- if(l>>1 != icon->h)
- icon->h = l>>1;
- s = gets(buf+12);
- if(s != icon->nplane)
- icon->nplane = s;
- s = gets(buf+14);
- if(s != icon->bits)
- icon->bits = s;
+ icon->h = l>>1;
+ icon->nplane = gets(buf+12);
+ icon->bits = gets(buf+14);
/* limit what we handle */
switch(icon->bits){
@@ -237,6 +233,11 @@ Bgeticon(Biobuf *b, Icon *icon)
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);
+ if(end < buf || end > buf+icon->len){
+ werrstr("bad icon length %lux != %lux", end - buf, icon->len);
+ return -1;
+ }
/* translate the color map to a plan 9 one */
map2map = transcmap(icon, cm);
@@ -246,9 +247,12 @@ Bgeticon(Biobuf *b, Icon *icon)
icon->mask = and2img(icon, and);
/* so that we save an image with a white background */
- img = allocimage(display, icon->img->r, CMAP8, 0, DWhite);
- draw(img, icon->img->r, icon->img, icon->mask, ZP);
- icon->img = img;
+ if(img = allocmemimage(icon->img->r, icon->img->chan)){
+ memfillcolor(img, DWhite);
+ memimagedraw(img, icon->img->r, icon->img, ZP, icon->mask, ZP, SoverD);
+ freememimage(icon->img);
+ icon->img = img;
+ }
free(buf);
free(map2map);
@@ -258,7 +262,7 @@ Bgeticon(Biobuf *b, Icon *icon)
void
usage(void)
{
- fprint(2, "usage: %s [file]\n", argv0);
+ fprint(2, "usage: %s [ -c ] [ file ]\n", argv0);
exits("usage");
}
@@ -328,7 +332,7 @@ doimage(Icon *icon)
snprint(file, sizeof(file), "%dx%d.img", icon->w, icon->h);
fd = create(file, OWRITE, 0664);
if(fd >= 0){
- rv = writeimage(fd, icon->img, 0);
+ rv = writememimage(fd, icon->img);
close(fd);
}
if(rv < 0)
@@ -348,7 +352,7 @@ domask(Icon *icon)
snprint(file, sizeof(file), "%dx%d.mask", icon->w, icon->h);
fd = create(file, OWRITE, 0664);
if(fd >= 0){
- rv = writeimage(fd, icon->mask, 0);
+ rv = writememimage(fd, icon->mask);
close(fd);
}
if(rv < 0)
@@ -412,10 +416,28 @@ enum
BORDER= 1,
};
+Image*
+screenimage(Memimage *m)
+{
+ Rectangle r;
+ Image *i;
+
+ if(i = allocimage(display, m->r, m->chan, 0, DNofill)){
+ 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));
+ r.min.y++;
+ }
+ }
+ return i;
+}
+
void
eresized(int new)
{
Icon *icon;
+ Image *i;
Rectangle r;
if(new && getwindow(display, Refnone) < 0)
@@ -427,7 +449,10 @@ eresized(int new)
r.min.x = r.max.x + BORDER;
r.max.x = r.min.x + Dx(icon->img->r);
r.max.y = r.min.y + Dy(icon->img->r);
- draw(screen, r, icon->img, nil, ZP);
+ if(i = screenimage(icon->img)){
+ draw(screen, r, i, nil, ZP);
+ freeimage(i);
+ }
border(screen, r, -BORDER, display->black, ZP);
icon->sr = r;
}
@@ -447,6 +472,11 @@ main(int argc, char **argv)
case 'd':
debug = 1;
break;
+ case 'c':
+ cflag = 1;
+ break;
+ default:
+ usage();
}ARGEND;
fd = -1;
@@ -464,16 +494,12 @@ main(int argc, char **argv)
break;
}
+ memimageinit();
Binit(&in, fd, OREAD);
if(Bgetheader(&in, &h) < 0)
sysfatal("reading header: %r");
- initdraw(nil, nil, "ico");
- background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, (128<<24)|(128<<16)|(128<<8)|0xFF);
-
- einit(Emouse|Ekeyboard);
-
num = 0;
r.min = Pt(4, 4);
for(icon = h.first; icon != nil; icon = icon->next){
@@ -486,14 +512,21 @@ main(int argc, char **argv)
icon->w, icon->h, icon->ncolor, icon->bits, icon->len, icon->offset);
r.max = addpt(r.min, Pt(icon->w, icon->h));
icon->r = r;
+ if(cflag){
+ writememimage(1, icon->img);
+ exits(0);
+ }
r.min.x += r.max.x;
num++;
}
- if(num == 0)
- exits("no images");
- eresized(0);
+ if(num == 0 || cflag)
+ sysfatal("no images");
+ initdraw(nil, nil, "ico");
+ background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x808080FF);
+ eresized(0);
+ einit(Emouse|Ekeyboard);
for(;;)
switch(event(&e)){
case Ekeyboard:
diff --git a/sys/src/cmd/mothra/getpix.c b/sys/src/cmd/mothra/getpix.c
index d966de53c..7fd58254c 100644
--- a/sys/src/cmd/mothra/getpix.c
+++ b/sys/src/cmd/mothra/getpix.c
@@ -19,6 +19,7 @@ char *pixcmd[]={
[JPEG] "jpg -9t",
[PNG] "png -9t",
[BMP] "bmp -9t",
+[ICO] "ico -c",
};
void getimage(Rtext *t, Www *w){
diff --git a/sys/src/cmd/mothra/mothra.h b/sys/src/cmd/mothra/mothra.h
index 7c1a04bcc..26b24dc63 100644
--- a/sys/src/cmd/mothra/mothra.h
+++ b/sys/src/cmd/mothra/mothra.h
@@ -50,6 +50,7 @@ enum{
JPEG,
PNG,
BMP,
+ ICO,
GUNZIP,
COMPRESS,
diff --git a/sys/src/cmd/mothra/snoop.c b/sys/src/cmd/mothra/snoop.c
index 2ed1dd2c0..0e1a2108a 100644
--- a/sys/src/cmd/mothra/snoop.c
+++ b/sys/src/cmd/mothra/snoop.c
@@ -100,6 +100,7 @@ snooptype(int fd)
"image/gif", GIF,
"image/png", PNG,
"image/bmp", BMP,
+ "image/x-icon", ICO,
"application/x-gzip", GUNZIP,
"application/x-compress", COMPRESS,
diff --git a/sys/src/cmd/page.c b/sys/src/cmd/page.c
index fe85c243b..61e5527ec 100644
--- a/sys/src/cmd/page.c
+++ b/sys/src/cmd/page.c
@@ -290,7 +290,10 @@ popenimg(Page *p)
seek(fd, 0, 0);
if(p->data){
p->ext = p->data;
- snprint(nam, sizeof(nam), "%s -t9", p->ext);
+ if(strcmp(p->ext, "ico") == 0)
+ snprint(nam, sizeof(nam), "%s -c", p->ext);
+ else
+ snprint(nam, sizeof(nam), "%s -t9", p->ext);
pipeline(fd, "%s", nam);
}
@@ -674,6 +677,7 @@ popenfile(Page *p)
"image/png", popenimg, "png",
"image/ppm", popenimg, "ppm",
"image/bmp", popenimg, "bmp",
+ "image/x-icon", popenimg, "ico",
"image/p9bit", popenimg, nil,
};