You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.9KB

  1. /*
  2. * This file is part of Libav.
  3. *
  4. * Libav is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * Libav is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with Libav; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <errno.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #define SCALEBITS 8
  23. #define ONE_HALF (1 << (SCALEBITS - 1))
  24. #define FIX(x) ((int) ((x) * (1L << SCALEBITS) + 0.5))
  25. #define err_if(expr) do { \
  26. if (expr) { \
  27. fprintf(stderr, "%s\n", strerror(errno)); \
  28. exit(1); \
  29. } \
  30. } while (0)
  31. static void rgb24_to_yuv420p(unsigned char *lum, unsigned char *cb,
  32. unsigned char *cr, unsigned char *src,
  33. int width, int height)
  34. {
  35. int wrap, wrap3, x, y;
  36. int r, g, b, r1, g1, b1;
  37. unsigned char *p;
  38. wrap = width;
  39. wrap3 = width * 3;
  40. p = src;
  41. for (y = 0; y < height; y += 2) {
  42. for (x = 0; x < width; x += 2) {
  43. r = p[0];
  44. g = p[1];
  45. b = p[2];
  46. r1 = r;
  47. g1 = g;
  48. b1 = b;
  49. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  50. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  51. r = p[3];
  52. g = p[4];
  53. b = p[5];
  54. r1 += r;
  55. g1 += g;
  56. b1 += b;
  57. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  58. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  59. p += wrap3;
  60. lum += wrap;
  61. r = p[0];
  62. g = p[1];
  63. b = p[2];
  64. r1 += r;
  65. g1 += g;
  66. b1 += b;
  67. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  68. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  69. r = p[3];
  70. g = p[4];
  71. b = p[5];
  72. r1 += r;
  73. g1 += g;
  74. b1 += b;
  75. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  76. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  77. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  78. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  79. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  80. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  81. cb++;
  82. cr++;
  83. p += -wrap3 + 2 * 3;
  84. lum += -wrap + 2;
  85. }
  86. p += wrap3;
  87. lum += wrap;
  88. }
  89. }
  90. /* cif format */
  91. #define DEFAULT_WIDTH 352
  92. #define DEFAULT_HEIGHT 288
  93. #define DEFAULT_NB_PICT 50
  94. static void pgmyuv_save(const char *filename, int w, int h,
  95. unsigned char *rgb_tab)
  96. {
  97. FILE *f;
  98. int i, h2, w2;
  99. unsigned char *cb, *cr;
  100. unsigned char *lum_tab, *cb_tab, *cr_tab;
  101. lum_tab = malloc(w * h);
  102. cb_tab = malloc(w * h / 4);
  103. cr_tab = malloc(w * h / 4);
  104. rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
  105. if (filename) {
  106. f = fopen(filename, "wb");
  107. fprintf(f, "P5\n%d %d\n%d\n", w, h * 3 / 2, 255);
  108. } else {
  109. f = stdout;
  110. }
  111. err_if(fwrite(lum_tab, 1, w * h, f) != w * h);
  112. h2 = h / 2;
  113. w2 = w / 2;
  114. cb = cb_tab;
  115. cr = cr_tab;
  116. if (filename) {
  117. for (i = 0; i < h2; i++) {
  118. err_if(fwrite(cb, 1, w2, f) != w2);
  119. err_if(fwrite(cr, 1, w2, f) != w2);
  120. cb += w2;
  121. cr += w2;
  122. }
  123. fclose(f);
  124. } else {
  125. for (i = 0; i < h2; i++) {
  126. err_if(fwrite(cb, 1, w2, f) != w2);
  127. cb += w2;
  128. }
  129. for (i = 0; i < h2; i++) {
  130. err_if(fwrite(cr, 1, w2, f) != w2);
  131. cr += w2;
  132. }
  133. }
  134. free(lum_tab);
  135. free(cb_tab);
  136. free(cr_tab);
  137. }
  138. static unsigned char *rgb_tab;
  139. static int width, height, wrap;
  140. static void put_pixel(int x, int y, int r, int g, int b)
  141. {
  142. unsigned char *p;
  143. if (x < 0 || x >= width ||
  144. y < 0 || y >= height)
  145. return;
  146. p = rgb_tab + y * wrap + x * 3;
  147. p[0] = r;
  148. p[1] = g;
  149. p[2] = b;
  150. }