commit 228bb71d16e38cf05974d547899282eda5bb2731 from: rsc date: Tue Dec 28 23:13:17 2004 UTC add crop commit - 1d2533d0101fd1721ab26837485c0b094205c3bd commit + 228bb71d16e38cf05974d547899282eda5bb2731 blob - /dev/null blob + e397a312c30484bfc961d379c5a0b32574fe6c56 (mode 644) --- /dev/null +++ src/cmd/draw/crop.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include + +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; yr.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 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 = ""; + 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); +}