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 }