plan9front/sys/src/games/todpic.c

191 lines
3.1 KiB
C
Raw Permalink Normal View History

2018-07-24 20:02:46 -07:00
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <bio.h>
int wofs;
u32int pal[256], bg = 0x00ffff;
Biobuf *bp;
#define abs(x) ((x) < 0 ? -(x) : (x))
void
put8(u8int v)
{
if(Bwrite(bp, &v, sizeof v) != sizeof v)
sysfatal("put8: short write");
}
void
put16(u16int v)
{
put8(v);
put8(v >> 8);
}
void
put32(u32int v)
{
put16(v);
put16(v >> 16);
}
int
pali(u32int v)
{
int i, Δ, Δ´;
u32int *p;
i = 0;
Δ = abs((char)v - (char)*pal)
+ abs((char)(v >> 8) - (char)(*pal >> 8))
+ abs((char)(v >> 16) - (char)(*pal >> 16));
for(p=pal; p<pal+nelem(pal); p++){
Δ´ = abs((char)v - (char)*p)
+ abs((char)(v >> 8) - (char)(*p >> 8))
+ abs((char)(v >> 16) - (char)(*p >> 16));
if(Δ´ < Δ){
Δ = Δ´;
i = p - pal;
if(Δ == 0)
break;
}
}
return i;
}
void
topic(Memimage *i)
{
int w, h, dx, dy;
uchar *np, *b, *buf, *p, *pp;
u32int v;
p = i->data->bdata;
dx = Dx(i->r);
dy = Dy(i->r);
if(dy > 254)
sysfatal("topic: invalid pic height");
put16(dx);
put16(dy);
put16(wofs ? dx / 2 - 1 : i->r.min.x);
put16(wofs ? dy - 5 : i->r.min.y);
if(i->r.min.x != 0)
dx = i->width;
buf = mallocz((5 * dy / 2 + 5) * dx, 1);
if(buf == nil)
sysfatal("mallocz: %r");
for(w=dx, b=buf; w>0; w--, p+=3){
put32(b - buf + 8 + dx * 4);
for(h=0, np=b+1, pp=p; h<dy; h++, pp+=dx*3){
v = pp[2] << 16 | pp[1] << 8 | pp[0];
if(v == bg){
if(b - np - 2 > 0){
*np = b - np - 2;
*b++ = 0;
np = b + 1;
}
continue;
}
if(b - np - 2 < 0){
*b++ = h;
b++;
*b++ = 0;
}
*b++ = pali(v);
}
if(b - np - 2 >= 0){
*np = b - np - 2;
*b++ = 0;
}
*b++ = 0xff;
}
Bwrite(bp, buf, b - buf);
free(buf);
}
void
toflat(Memimage *i)
{
int n;
uchar *p;
if(Dx(i->r) != 64 || Dy(i->r) != 64)
sysfatal("toflat: invalid flatpic dimensions");
p = i->data->bdata;
n = 64*64;
while(n-- > 0){
put8(pali(p[2] << 16 | p[1] << 8 | p[0]));
p += 4;
}
}
static Memimage*
iconv(Memimage *i)
{
Memimage *ni;
if(i->chan == RGB24)
return i;
if((ni = allocmemimage(i->r, RGB24)) == nil)
sysfatal("allocmemimage: %r");
memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S);
freememimage(i);
return ni;
}
void
getpal(char *f)
{
uchar u[3];
u32int *p;
Biobuf *bp;
if((bp = Bopen(f, OREAD)) == nil)
sysfatal("getpal: %r");
for(p=pal; p<pal+nelem(pal); p++){
if(Bread(bp, u, 3) != 3)
sysfatal("getpal: short read: %r");
*p = u[0]<<16 | u[1]<<8 | u[2];
}
Bterm(bp);
}
void
usage(void)
{
fprint(2, "usage: %s [-fw] [-b bgcol] [-p palette] [image]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
int fd, flat;
char *p;
Memimage *i;
fd = 0;
flat = 0;
p = "/mnt/wad/playpal";
ARGBEGIN{
case 'b': bg = strtoul(EARGF(usage()), nil, 0); break;
case 'f': flat = 1; break;
case 'p': p = EARGF(usage()); break;
case 'w': wofs = 1; break;
default: usage();
}ARGEND
if(*argv != nil)
if((fd = open(*argv, OREAD)) < 0)
sysfatal("open: %r");
getpal(p);
if((bp = Bfdopen(1, OWRITE)) == nil)
sysfatal("Bfdopen: %r");
memimageinit();
if((i = readmemimage(fd)) == nil)
sysfatal("readmemimage: %r");
(flat ? toflat : topic)(iconv(i));
exits(nil);
}