2011-09-04 17:17:30 +00:00
|
|
|
#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;
|
|
|
|
|
2012-10-18 18:17:12 +00:00
|
|
|
bpp = (m->depth+7)/8;
|
2011-09-04 17:17:30 +00:00
|
|
|
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);
|
2011-12-02 11:09:08 +00:00
|
|
|
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)
|
2011-09-04 17:17:30 +00:00
|
|
|
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*
|
2011-09-10 21:15:39 +00:00
|
|
|
upsidedown(Memimage *m)
|
2011-09-04 17:17:30 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2011-09-10 23:01:50 +00:00
|
|
|
fprint(2, "usage: %s [ -r degree ] [ -u | -l ] [ file ]\n", argv0);
|
2011-09-04 17:17:30 +00:00
|
|
|
exits("usage");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
Memimage *m;
|
|
|
|
int fd, r;
|
2011-09-10 21:15:39 +00:00
|
|
|
char f;
|
2011-09-04 17:17:30 +00:00
|
|
|
|
2011-09-10 21:15:39 +00:00
|
|
|
f = 0;
|
2011-09-04 17:17:30 +00:00
|
|
|
r = 0;
|
|
|
|
fd = 0;
|
|
|
|
ARGBEGIN {
|
2011-09-10 21:15:39 +00:00
|
|
|
case 'u':
|
|
|
|
f = 'u';
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
f = 'l';
|
|
|
|
break;
|
2011-09-04 17:17:30 +00:00
|
|
|
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");
|
2011-09-10 21:15:39 +00:00
|
|
|
if(f == 'u' || f == 'l'){
|
|
|
|
m = upsidedown(m);
|
|
|
|
if(f == 'l')
|
|
|
|
r = 180;
|
|
|
|
}
|
2011-09-04 17:17:30 +00:00
|
|
|
switch(r % 360){
|
2011-09-10 21:15:39 +00:00
|
|
|
case 270:
|
2011-09-04 17:17:30 +00:00
|
|
|
m = rot90(m);
|
|
|
|
case 180:
|
2011-09-10 21:15:39 +00:00
|
|
|
m = rot90(m);
|
|
|
|
case 90:
|
|
|
|
m = rot90(m);
|
2011-09-04 17:17:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(writememimage(1, m) < 0)
|
|
|
|
sysfatal("writememimage: %r");
|
|
|
|
exits(0);
|
|
|
|
}
|
|
|
|
|