123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <memdraw.h>
- enum
- {
- None,
- Inset, /* move border in or out uniformly */
- Insetxy, /* move border in or out; different parameters for x and y */
- Set, /* set rectangle to absolute values */
- Blank, /* cut off blank region according to color value */
- /* Blank is not actually set as a mode; it can be combined with others */
- };
- void
- usage(void)
- {
- fprint(2, "usage: crop [-c rgb] [-i ±inset | -r R | -x ±inset | -y ±inset] [-t tx ty] [-b rgb ] [imagefile]\n");
- fprint(2, "\twhere R is a rectangle minx miny maxx maxy\n");
- fprint(2, "\twhere rgb is a color red green blue\n");
- exits("usage");
- }
- int
- getint(char *s)
- {
- if(s == nil)
- usage();
- if(*s == '+')
- return atoi(s+1);
- if(*s == '-')
- return -atoi(s+1);
- return atoi(s);
- }
- Rectangle
- crop(Memimage *m, ulong c)
- {
- Memimage *n;
- int x, y, bpl, wpl;
- int left, right, top, bottom;
- ulong *buf;
- left = m->r.max.x;
- right = m->r.min.x;
- top = m->r.max.y;
- bottom = m->r.min.y;
- n = nil;
- if(m->chan != RGBA32){
- /* convert type for simplicity */
- n = allocmemimage(m->r, RGBA32);
- if(n == nil)
- sysfatal("can't allocate temporary image: %r");
- memimagedraw(n, n->r, m, m->r.min, nil, ZP, S);
- m = n;
- }
- wpl = wordsperline(m->r, m->depth);
- bpl = wpl*sizeof(ulong);
- buf = malloc(bpl);
- if(buf == nil)
- sysfatal("can't allocate buffer: %r");
- for(y=m->r.min.y; y<m->r.max.y; y++){
- x = unloadmemimage(m, Rect(m->r.min.x, y, m->r.max.x, y+1), (uchar*)buf, bpl);
- if(x != bpl)
- sysfatal("unloadmemimage");
- for(x=0; x<wpl; x++)
- if(buf[x] != c){
- if(x < left)
- left = x;
- if(x > right)
- right = x;
- if(y < top)
- top = y;
- bottom = y;
- }
- }
-
- if(n != nil)
- freememimage(n);
- return Rect(left, top, right+1, bottom+1);
- }
- void
- main(int argc, char *argv[])
- {
- int fd, mode, red, green, blue;
- Rectangle r, rparam;
- Point t;
- Memimage *m, *new;
- char *file;
- ulong bg, cropval;
- long dw;
- memimageinit();
- mode = None;
- bg = 0;
- cropval = 0;
- t = ZP;
- memset(&rparam, 0, sizeof rparam);
- ARGBEGIN{
- case 'b':
- if(bg != 0)
- usage();
- red = getint(ARGF())&0xFF;
- green = getint(ARGF())&0xFF;
- blue = getint(ARGF())&0xFF;
- bg = (red<<24)|(green<<16)|(blue<<8)|0xFF;
- break;
- case 'c':
- if(cropval != 0)
- usage();
- red = getint(ARGF())&0xFF;
- green = getint(ARGF())&0xFF;
- blue = getint(ARGF())&0xFF;
- cropval = (red<<24)|(green<<16)|(blue<<8)|0xFF;
- break;
- case 'i':
- if(mode != None)
- usage();
- mode = Inset;
- rparam.min.x = getint(ARGF());
- break;
- case 'x':
- if(mode != None && mode != Insetxy)
- usage();
- mode = Insetxy;
- rparam.min.x = getint(ARGF());
- break;
- case 'y':
- if(mode != None && mode != Insetxy)
- usage();
- mode = Insetxy;
- rparam.min.y = getint(ARGF());
- break;
- case 'r':
- if(mode != None)
- usage();
- mode = Set;
- rparam.min.x = getint(ARGF());
- rparam.min.y = getint(ARGF());
- rparam.max.x = getint(ARGF());
- rparam.max.y = getint(ARGF());
- break;
- case 't':
- t.x = getint(ARGF());
- t.y = getint(ARGF());
- break;
- default:
- usage();
- }ARGEND
- if(mode == None && cropval == 0 && eqpt(ZP, t))
- usage();
- file = "<stdin>";
- fd = 0;
- if(argc > 1)
- usage();
- else if(argc == 1){
- file = argv[0];
- fd = open(file, OREAD);
- if(fd < 0)
- sysfatal("can't open %s: %r", file);
- }
- m = readmemimage(fd);
- if(m == nil)
- sysfatal("can't read %s: %r", file);
- r = m->r;
- if(cropval != 0){
- r = crop(m, cropval);
- m->clipr = r;
- }
- switch(mode){
- case None:
- break;
- case Inset:
- r = insetrect(r, rparam.min.x);
- break;
- case Insetxy:
- r.min.x += rparam.min.x;
- r.max.x -= rparam.min.x;
- r.min.y += rparam.min.y;
- r.max.y -= rparam.min.y;
- break;
- case Set:
- r = rparam;
- break;
- }
- new = allocmemimage(r, m->chan);
- if(new == nil)
- sysfatal("can't allocate new image: %r");
- if(bg != 0)
- memfillcolor(new, bg);
- else
- memfillcolor(new, 0x000000FF);
- memimagedraw(new, m->clipr, m, m->clipr.min, nil, ZP, S);
- dw = byteaddr(new, ZP) - byteaddr(new, t);
- new->r = rectaddpt(new->r, t);
- new->zero += dw;
- if(writememimage(1, new) < 0)
- sysfatal("write error on output: %r");
- exits(nil);
- }
|