Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <memdraw.h>
5
 
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
};
15
 
16
void
17
usage(void)
18
{
19
	fprint(2, "usage: crop [-b rgb] [-c rgb] [-i ±inset | -r R | -x ±inset | -y ±inset] [-t tx ty] [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
}
24
 
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
}
36
 
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;
44
 
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");
63
 
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
	}
79
 
80
	if(n != nil)
81
		freememimage(n);
82
	return Rect(left, top, right+1, bottom+1);
83
}
84
 
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;
95
 
96
	memimageinit();
97
	mode = None;
98
	bg = 0;
99
	cropval = 0;
100
	t = ZP;
101
	memset(&rparam, 0, sizeof rparam);
102
 
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
154
 
155
	if(mode == None && cropval == 0 && eqpt(ZP, t))
156
		usage();
157
 
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);
167
	}
168
 
169
	m = readmemimage(fd);
170
	if(m == nil)
171
		sysfatal("can't read %s: %r", file);
172
 
173
	r = m->r;
174
	if(cropval != 0){
175
		r = crop(m, cropval);
176
		m->clipr = r;
177
	}
178
 
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;
194
	}
195
 
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);
203
 
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);
211
}