Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
6 enum
7 {
8 None,
9 Inset, /* move border in or out uniformly */
10 Insetxy, /* move border in or out; different parameters for x and y */
11 Set, /* set rectangle to absolute values */
12 Blank, /* cut off blank region according to color value */
13 /* Blank is not actually set as a mode; it can be combined with others */
14 };
16 void
17 usage(void)
18 {
19 fprint(2, "usage: crop [-c rgb] [-i ±inset | -r R | -x ±inset | -y ±inset] [-t tx ty] [-b rgb ] [imagefile]\n");
20 fprint(2, "\twhere R is a rectangle minx miny maxx maxy\n");
21 fprint(2, "\twhere rgb is a color red green blue\n");
22 exits("usage");
23 }
25 int
26 getint(char *s)
27 {
28 if(s == nil)
29 usage();
30 if(*s == '+')
31 return atoi(s+1);
32 if(*s == '-')
33 return -atoi(s+1);
34 return atoi(s);
35 }
37 Rectangle
38 crop(Memimage *m, ulong c)
39 {
40 Memimage *n;
41 int x, y, bpl, wpl;
42 int left, right, top, bottom;
43 ulong *buf;
45 left = m->r.max.x;
46 right = m->r.min.x;
47 top = m->r.max.y;
48 bottom = m->r.min.y;
49 n = nil;
50 if(m->chan != RGBA32){
51 /* convert type for simplicity */
52 n = allocmemimage(m->r, RGBA32);
53 if(n == nil)
54 sysfatal("can't allocate temporary image: %r");
55 memimagedraw(n, n->r, m, m->r.min, nil, ZP, S);
56 m = n;
57 }
58 wpl = wordsperline(m->r, m->depth);
59 bpl = wpl*sizeof(ulong);
60 buf = malloc(bpl);
61 if(buf == nil)
62 sysfatal("can't allocate buffer: %r");
64 for(y=m->r.min.y; y<m->r.max.y; y++){
65 x = unloadmemimage(m, Rect(m->r.min.x, y, m->r.max.x, y+1), (uchar*)buf, bpl);
66 if(x != bpl)
67 sysfatal("unloadmemimage");
68 for(x=0; x<wpl; x++)
69 if(buf[x] != c){
70 if(x < left)
71 left = x;
72 if(x > right)
73 right = x;
74 if(y < top)
75 top = y;
76 bottom = y;
77 }
78 }
80 if(n != nil)
81 freememimage(n);
82 return Rect(left, top, right+1, bottom+1);
83 }
85 void
86 main(int argc, char *argv[])
87 {
88 int fd, mode, red, green, blue;
89 Rectangle r, rparam;
90 Point t;
91 Memimage *m, *new;
92 char *file;
93 ulong bg, cropval;
94 long dw;
96 memimageinit();
97 mode = None;
98 bg = 0;
99 cropval = 0;
100 t = ZP;
101 memset(&rparam, 0, sizeof rparam);
103 ARGBEGIN{
104 case 'b':
105 if(bg != 0)
106 usage();
107 red = getint(ARGF())&0xFF;
108 green = getint(ARGF())&0xFF;
109 blue = getint(ARGF())&0xFF;
110 bg = (red<<24)|(green<<16)|(blue<<8)|0xFF;
111 break;
112 case 'c':
113 if(cropval != 0)
114 usage();
115 red = getint(ARGF())&0xFF;
116 green = getint(ARGF())&0xFF;
117 blue = getint(ARGF())&0xFF;
118 cropval = (red<<24)|(green<<16)|(blue<<8)|0xFF;
119 break;
120 case 'i':
121 if(mode != None)
122 usage();
123 mode = Inset;
124 rparam.min.x = getint(ARGF());
125 break;
126 case 'x':
127 if(mode != None && mode != Insetxy)
128 usage();
129 mode = Insetxy;
130 rparam.min.x = getint(ARGF());
131 break;
132 case 'y':
133 if(mode != None && mode != Insetxy)
134 usage();
135 mode = Insetxy;
136 rparam.min.y = getint(ARGF());
137 break;
138 case 'r':
139 if(mode != None)
140 usage();
141 mode = Set;
142 rparam.min.x = getint(ARGF());
143 rparam.min.y = getint(ARGF());
144 rparam.max.x = getint(ARGF());
145 rparam.max.y = getint(ARGF());
146 break;
147 case 't':
148 t.x = getint(ARGF());
149 t.y = getint(ARGF());
150 break;
151 default:
152 usage();
153 }ARGEND
155 if(mode == None && cropval == 0 && eqpt(ZP, t))
156 usage();
158 file = "<stdin>";
159 fd = 0;
160 if(argc > 1)
161 usage();
162 else if(argc == 1){
163 file = argv[0];
164 fd = open(file, OREAD);
165 if(fd < 0)
166 sysfatal("can't open %s: %r", file);
169 m = readmemimage(fd);
170 if(m == nil)
171 sysfatal("can't read %s: %r", file);
173 r = m->r;
174 if(cropval != 0){
175 r = crop(m, cropval);
176 m->clipr = r;
179 switch(mode){
180 case None:
181 break;
182 case Inset:
183 r = insetrect(r, rparam.min.x);
184 break;
185 case Insetxy:
186 r.min.x += rparam.min.x;
187 r.max.x -= rparam.min.x;
188 r.min.y += rparam.min.y;
189 r.max.y -= rparam.min.y;
190 break;
191 case Set:
192 r = rparam;
193 break;
196 new = allocmemimage(r, m->chan);
197 if(new == nil)
198 sysfatal("can't allocate new image: %r");
199 if(bg != 0)
200 memfillcolor(new, bg);
201 else
202 memfillcolor(new, 0x000000FF);
204 memimagedraw(new, m->clipr, m, m->clipr.min, nil, ZP, S);
205 dw = byteaddr(new, ZP) - byteaddr(new, t);
206 new->r = rectaddpt(new->r, t);
207 new->zero += dw;
208 if(writememimage(1, new) < 0)
209 sysfatal("write error on output: %r");
210 exits(nil);