implement cropping movies
Stefan Schuermans

Stefan Schuermans commited on 2014-05-10 14:17:11
Showing 5 changed files, with 178 additions and 28 deletions.

... ...
@@ -219,7 +219,7 @@ int main(int argCnt, char **args)
219 219
   stBlinkenMovie *pMovie;
220 220
   int i;
221 221
   char *str;
222
-  unsigned int height, width, channels, colors, times;
222
+  unsigned int height, width, channels, colors, times, top, left;
223 223
   int mode;
224 224
 
225 225
   // print info
... ...
@@ -253,6 +253,8 @@ int main(int argCnt, char **args)
253 253
            "     print movie\n"
254 254
            "  -r <width>x<height>-<channels>/<colors>\n"
255 255
            "     resize movie\n"
256
+           "  -cr <src-x>,<src-y> <width>x<height>\n"
257
+           "     crop movie\n"
256 258
            "  -s <width>x<height>\n"
257 259
            "     scale movie\n"
258 260
            "  -c <channels> [solid|rainbow]\n"
... ...
@@ -367,7 +369,7 @@ int main(int argCnt, char **args)
367 369
             printf("movie looped %u times\n", times);
368 370
         }
369 371
       } else
370
-        printf("missing movie format for \"-r\"\n");
372
+        printf("missing loop count for \"-l\"\n");
371 373
     }
372 374
     // output format, frame count and duration of movie
373 375
     else if (strcmp(args[i], "-f") == 0) {
... ...
@@ -415,6 +417,32 @@ int main(int argCnt, char **args)
415 417
       } else
416 418
         printf("missing movie format for \"-r\"\n");
417 419
     }
420
+    // crop movie
421
+    else if (strcmp(args[i], "-cr") == 0) {
422
+      if (i + 2 < argCnt) {
423
+        const char *topleft, *dimensions;
424
+        i++;
425
+        topleft = args[i];
426
+        i++;
427
+        dimensions = args[i];
428
+        if (sscanf
429
+            (topleft, "%u,%u", &left, &top) != 2)
430
+          printf("invalid top-left position \"%s\"\n", topleft);
431
+        else if (sscanf
432
+            (dimensions, "%ux%u", &width, &height) != 2)
433
+          printf("invalid movie dimensions \"%s\"\n", dimensions);
434
+        else if (pMovie == NULL)
435
+          printf("no movie loaded to crop\n");
436
+        else {
437
+          BlinkenMovieCrop(pMovie, top, left, height, width);
438
+          printf("movie cropped to %u,%u %ux%u\n", left, top, width, height);
439
+        }
440
+      } else if (i + 1 < argCnt) {
441
+        printf("missing dimensions for \"-cr\"\n");
442
+        i++;
443
+      } else
444
+        printf("missing top-left position for \"-cr\"\n");
445
+    }
418 446
     // scale movie
