tadd crop - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 228bb71d16e38cf05974d547899282eda5bb2731
 (DIR) parent 1d2533d0101fd1721ab26837485c0b094205c3bd
 (HTM) Author: rsc <devnull@localhost>
       Date:   Tue, 28 Dec 2004 23:13:17 +0000
       
       add crop
       
       Diffstat:
         A src/cmd/draw/crop.c                 |     211 +++++++++++++++++++++++++++++++
       
       1 file changed, 211 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/draw/crop.c b/src/cmd/draw/crop.c
       t@@ -0,0 +1,211 @@
       +#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);
       +}