transform.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (C) 2010 Georg Martius <georg.martius@web.de>
  3. * Copyright (C) 2010 Daniel G. Taylor <dan@programmer-art.org>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * transform input video
  24. */
  25. #include "libavutil/common.h"
  26. #include "libavutil/avassert.h"
  27. #include "transform.h"
  28. #define INTERPOLATE_METHOD(name) \
  29. static uint8_t name(float x, float y, const uint8_t *src, \
  30. int width, int height, int stride, uint8_t def)
  31. #define PIXEL(img, x, y, w, h, stride, def) \
  32. ((x) < 0 || (y) < 0) ? (def) : \
  33. (((x) >= (w) || (y) >= (h)) ? (def) : \
  34. img[(x) + (y) * (stride)])
  35. /**
  36. * Nearest neighbor interpolation
  37. */
  38. INTERPOLATE_METHOD(interpolate_nearest)
  39. {
  40. return PIXEL(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def);
  41. }
  42. /**
  43. * Bilinear interpolation
  44. */
  45. INTERPOLATE_METHOD(interpolate_bilinear)
  46. {
  47. int x_c, x_f, y_c, y_f;
  48. int v1, v2, v3, v4;
  49. if (x < -1 || x > width || y < -1 || y > height) {
  50. return def;
  51. } else {
  52. x_f = (int)x;
  53. x_c = x_f + 1;
  54. y_f = (int)y;
  55. y_c = y_f + 1;
  56. v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
  57. v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
  58. v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
  59. v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
  60. return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) +
  61. v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
  62. }
  63. }
  64. /**
  65. * Biquadratic interpolation
  66. */
  67. INTERPOLATE_METHOD(interpolate_biquadratic)
  68. {
  69. int x_c, x_f, y_c, y_f;
  70. uint8_t v1, v2, v3, v4;
  71. float f1, f2, f3, f4;
  72. if (x < - 1 || x > width || y < -1 || y > height)
  73. return def;
  74. else {
  75. x_f = (int)x;
  76. x_c = x_f + 1;
  77. y_f = (int)y;
  78. y_c = y_f + 1;
  79. v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
  80. v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
  81. v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
  82. v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
  83. f1 = 1 - sqrt((x_c - x) * (y_c - y));
  84. f2 = 1 - sqrt((x_c - x) * (y - y_f));
  85. f3 = 1 - sqrt((x - x_f) * (y_c - y));
  86. f4 = 1 - sqrt((x - x_f) * (y - y_f));
  87. return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4);
  88. }
  89. }
  90. void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) {
  91. matrix[0] = zoom * cos(angle);
  92. matrix[1] = -sin(angle);
  93. matrix[2] = x_shift;
  94. matrix[3] = -matrix[1];
  95. matrix[4] = matrix[0];
  96. matrix[5] = y_shift;
  97. matrix[6] = 0;
  98. matrix[7] = 0;
  99. matrix[8] = 1;
  100. }
  101. void avfilter_add_matrix(const float *m1, const float *m2, float *result)
  102. {
  103. int i;
  104. for (i = 0; i < 9; i++)
  105. result[i] = m1[i] + m2[i];
  106. }
  107. void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
  108. {
  109. int i;
  110. for (i = 0; i < 9; i++)
  111. result[i] = m1[i] - m2[i];
  112. }
  113. void avfilter_mul_matrix(const float *m1, float scalar, float *result)
  114. {
  115. int i;
  116. for (i = 0; i < 9; i++)
  117. result[i] = m1[i] * scalar;
  118. }
  119. int avfilter_transform(const uint8_t *src, uint8_t *dst,
  120. int src_stride, int dst_stride,
  121. int width, int height, const float *matrix,
  122. enum InterpolateMethod interpolate,
  123. enum FillMethod fill)
  124. {
  125. int x, y;
  126. float x_s, y_s;
  127. uint8_t def = 0;
  128. uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
  129. switch(interpolate) {
  130. case INTERPOLATE_NEAREST:
  131. func = interpolate_nearest;
  132. break;
  133. case INTERPOLATE_BILINEAR:
  134. func = interpolate_bilinear;
  135. break;
  136. case INTERPOLATE_BIQUADRATIC:
  137. func = interpolate_biquadratic;
  138. break;
  139. default:
  140. return AVERROR(EINVAL);
  141. }
  142. for (y = 0; y < height; y++) {
  143. for(x = 0; x < width; x++) {
  144. x_s = x * matrix[0] + y * matrix[1] + matrix[2];
  145. y_s = x * matrix[3] + y * matrix[4] + matrix[5];
  146. switch(fill) {
  147. case FILL_ORIGINAL:
  148. def = src[y * src_stride + x];
  149. break;
  150. case FILL_CLAMP:
  151. y_s = av_clipf(y_s, 0, height - 1);
  152. x_s = av_clipf(x_s, 0, width - 1);
  153. def = src[(int)y_s * src_stride + (int)x_s];
  154. break;
  155. case FILL_MIRROR:
  156. x_s = avpriv_mirror(x_s, width-1);
  157. y_s = avpriv_mirror(y_s, height-1);
  158. av_assert2(x_s >= 0 && y_s >= 0);
  159. av_assert2(x_s < width && y_s < height);
  160. def = src[(int)y_s * src_stride + (int)x_s];
  161. }
  162. dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
  163. }
  164. }
  165. return 0;
  166. }