419 447
     else if (strcmp(args[i], "-s") == 0) {
420 448
       if (i + 1 < argCnt) {
... ...
@@ -339,12 +339,13 @@ int BlinkenFrameCompare(stBlinkenFrame *pFrame1, stBlinkenFrame *pFrame2)
339 339
   return 0;
340 340
 }
341 341
 
342
-void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
343
-                        int channels, int maxval)
342
+static void BlinkenFramePadCrop(stBlinkenFrame *pFrame, int height, int width,
343
+                                int channels, int maxval,
344
+                                int emptyY, int emptyX, int skipY, int skipX)
344 345
 {
345 346
   unsigned char **ppData;
346 347
   int y, x, c, i, j;
347
-  int emptyY, emptyX, skipY, skipX, rangeY, rangeX;
348
+  int rangeY, rangeX;
348 349
   unsigned long val, div;
349 350
 
350 351
   if (pFrame == NULL)
... ...
@@ -367,14 +368,13 @@ void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
367 368
   if (maxval > BlinkenMaxvalMax)
368 369
     maxval = BlinkenMaxvalMax;
369 370
 
370
-  if (height == pFrame->height &&
371
-      width == pFrame->width &&
372
-      channels == pFrame->channels && maxval == pFrame->maxval)
371
+  if (height == pFrame->height && width == pFrame->width &&
372
+      channels == pFrame->channels && maxval == pFrame->maxval &&
373
+      emptyX == 0 && emptyY == 0 && skipY == 0 && skipX == 0)
373 374
     return;
374 375
 
375 376
   // allocate new data array
376
-  ppData =
377
-      (unsigned char **)BlinkenMalloc2D(height, width * channels,
377
+  ppData = (unsigned char **)BlinkenMalloc2D(height, width * channels,
378 378
                                              sizeof(unsigned char));
379 379
   if (ppData == NULL)
380 380
     return;
... ...
@@ -383,27 +383,27 @@ void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
383 383
       for (c = 0; c < channels; c++, i++)
384 384
         ppData[y][i] = 0;
385 385
 
386
-  // get number of pixels to skip / to leave empty in X and Y direction
387
-  if (height > pFrame->height) {
388
-    emptyY = (height - pFrame->height) / 2;
389
-    skipY = 0;
390
-    rangeY = pFrame->height;
391
-  } else {
386
+  // sanitize number of pixels to skip / to leave empty in X and Y direction
387
+  if (emptyY < 0)
392 388
     emptyY = 0;
393
-    skipY = (pFrame->height - height) / 2;
394
-    rangeY = height;
395
-  }
396
-  if (width > pFrame->width) {
397
-    emptyX = (width - pFrame->width) / 2;
398
-    skipX = 0;
399
-    rangeX = pFrame->width;
400
-  } else {
389
+  if (emptyY > height)
390
+    emptyY = height;
391
+  if (emptyX < 0)
401 392
     emptyX = 0;
402
-    skipX = (pFrame->width - width) / 2;
403
-    rangeX = width;
404
-  }
393
+  if (emptyX > width)
394
+    emptyX = width;
395
+  if (skipY < 0)
396
+    skipY = 0;
397
+  if (skipY > pFrame->height)
398
+    skipY = pFrame->height;
399
+  if (skipX < 0)
400
+    skipX = 0;
401
+  if (skipX > pFrame->width)
402
+    skipX = pFrame->width;
403
+  rangeY = mini(height - emptyY, pFrame->height - skipY);
404
+  rangeX = mini(width - emptyX, pFrame->width - skipX);
405 405
 
406
-  // resize frame with help of calculated parameters
406
+  // pad/crop frame with help of calculated parameters
407 407
   for (y = 0; y < rangeY; y++) {
408 408
     for (x = 0; x < rangeX; x++) {
409 409
       i = (skipX + x) * pFrame->channels;
... ...
@@ -444,6 +444,88 @@ void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
444 444
   pFrame->ppData = ppData;
445 445
 }
446 446
 
447
+void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
448
+                        int channels, int maxval)
449
+{
450
+  int emptyY, emptyX, skipY, skipX;
451
+
452
+  if (pFrame == NULL)
453
+    return;
454
+
455
+  if (height < BlinkenHeightMin)
456
+    height = BlinkenHeightMin;
457
+  if (height > BlinkenHeightMax)
458
+    height = BlinkenHeightMax;
459
+  if (width < BlinkenWidthMin)
460
+    width = BlinkenWidthMin;
461
+  if (width > BlinkenWidthMax)
462
+    width = BlinkenWidthMax;
463
+  if (channels < BlinkenChannelsMin)
464
+    channels = BlinkenChannelsMin;
465
+  if (channels > BlinkenChannelsMax)
466
+    channels = BlinkenMaxvalMax;
467
+  if (maxval < BlinkenMaxvalMin)
468
+    maxval = BlinkenMaxvalMin;
469
+  if (maxval > BlinkenMaxvalMax)
470
+    maxval = BlinkenMaxvalMax;
471
+
472
+  if (height == pFrame->height && width == pFrame->width &&
473
+      channels == pFrame->channels && maxval == pFrame->maxval)
474
+    return;
475
+
476
+  // get number of pixels to skip / to leave empty in X and Y direction
477
+  if (height > pFrame->height) {
478
+    emptyY = (height - pFrame->height) / 2;
479
+    skipY = 0;
480
+  } else {
481
+    emptyY = 0;
482
+    skipY = (pFrame->height - height) / 2;
483
+  }
484
+  if (width > pFrame->width) {
485
+    emptyX = (width - pFrame->width) / 2;
486
+    skipX = 0;
487
+  } else {
488
+    emptyX = 0;
489
+    skipX = (pFrame->width - width) / 2;
490
+  }
491
+
492
+  // resize frame with help of calculated parameters
493
+  BlinkenFramePadCrop(pFrame, height, width, channels, maxval,
494
+                      emptyY, emptyX, skipY, skipX);
495
+}
496
+
497
+void BlinkenFrameCrop(stBlinkenFrame *pFrame, int top, int left,
498
+                      int height, int width)
499
+{
500
+  if (pFrame == NULL)
501
+    return;
502
+
503
+  if (top < 0)
504
+    top = 0;
505
+  if (top > pFrame->height - BlinkenHeightMin)
506
+    top = pFrame->height - BlinkenHeightMin;
507
+  if (height < BlinkenHeightMin)
508
+    height = BlinkenHeightMin;
509
+  if (height > pFrame->height - top)
510
+    height = pFrame->height - top;
511
+  if (left < 0)
512
+    left = 0;
513
+  if (left > pFrame->width - BlinkenWidthMin)
514
+    left = pFrame->width - BlinkenWidthMin;
515
+  if (width < BlinkenWidthMin)
516
+    width = BlinkenWidthMin;
517
+  if (width > pFrame->width - left)
518
+    width = pFrame->width - left;
519
+
520
+  if (top == 0 && left == 0 &&
521
+      height == pFrame->height && width == pFrame->width)
522
+    return;
523
+
524
+  // crop frame with help of calculated parameters
525
+  BlinkenFramePadCrop(pFrame, height, width, pFrame->channels, pFrame->maxval,
526
+                      0, 0, top, left);
527
+}
528
+
447 529
 void BlinkenFrameScale(stBlinkenFrame *pFrame, int height, int width)
448 530
 {
449 531
   unsigned char **ppData;
... ...
@@ -48,6 +48,8 @@ int BlinkenFrameCompare(stBlinkenFrame *pFrame1, stBlinkenFrame *pFrame2);
48 48
 
49 49
 void BlinkenFrameResize(stBlinkenFrame *pFrame, int height, int width,
50 50
                         int channels, int maxval);
51
+void BlinkenFrameCrop(stBlinkenFrame *pFrame, int top, int left,
52
+                      int height, int width);
51 53
 void BlinkenFrameScale(stBlinkenFrame *pFrame, int height, int width);
52 54
 void BlinkenFrameColorize(stBlinkenFrame *pFrame, int channels, int mode,
53 55
                           int step);
... ...
@@ -567,6 +567,42 @@ void BlinkenMovieResize(stBlinkenMovie *pMovie, int height, int width,
567 567
     BlinkenFrameResize(pMovie->ppFrames[i], height, width, channels, maxval);
568 568
 }
569 569
 
570
+void BlinkenMovieCrop(stBlinkenMovie *pMovie, int top, int left,
571
+                      int height, int width)
572
+{
573
+  int i;
574
+
575
+  if (pMovie == NULL)
576
+    return;
577
+
578
+  if (top < 0)
579
+    top = 0;
580
+  if (top > pMovie->height - BlinkenHeightMin)
581
+    top = pMovie->height - BlinkenHeightMin;
582
+  if (height < BlinkenHeightMin)
583
+    height = BlinkenHeightMin;
584
+  if (height > pMovie->height - top)
585
+    height = pMovie->height - top;
586
+  if (left < 0)
587
+    left = 0;
588
+  if (left > pMovie->width - BlinkenWidthMin)
589
+    left = pMovie->width - BlinkenWidthMin;
590
+  if (width < BlinkenWidthMin)
591
+    width = BlinkenWidthMin;
592
+  if (width > pMovie->width - left)
593
+    width = pMovie->width - left;
594
+
595
+  if (top == 0 && left == 0 &&
596
+      height == pMovie->height && width == pMovie->width)
597
+    return;
598
+
599
+  pMovie->height = height;
600
+  pMovie->width = width;
601
+
602
+  for (i = 0; i < pMovie->frameCnt; i++)
603
+    BlinkenFrameCrop(pMovie->ppFrames[i], top, left, height, width);
604
+}
605
+
570 606
 void BlinkenMovieScale(stBlinkenMovie *pMovie, int height, int width)
571 607
 {
572 608
   int i;
... ...
@@ -63,6 +63,8 @@ void BlinkenMovieReverse(stBlinkenMovie *pMovie);
63 63
 
64 64
 void BlinkenMovieResize(stBlinkenMovie *pMovie, int height, int width,
65 65
                         int channels, int maxval);
66
+void BlinkenMovieCrop(stBlinkenMovie *pMovie, int top, int left,
67
+                      int height, int width);
66 68
 void BlinkenMovieScale(stBlinkenMovie *pMovie, int height, int width);
67 69
 void BlinkenMovieColorize(stBlinkenMovie *pMovie, int channels, int mode);
68 70
 void BlinkenMovieCopyRect(stBlinkenMovie *pDest, int destY, int destX,
69 71