deinterlace.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdint.h>
  5. #include <errno.h>
  6. #include <assert.h>
  7. #include <getopt.h>
  8. #define IPE_DEFAULT_WIDTH 2048
  9. char *strdup(const char *str)
  10. {
  11. int n = strlen(str) + 1;
  12. char *dup = malloc(n);
  13. if (dup)
  14. strcpy(dup, str);
  15. return dup;
  16. }
  17. int process_simple_frame(const uint16_t *frame_in, uint16_t *frame_out, int width, int height)
  18. {
  19. const size_t row_size_bytes = width * sizeof(uint16_t);
  20. for (int row = 0; row < height; row++) {
  21. /* Copy one line */
  22. memcpy(frame_out, frame_in + row*width, row_size_bytes);
  23. frame_out += width;
  24. /* Interpolate between source row and row+1 */
  25. for (int x = 0; x < width; x++) {
  26. frame_out[x] = (int) (0.5 * frame_in[row*width + x] + 0.5 * frame_in[(row+1)*width + x]);
  27. }
  28. frame_out += width;
  29. }
  30. /* Copy last row */
  31. memcpy(frame_out, frame_in + width * (height - 1), row_size_bytes);
  32. return 0;
  33. }
  34. int weave(const uint16_t *frames_in, uint16_t *frame_out, int width, int height)
  35. {
  36. const size_t row_size_bytes = width * sizeof(uint16_t);
  37. const size_t frame_offset = width * height;
  38. for (int row = 0; row < height; row++) {
  39. memcpy(frame_out, frames_in + row*width, row_size_bytes);
  40. frame_out += width;
  41. memcpy(frame_out, frames_in + frame_offset + row*width, row_size_bytes);
  42. frame_out += width;
  43. }
  44. return 0;
  45. }
  46. int process_file(const char *filename, int width, int height, int num_lines_skipped)
  47. {
  48. FILE *fp = fopen(filename, "rb");
  49. if (fp == NULL) {
  50. return EIO;
  51. }
  52. fseek(fp, 0, SEEK_END);
  53. const size_t file_size = ftell(fp);
  54. rewind(fp);
  55. uint16_t *frame_in_buffer = (uint16_t *) malloc(file_size);
  56. if (frame_in_buffer == NULL) {
  57. fclose(fp);
  58. return ENOMEM;
  59. }
  60. size_t buffer_length = fread(frame_in_buffer, 1, file_size, fp);
  61. fclose(fp);
  62. if (buffer_length != file_size) {
  63. free(frame_in_buffer);
  64. return EIO;
  65. }
  66. uint16_t *frame_out_buffer = (uint16_t *) malloc(file_size * 2);
  67. if (frame_out_buffer == NULL) {
  68. fclose(fp);
  69. return ENOMEM;
  70. }
  71. const int num_frames = file_size / (width * height * sizeof(uint16_t));
  72. printf("de-interlacing %i frames...\n", num_frames);
  73. /*
  74. for (int frame = 0; frame < num_frames; frame++) {
  75. process_simple_frame(
  76. frame_in_buffer + frame * (width * height),
  77. frame_out_buffer + frame * (width * height * 2),
  78. width, height);
  79. }
  80. */
  81. for (int frame = 0; frame < num_frames-1; frame++) {
  82. weave(frame_in_buffer + frame * (width * height),
  83. frame_out_buffer + frame * (width * height * 2),
  84. width, height);
  85. }
  86. fp = fopen("result.raw", "wb");
  87. fwrite(frame_out_buffer, 1, file_size * 2, fp);
  88. fclose(fp);
  89. free(frame_in_buffer);
  90. free(frame_out_buffer);
  91. return 0;
  92. }
  93. int main(int argc, char const* argv[])
  94. {
  95. static struct option long_options[] = {
  96. { "width", 1, 0, 'w' },
  97. { "interlaced-height", 1, 0, 'i' },
  98. { "target-height", 1, 0, 't' },
  99. { "file", 1, 0, 'f' },
  100. { NULL, 0, NULL, 0 }
  101. };
  102. int c, option_index = 0, errnum;
  103. int width = IPE_DEFAULT_WIDTH;
  104. int interlaced_height = -1;
  105. int target_height = -1;
  106. char *file_name = NULL;
  107. char *end;
  108. while ((c = getopt_long(argc, (char *const *) argv, "w:i:t:f:", long_options, &option_index)) != -1) {
  109. switch (c) {
  110. case 'w':
  111. width = (int) strtol(optarg, &end, 10);
  112. break;
  113. case 'i':
  114. interlaced_height = (int) strtol(optarg, &end, 10);
  115. break;
  116. case 't':
  117. target_height = (int) strtol(optarg, &end, 10);
  118. break;
  119. case 'f':
  120. file_name = strdup( (char *) optarg);
  121. break;
  122. }
  123. }
  124. if (interlaced_height == -1 || file_name == NULL) {
  125. printf("Usage: deinterlace --interlaced-height=[number] --target-height=[number] --file=[name]\n");
  126. exit(EXIT_FAILURE);
  127. }
  128. if (target_height == -1)
  129. target_height = interlaced_height * 2;
  130. if ((errnum = process_file(file_name, width, interlaced_height, (target_height / interlaced_height) - 1)))
  131. printf("Error occured: %s\n", strerror(errnum));
  132. free(file_name);
  133. return 0;
  134. }