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.

199 lines
5.6KB

  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 ff_get_matrix(
  91. float x_shift,
  92. float y_shift,
  93. float angle,
  94. float scale_x,
  95. float scale_y,
  96. float *matrix
  97. ) {
  98. matrix[0] = scale_x * cos(angle);
  99. matrix[1] = -sin(angle);
  100. matrix[2] = x_shift;
  101. matrix[3] = -matrix[1];
  102. matrix[4] = scale_y * cos(angle);
  103. matrix[5] = y_shift;
  104. matrix[6] = 0;
  105. matrix[7] = 0;
  106. matrix[8] = 1;
  107. }
  108. void avfilter_add_matrix(const float *m1, const float *m2, float *result)
  109. {
  110. int i;
  111. for (i = 0; i < 9; i++)
  112. result[i] = m1[i] + m2[i];
  113. }
  114. void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
  115. {
  116. int i;
  117. for (i = 0; i < 9; i++)
  118. result[i] = m1[i] - m2[i];
  119. }
  120. void avfilter_mul_matrix(const float *m1, float scalar, float *result)
  121. {
  122. int i;
  123. for (i = 0; i < 9; i++)
  124. result[i] = m1[i] * scalar;
  125. }
  126. int avfilter_transform(const uint8_t *src, uint8_t *dst,
  127. int src_stride, int dst_stride,
  128. int width, int height, const float *matrix,
  129. enum InterpolateMethod interpolate,
  130. enum FillMethod fill)
  131. {
  132. int x, y;
  133. float x_s, y_s;
  134. uint8_t def = 0;
  135. uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
  136. switch(interpolate) {
  137. case INTERPOLATE_NEAREST:
  138. func = interpolate_nearest;
  139. break;
  140. case INTERPOLATE_BILINEAR:
  141. func = interpolate_bilinear;
  142. break;
  143. case INTERPOLATE_BIQUADRATIC:
  144. func = interpolate_biquadratic;
  145. break;
  146. default:
  147. return AVERROR(EINVAL);
  148. }
  149. for (y = 0; y < height; y++) {
  150. for(x = 0; x < width; x++) {
  151. x_s = x * matrix[0] + y * matrix[1] + matrix[2];
  152. y_s = x * matrix[3] + y * matrix[4] + matrix[5];
  153. switch(fill) {
  154. case FILL_ORIGINAL:
  155. def = src[y * src_stride + x];
  156. break;
  157. case FILL_CLAMP:
  158. y_s = av_clipf(y_s, 0, height - 1);
  159. x_s = av_clipf(x_s, 0, width - 1);
  160. def = src[(int)y_s * src_stride + (int)x_s];
  161. break;
  162. case FILL_MIRROR:
  163. x_s = avpriv_mirror(x_s, width-1);
  164. y_s = avpriv_mirror(y_s, height-1);
  165. av_assert2(x_s >= 0 && y_s >= 0);
  166. av_assert2(x_s < width && y_s < height);
  167. def = src[(int)y_s * src_stride + (int)x_s];
  168. }
  169. dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
  170. }
  171. }
  172. return 0;
  173. }