ref: a70b93a356662355214f5405edda066786f6dd03
dir: /sys/src/cmd/rotate.c/
#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; bpp = (m->depth+7)/8; chan = m->chan; switch(chan){ case GREY1: case GREY2: case GREY4: 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, m->r.min.x+dy, m->r.min.y+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* upsidedown(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; } void usage(void) { fprint(2, "usage: %s [ -r degree ] [ -u | -l ] [ file ]\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { Memimage *m; int fd, r; char f; f = 0; r = 0; fd = 0; ARGBEGIN { case 'u': f = 'u'; break; case 'l': f = 'l'; break; 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"); if(f == 'u' || f == 'l'){ m = upsidedown(m); if(f == 'l') r = 180; } switch(r % 360){ case 270: m = rot90(m); case 180: m = rot90(m); case 90: m = rot90(m); break; } if(writememimage(1, m) < 0) sysfatal("writememimage: %r"); exits(0); }