URI:
       tcrop.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tcrop.c (4138B)
       ---
            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 [-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 }
           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, uint32 c)
           39 {
           40         Memimage *n;
           41         int x, y, bpl, wpl;
           42         int left, right, top, bottom;
           43         uint32 *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(uint32);
           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         uint32 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 }