crop.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 }