summaryrefslogtreecommitdiff
path: root/sys/src/cmd/rotate.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-09-04 19:17:30 +0200
committercinap_lenrek <cinap_lenrek@centraldogma>2011-09-04 19:17:30 +0200
commit73d4cf72277c2626b6a9e4c9597674a316e58591 (patch)
treec434b2091ad4f48df76dd31132469e7dfce32fac /sys/src/cmd/rotate.c
parent6842f8712508262d0ea27692f13caa686419601e (diff)
add resize (from richard miller) and rotate
Diffstat (limited to 'sys/src/cmd/rotate.c')
-rw-r--r--sys/src/cmd/rotate.c148
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);
+}
+