From 69daa9fd96668123b751de83df864531a092b0f2 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 31 Jul 2015 12:58:58 +0200 Subject: [PATCH] jpg/ico: support for embedded png icons --- sys/src/cmd/jpg/ico.c | 63 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/sys/src/cmd/jpg/ico.c b/sys/src/cmd/jpg/ico.c index 87f0bebe4..0f2411961 100644 --- a/sys/src/cmd/jpg/ico.c +++ b/sys/src/cmd/jpg/ico.c @@ -6,6 +6,8 @@ #include #include +#include "imagefile.h" + typedef struct Icon Icon; struct Icon { @@ -204,27 +206,63 @@ Bgeticon(Biobuf *b, Icon *icon) uchar *buf; uchar *map2map; Memimage *img; + uchar magic[4]; int ncolor; long chan; - if(icon->len < 40){ - werrstr("bad icon header length"); - return -1; - } Bseek(b, icon->offset, 0); - buf = malloc(icon->len); - if(buf == nil) - return -1; - if(Bread(b, buf, icon->len) != icon->len){ + if(Bread(b, magic, 4) != 4){ werrstr("unexpected EOF"); return -1; } - /* this header's info takes precedence over previous one */ - if(getl(buf) != 40){ - werrstr("bad icon header"); + if(magic[0] == 137 && memcmp(magic+1, "PNG", 3) == 0){ + Rawimage **png; + + Bseek(b, -4, 1); + png = Breadpng(b, CRGB); + if(png == nil || png[0] == nil) + return -1; + switch(png[0]->chandesc){ + case CY: + chan = GREY8; + break; + case CYA16: + chan = CHAN2(CGrey, 8, CAlpha, 8); + break; + case CRGB24: + chan = RGB24; + break; + case CRGBA32: + chan = RGBA32; + break; + default: + werrstr("bad icon png channel descriptor"); + return -1; + } + icon->mask = nil; + icon->img = allocmemimage(png[0]->r, chan); + loadmemimage(icon->img, icon->img->r, png[0]->chans[0], png[0]->chanlen); + return 0; + } + + if(getl(magic) != 40){ + werrstr("bad icon bmp header"); + return -1; + } + if(icon->len < 40){ + werrstr("bad icon bmp header length"); + return -1; + } + buf = malloc(icon->len); + if(buf == nil) + return -1; + memmove(buf, magic, 4); + if(Bread(b, buf+4, icon->len-4) != icon->len-4){ + werrstr("unexpected EOF"); return -1; } + /* this header's info takes precedence over previous one */ ncolor = 0; icon->w = getl(buf+4); icon->h = getl(buf+8)>>1; @@ -391,6 +429,9 @@ domask(Icon *icon) char file[64]; int fd; + if(icon->mask == nil) + return; + rv = -1; snprint(file, sizeof(file), "%dx%d.mask", icon->w, icon->h); fd = create(file, OWRITE, 0664);