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 |