blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

blind-crop.c (2796B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-s | -S | -t] width height left top")
      5 
      6 int
      7 main(int argc, char *argv[])
      8 {
      9 	struct stream stream;
     10 	char *buf, *image, *p;
     11 	size_t width = 0, height = 0, left = 0, top = 0;
     12 	size_t right, right_start, bottom, bottom_start;
     13 	size_t off, yoff = 0, x, y, irown, orown, ptr, m;
     14 	int tile = 0, keepsize = 0, keepsize_inv = 0;
     15 
     16 	ARGBEGIN {
     17 	case 's':
     18 		keepsize = 1;
     19 		break;
     20 	case 'S':
     21 		keepsize_inv = 1;
     22 		break;
     23 	case 't':
     24 		tile = 1;
     25 		break;
     26 	default:
     27 		usage();
     28 	} ARGEND;
     29 
     30 	if (argc != 4 || tile + keepsize + keepsize_inv > 1)
     31 		usage();
     32 
     33 	width  = etozu_arg("the width",         argv[0], 1, SIZE_MAX);
     34 	height = etozu_arg("the height",        argv[1], 1, SIZE_MAX);
     35 	left   = etozu_arg("the left position", argv[2], 0, SIZE_MAX);
     36 	top    = etozu_arg("the top position",  argv[3], 0, SIZE_MAX);
     37 
     38 	eopen_stream(&stream, NULL);
     39 	if (left > SIZE_MAX - width || left + width > stream.width ||
     40 	    top > SIZE_MAX - height || top + height > stream.height)
     41 		eprintf("crop area extends beyond original image\n");
     42 	if (tile || keepsize || keepsize_inv) {
     43 		fprint_stream_head(stdout, &stream);
     44 	} else {
     45 		x = stream.width,  stream.width  = width;
     46 		y = stream.height, stream.height = height;
     47 		fprint_stream_head(stdout, &stream);
     48 		stream.width  = x;
     49 		stream.height = y;
     50 	}
     51 	efflush(stdout, "<stdout>");
     52 
     53 	echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
     54 	irown = stream.row_size;
     55 	buf = emalloc(stream.frame_size);
     56 	orown = width * stream.pixel_size;
     57 	m = (tile || keepsize || keepsize_inv) ? stream.frame_size : height * orown;
     58 	image = (keepsize || keepsize_inv) ? buf : emalloc(m);
     59 
     60 	left *= stream.pixel_size;
     61 	if (!tile) {
     62 		off = top * irown + left;
     63 	} else {
     64 		off  = (orown  - left % orown)  % orown;
     65 		yoff = (height - top  % height) % height;
     66 	}
     67 	bottom = stream.height - (bottom_start = top  + height);
     68 	right  = irown         - (right_start  = left + orown);
     69 
     70 	while (eread_frame(&stream, buf)) {
     71 		if (tile) {
     72 			for (ptr = y = 0; y < stream.height; y++) {
     73 				p = buf + ((y + yoff) % height + top) * irown;
     74 				for (x = 0; x < irown; x++, ptr++)
     75 					image[ptr] = p[(x + off) % orown + left];
     76 			}
     77 		} else if (keepsize) {
     78 			memset(image, 0, top * irown);
     79 			memset(image + bottom_start * irown, 0, bottom * irown);
     80 			for (y = top; y < bottom_start; y++) {
     81 				memset(image + y * irown, 0, left);
     82 				memset(image + y * irown + right_start, 0, right);
     83 			}
     84 		} else if (keepsize_inv) {
     85 			for (y = top; y < bottom_start; y++)
     86 				memset(image + y * irown + left, 0, orown);
     87 		} else {
     88 			for (y = 0; y < height; y++)
     89 				memcpy(image + y * orown, buf + y * irown + off, orown);
     90 		}
     91 		ewriteall(STDOUT_FILENO, image, m, "<stdout>");
     92 	}
     93 
     94 	if (buf != image)
     95 		free(image);
     96 	free(buf);
     97 	return 0;
     98 }