]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rotate.c
merge
[plan9front.git] / sys / src / cmd / rotate.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5
6 Memimage*
7 rot90(Memimage *m)
8 {
9         int line, bpp, x, y, dx, dy;
10         ulong chan;
11         uchar *s, *d;
12         Memimage *w;
13         char buf[12];
14
15         bpp = m->depth/8;
16         chan = m->chan;
17         switch(chan){
18         default:
19                 sysfatal("can't handle channel type %s", chantostr(buf, chan));
20         case RGB15:
21                 bpp = 2;
22         case CMAP8:
23         case GREY8:
24         case RGB16:
25         case RGB24:
26         case RGBA32:
27         case ARGB32:
28         case XRGB32:
29                 break;
30         case GREY1:
31         case GREY2:
32         case GREY4:
33                 bpp = 1;
34                 if((w = allocmemimage(m->r, GREY8)) == nil)
35                         sysfatal("allocmemimage: %r");
36                 memimagedraw(w, w->r, m, m->r.min, nil, ZP, S);
37                 freememimage(m);
38                 m = w;
39                 break;
40         }
41
42         dx = Dx(m->r);
43         dy = Dy(m->r);
44         if((w = allocmemimage(Rect(m->r.min.x, m->r.min.y, dy, dx), m->chan)) == nil)
45                 sysfatal("allocmemimage: %r");
46         line = w->width*sizeof(ulong);
47         for(y=0; y<dy; y++){
48                 s = byteaddr(m, addpt(m->r.min, Pt(0, y)));
49                 d = byteaddr(w, addpt(w->r.min, Pt(dy-y-1, 0)));
50                 for(x=0; x<dx; x++){
51                         switch(bpp){
52                         case 4:
53                                 d[3] = s[3];
54                         case 3:
55                                 d[2] = s[2];
56                         case 2:
57                                 d[1] = s[1];
58                         case 1:
59                                 d[0] = s[0];
60                         }
61                         s += bpp;
62                         d += line;
63                 }
64         }
65         freememimage(m);
66         if(w->chan != chan){
67                 if((m = allocmemimage(w->r, chan)) == nil)
68                         sysfatal("allocmemimage: %r");
69                 memimagedraw(m, m->r, w, w->r.min, nil, ZP, S);
70                 freememimage(w);
71                 w = m;
72         }
73         return w;
74 }
75
76 Memimage*
77 rot180(Memimage *m)
78 {
79         uchar *s, *d, *t;
80         int w, y, dy;
81
82         dy = Dy(m->r);
83         w = m->width * sizeof(ulong);
84         if((t = malloc(w)) == nil)
85                 sysfatal("malloc: %r");
86         for(y=0; y<dy/2; y++){
87                 s = byteaddr(m, addpt(m->r.min, Pt(0, y)));
88                 d = byteaddr(m, addpt(m->r.min, Pt(0, dy-y-1)));
89                 memmove(t, d, w);
90                 memmove(d, s, w);
91                 memmove(s, t, w);
92         }
93         free(t);
94         return m;
95 }
96
97 Memimage*
98 rot270(Memimage *m)
99 {
100         return rot90(rot180(m));
101 }
102
103 void
104 usage(void)
105 {
106         fprint(2, "usage: %s -r degree [ file ]\n", argv0);
107         exits("usage");
108 }
109
110 void
111 main(int argc, char *argv[])
112 {
113         Memimage *m;
114         int fd, r;
115
116         r = 0;
117         fd = 0;
118         ARGBEGIN {
119         case 'r':
120                 r = atoi(EARGF(usage()));
121                 break;
122         default:
123                 usage();
124         } ARGEND;
125         if(*argv){
126                 fd = open(*argv, OREAD);
127                 if(fd < 0)
128                         sysfatal("open: %r");
129         }
130         memimageinit();
131         if((m = readmemimage(fd)) == nil)
132                 sysfatal("readmemimage: %r");
133         switch(r % 360){
134         case 90:
135                 m = rot90(m);
136                 break;
137         case 180:
138                 m = rot180(m);
139                 break;
140         case 270:
141                 m = rot270(m);
142                 break;
143         }
144         if(writememimage(1, m) < 0)
145                 sysfatal("writememimage: %r");
146         exits(0);
147 }
148