diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-09-04 19:17:30 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-09-04 19:17:30 +0200 |
commit | 73d4cf72277c2626b6a9e4c9597674a316e58591 (patch) | |
tree | c434b2091ad4f48df76dd31132469e7dfce32fac /sys/src/cmd/rotate.c | |
parent | 6842f8712508262d0ea27692f13caa686419601e (diff) |
add resize (from richard miller) and rotate
Diffstat (limited to 'sys/src/cmd/rotate.c')
-rw-r--r-- | sys/src/cmd/rotate.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/sys/src/cmd/rotate.c b/sys/src/cmd/rotate.c new file mode 100644 index 000000000..5c4d4fa94 --- /dev/null +++ b/sys/src/cmd/rotate.c @@ -0,0 +1,148 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <memdraw.h> + +Memimage* +rot90(Memimage *m) +{ + int line, bpp, x, y, dx, dy; + ulong chan; + uchar *s, *d; + Memimage *w; + char buf[12]; + + bpp = m->depth/8; + chan = m->chan; + switch(chan){ + default: + sysfatal("can't handle channel type %s", chantostr(buf, chan)); + case RGB15: + bpp = 2; + case CMAP8: + case GREY8: + case RGB16: + case RGB24: + case RGBA32: + case ARGB32: + case XRGB32: + break; + case GREY1: + case GREY2: + case GREY4: + bpp = 1; + if((w = allocmemimage(m->r, GREY8)) == nil) + sysfatal("allocmemimage: %r"); + memimagedraw(w, w->r, m, m->r.min, nil, ZP, S); + freememimage(m); + m = w; + break; + } + + dx = Dx(m->r); + dy = Dy(m->r); + if((w = allocmemimage(Rect(m->r.min.x, m->r.min.y, dy, dx), m->chan)) == nil) + sysfatal("allocmemimage: %r"); + line = w->width*sizeof(ulong); + for(y=0; y<dy; y++){ + s = byteaddr(m, addpt(m->r.min, Pt(0, y))); + d = byteaddr(w, addpt(w->r.min, Pt(dy-y-1, 0))); + for(x=0; x<dx; x++){ + switch(bpp){ + case 4: + d[3] = s[3]; + case 3: + d[2] = s[2]; + case 2: + d[1] = s[1]; + case 1: + d[0] = s[0]; + } + s += bpp; + d += line; + } + } + freememimage(m); + if(w->chan != chan){ + if((m = allocmemimage(w->r, chan)) == nil) + sysfatal("allocmemimage: %r"); + memimagedraw(m, m->r, w, w->r.min, nil, ZP, S); + freememimage(w); + w = m; + } + return w; +} + +Memimage* +rot180(Memimage *m) +{ + uchar *s, *d, *t; + int w, y, dy; + + dy = Dy(m->r); + w = m->width * sizeof(ulong); + if((t = malloc(w)) == nil) + sysfatal("malloc: %r"); + for(y=0; y<dy/2; y++){ + s = byteaddr(m, addpt(m->r.min, Pt(0, y))); + d = byteaddr(m, addpt(m->r.min, Pt(0, dy-y-1))); + memmove(t, d, w); + memmove(d, s, w); + memmove(s, t, w); + } + free(t); + return m; +} + +Memimage* +rot270(Memimage *m) +{ + return rot90(rot180(m)); +} + +void +usage(void) +{ + fprint(2, "usage: %s -r degree [ file ]\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Memimage *m; + int fd, r; + + r = 0; + fd = 0; + ARGBEGIN { + case 'r': + r = atoi(EARGF(usage())); + break; + default: + usage(); + } ARGEND; + if(*argv){ + fd = open(*argv, OREAD); + if(fd < 0) + sysfatal("open: %r"); + } + memimageinit(); + if((m = readmemimage(fd)) == nil) + sysfatal("readmemimage: %r"); + switch(r % 360){ + case 90: + m = rot90(m); + break; + case 180: + m = rot180(m); + break; + case 270: + m = rot270(m); + break; + } + if(writememimage(1, m) < 0) + sysfatal("writememimage: %r"); + exits(0); +} + |