Why not?
This commit is contained in:
parent
a01e58366c
commit
28994509cc
82 changed files with 13293 additions and 0 deletions
322
src/cmd/jpg/toico.c
Normal file
322
src/cmd/jpg/toico.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <draw.h>
|
||||
|
||||
enum
|
||||
{
|
||||
FileHdrLen= 6,
|
||||
IconDescrLen= 16,
|
||||
IconHdrLen= 40,
|
||||
};
|
||||
|
||||
typedef struct Icon Icon;
|
||||
struct Icon
|
||||
{
|
||||
Icon *next;
|
||||
char *file;
|
||||
|
||||
uchar w; /* icon width */
|
||||
uchar h; /* icon height */
|
||||
ushort ncolor; /* number of colors */
|
||||
ushort nplane; /* number of bit planes */
|
||||
ushort bits; /* bits per pixel */
|
||||
ulong len; /* length of data */
|
||||
ulong offset; /* file offset to data */
|
||||
uchar map[4*256]; /* color map */
|
||||
|
||||
Image *img;
|
||||
|
||||
uchar *xor;
|
||||
int xorlen;
|
||||
uchar *and;
|
||||
int andlen;
|
||||
};
|
||||
|
||||
typedef struct Header Header;
|
||||
struct Header
|
||||
{
|
||||
uint n;
|
||||
Icon *first;
|
||||
Icon *last;
|
||||
};
|
||||
|
||||
void
|
||||
Bputs(Biobuf *b, ushort x)
|
||||
{
|
||||
Bputc(b, x&0xff);
|
||||
Bputc(b, x>>8);
|
||||
}
|
||||
|
||||
void
|
||||
Bputl(Biobuf *b, ulong x)
|
||||
{
|
||||
Bputs(b, x&0xffff);
|
||||
Bputs(b, x>>16);
|
||||
}
|
||||
|
||||
Header h;
|
||||
|
||||
void* emalloc(int);
|
||||
void mk8bit(Icon*, int);
|
||||
void mkxorand(Icon*, int);
|
||||
void readicon(char*);
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
Biobuf *b, out;
|
||||
Icon *icon;
|
||||
ulong offset;
|
||||
ulong len;
|
||||
|
||||
ARGBEGIN{
|
||||
}ARGEND;
|
||||
|
||||
/* read in all the images */
|
||||
initdraw(nil, nil, nil);
|
||||
if(argc < 1){
|
||||
readicon("/fd/0");
|
||||
} else {
|
||||
for(i = 0; i < argc; i++)
|
||||
readicon(argv[i]);
|
||||
}
|
||||
|
||||
/* create the .ico file */
|
||||
b = &out;
|
||||
Binit(b, 1, OWRITE);
|
||||
|
||||
/* offset to first icon */
|
||||
offset = FileHdrLen + h.n*IconDescrLen;
|
||||
|
||||
/* file header is */
|
||||
Bputs(b, 0);
|
||||
Bputs(b, 1);
|
||||
Bputs(b, h.n);
|
||||
|
||||
/* icon description */
|
||||
for(icon = h.first; icon != nil; icon = icon->next){
|
||||
Bputc(b, icon->w);
|
||||
Bputc(b, icon->h);
|
||||
Bputc(b, icon->ncolor);
|
||||
Bputc(b, 0);
|
||||
Bputs(b, icon->nplane);
|
||||
Bputs(b, icon->bits);
|
||||
len = IconHdrLen + icon->ncolor*4 + icon->xorlen + icon->andlen;
|
||||
Bputl(b, len);
|
||||
Bputl(b, offset);
|
||||
offset += len;
|
||||
}
|
||||
|
||||
/* icons */
|
||||
for(icon = h.first; icon != nil; icon = icon->next){
|
||||
/* icon header (BMP like) */
|
||||
Bputl(b, IconHdrLen);
|
||||
Bputl(b, icon->w);
|
||||
Bputl(b, 2*icon->h);
|
||||
Bputs(b, icon->nplane);
|
||||
Bputs(b, icon->bits);
|
||||
Bputl(b, 0); /* compression info */
|
||||
Bputl(b, 0);
|
||||
Bputl(b, 0);
|
||||
Bputl(b, 0);
|
||||
Bputl(b, 0);
|
||||
Bputl(b, 0);
|
||||
|
||||
/* color map */
|
||||
if(Bwrite(b, icon->map, 4*icon->ncolor) < 0)
|
||||
sysfatal("writing color map: %r");
|
||||
|
||||
/* xor bits */
|
||||
if(Bwrite(b, icon->xor, icon->xorlen) < 0)
|
||||
sysfatal("writing xor bits: %r");
|
||||
|
||||
/* and bits */
|
||||
if(Bwrite(b, icon->and, icon->andlen) < 0)
|
||||
sysfatal("writing and bits: %r");
|
||||
}
|
||||
|
||||
Bterm(b);
|
||||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
readicon(char *file)
|
||||
{
|
||||
int fd;
|
||||
Icon *icon;
|
||||
|
||||
fd = open(file, OREAD);
|
||||
if(fd < 0)
|
||||
sysfatal("opening %s: %r", file);
|
||||
icon = emalloc(sizeof(Icon));
|
||||
icon->img = readimage(display, fd, 0);
|
||||
if(icon->img == nil)
|
||||
sysfatal("reading image %s: %r", file);
|
||||
close(fd);
|
||||
|
||||
if(h.first)
|
||||
h.last->next = icon;
|
||||
else
|
||||
h.first = icon;
|
||||
h.last = icon;
|
||||
h.n++;
|
||||
|
||||
icon->h = Dy(icon->img->r);
|
||||
icon->w = Dx(icon->img->r);
|
||||
icon->bits = 1<<icon->img->depth;
|
||||
icon->nplane = 1;
|
||||
|
||||
/* convert to 8 bits per pixel */
|
||||
switch(icon->img->chan){
|
||||
case GREY8:
|
||||
case CMAP8:
|
||||
break;
|
||||
case GREY1:
|
||||
case GREY2:
|
||||
case GREY4:
|
||||
mk8bit(icon, 1);
|
||||
break;
|
||||
default:
|
||||
mk8bit(icon, 0);
|
||||
break;
|
||||
}
|
||||
icon->bits = 8;
|
||||
icon->file = file;
|
||||
|
||||
/* create xor/and masks, minimizing bits per pixel */
|
||||
mkxorand(icon, icon->img->chan == GREY8);
|
||||
}
|
||||
|
||||
void*
|
||||
emalloc(int len)
|
||||
{
|
||||
void *x;
|
||||
|
||||
x = mallocz(len, 1);
|
||||
if(x == nil)
|
||||
sysfatal("memory: %r");
|
||||
return x;
|
||||
}
|
||||
|
||||
/* convert to 8 bit */
|
||||
void
|
||||
mk8bit(Icon *icon, int grey)
|
||||
{
|
||||
Image *img;
|
||||
|
||||
img = allocimage(display, icon->img->r, grey ? GREY8 : CMAP8, 0, DNofill);
|
||||
if(img == nil)
|
||||
sysfatal("can't allocimage: %r");
|
||||
draw(img, img->r, icon->img, nil, ZP);
|
||||
freeimage(icon->img);
|
||||
icon->img = img;
|
||||
}
|
||||
|
||||
/* make xor and and mask */
|
||||
void
|
||||
mkxorand(Icon *icon, int grey)
|
||||
{
|
||||
int i, x, y, s, sa;
|
||||
uchar xx[256];
|
||||
uchar *data, *p, *e;
|
||||
int ndata;
|
||||
uchar *mp;
|
||||
int ncolor;
|
||||
ulong color;
|
||||
int bits;
|
||||
uchar andbyte, xorbyte;
|
||||
uchar *ato, *xto;
|
||||
int xorrl, andrl;
|
||||
|
||||
ndata = icon->h * icon->w;
|
||||
data = emalloc(ndata);
|
||||
if(unloadimage(icon->img, icon->img->r, data, ndata) < 0)
|
||||
sysfatal("can't unload %s: %r", icon->file);
|
||||
e = data + ndata;
|
||||
|
||||
/* find colors used */
|
||||
memset(xx, 0, sizeof xx);
|
||||
for(p = data; p < e; p++)
|
||||
xx[*p]++;
|
||||
|
||||
/* count the colors and create a mapping from plan 9 */
|
||||
mp = icon->map;
|
||||
ncolor = 0;
|
||||
for(i = 0; i < 256; i++){
|
||||
if(xx[i] == 0)
|
||||
continue;
|
||||
if(grey){
|
||||
*mp++ = i;
|
||||
*mp++ = i;
|
||||
*mp++ = i;
|
||||
*mp++ = 0;
|
||||
} else {
|
||||
color = cmap2rgb(i);
|
||||
*mp++ = color;
|
||||
*mp++ = color>>8;
|
||||
*mp++ = color>>16;
|
||||
*mp++ = 0;
|
||||
}
|
||||
xx[i] = ncolor;
|
||||
ncolor++;
|
||||
}
|
||||
|
||||
/* get minimum number of pixels per bit (with a color map) */
|
||||
if(ncolor <= 2){
|
||||
ncolor = 2;
|
||||
bits = 1;
|
||||
} else if(ncolor <= 4){
|
||||
ncolor = 4;
|
||||
bits = 2;
|
||||
} else if(ncolor <= 16){
|
||||
ncolor = 16;
|
||||
bits = 4;
|
||||
} else {
|
||||
ncolor = 256;
|
||||
bits = 8;
|
||||
}
|
||||
icon->bits = bits;
|
||||
icon->ncolor = ncolor;
|
||||
|
||||
/* the xor mask rows are justified to a 32 bit boundary */
|
||||
/* the and mask is 1 bit grey */
|
||||
xorrl = 4*((bits*icon->w + 31)/32);
|
||||
andrl = 4*((icon->w + 31)/32);
|
||||
icon->xor = emalloc(xorrl * icon->h);
|
||||
icon->and = emalloc(andrl * icon->h);
|
||||
icon->xorlen = xorrl*icon->h;
|
||||
icon->andlen = andrl*icon->h;
|
||||
|
||||
/* make both masks. they're upside down relative to plan9 ones */
|
||||
p = data;
|
||||
for(y = 0; y < icon->h; y++){
|
||||
andbyte = 0;
|
||||
xorbyte = 0;
|
||||
sa = s = 0;
|
||||
xto = icon->xor + (icon->h-1-y)*xorrl;
|
||||
ato = icon->and + (icon->h-1-y)*andrl;
|
||||
for(x = 0; x < icon->w; x++){
|
||||
xorbyte <<= bits;
|
||||
xorbyte |= xx[*p];
|
||||
s += bits;
|
||||
if(s == 8){
|
||||
*xto++ = xorbyte;
|
||||
xorbyte = 0;
|
||||
s = 0;
|
||||
}
|
||||
andbyte <<= 1;
|
||||
if(*p == 0xff)
|
||||
andbyte |= 1;
|
||||
sa++;
|
||||
if(sa == 0){
|
||||
*ato++ = andbyte;
|
||||
sa = 0;
|
||||
andbyte = 0;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue