react-native-vision-camera-spoof-detector 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.gitattributes +2 -0
  2. package/.gitignore +27 -0
  3. package/CHANGELOG.md +2 -2
  4. package/CONTRIBUTING.md +2 -2
  5. package/README.md +442 -443
  6. package/android/build.gradle +12 -4
  7. package/android/src/main/cpp/CMakeLists.txt +101 -94
  8. package/android/src/main/cpp/libyuv/.clang-format +6 -6
  9. package/android/src/main/cpp/libyuv/.gn +40 -40
  10. package/android/src/main/cpp/libyuv/.vpython3 +410 -410
  11. package/android/src/main/cpp/libyuv/AUTHORS +7 -7
  12. package/android/src/main/cpp/libyuv/Android.bp +202 -202
  13. package/android/src/main/cpp/libyuv/Android.mk +106 -106
  14. package/android/src/main/cpp/libyuv/BUILD.gn +490 -490
  15. package/android/src/main/cpp/libyuv/CM_linux_packages.cmake +70 -70
  16. package/android/src/main/cpp/libyuv/CMakeLists.txt +259 -252
  17. package/android/src/main/cpp/libyuv/DEPS +935 -935
  18. package/android/src/main/cpp/libyuv/DIR_METADATA +3 -3
  19. package/android/src/main/cpp/libyuv/LICENSE +29 -29
  20. package/android/src/main/cpp/libyuv/OWNERS +11 -11
  21. package/android/src/main/cpp/libyuv/PATENTS +23 -23
  22. package/android/src/main/cpp/libyuv/PRESUBMIT.py +65 -65
  23. package/android/src/main/cpp/libyuv/README.chromium +11 -11
  24. package/android/src/main/cpp/libyuv/README.md +19 -19
  25. package/android/src/main/cpp/libyuv/build_overrides/build.gni +60 -60
  26. package/android/src/main/cpp/libyuv/build_overrides/gtest.gni +19 -19
  27. package/android/src/main/cpp/libyuv/build_overrides/partition_alloc.gni +17 -17
  28. package/android/src/main/cpp/libyuv/codereview.settings +5 -5
  29. package/android/src/main/cpp/libyuv/docs/deprecated_builds.md +409 -409
  30. package/android/src/main/cpp/libyuv/docs/environment_variables.md +64 -64
  31. package/android/src/main/cpp/libyuv/docs/feature_detection.md +108 -108
  32. package/android/src/main/cpp/libyuv/docs/filtering.md +196 -196
  33. package/android/src/main/cpp/libyuv/docs/formats.md +208 -208
  34. package/android/src/main/cpp/libyuv/docs/getting_started.md +296 -296
  35. package/android/src/main/cpp/libyuv/docs/rotation.md +107 -107
  36. package/android/src/main/cpp/libyuv/download_vs_toolchain.py +29 -29
  37. package/android/src/main/cpp/libyuv/include/libyuv/basic_types.h +68 -68
  38. package/android/src/main/cpp/libyuv/include/libyuv/compare.h +111 -111
  39. package/android/src/main/cpp/libyuv/include/libyuv/compare_row.h +112 -112
  40. package/android/src/main/cpp/libyuv/include/libyuv/convert.h +1117 -1117
  41. package/android/src/main/cpp/libyuv/include/libyuv/convert_argb.h +2335 -2335
  42. package/android/src/main/cpp/libyuv/include/libyuv/convert_from.h +203 -203
  43. package/android/src/main/cpp/libyuv/include/libyuv/convert_from_argb.h +394 -394
  44. package/android/src/main/cpp/libyuv/include/libyuv/cpu_id.h +147 -147
  45. package/android/src/main/cpp/libyuv/include/libyuv/cpu_support.h +99 -99
  46. package/android/src/main/cpp/libyuv/include/libyuv/loongson_intrinsics.h +1949 -1949
  47. package/android/src/main/cpp/libyuv/include/libyuv/mjpeg_decoder.h +195 -195
  48. package/android/src/main/cpp/libyuv/include/libyuv/planar_functions.h +1131 -1131
  49. package/android/src/main/cpp/libyuv/include/libyuv/rotate.h +296 -296
  50. package/android/src/main/cpp/libyuv/include/libyuv/rotate_argb.h +37 -37
  51. package/android/src/main/cpp/libyuv/include/libyuv/rotate_row.h +265 -265
  52. package/android/src/main/cpp/libyuv/include/libyuv/row.h +6738 -6738
  53. package/android/src/main/cpp/libyuv/include/libyuv/row_sve.h +2154 -2154
  54. package/android/src/main/cpp/libyuv/include/libyuv/scale.h +336 -336
  55. package/android/src/main/cpp/libyuv/include/libyuv/scale_argb.h +76 -76
  56. package/android/src/main/cpp/libyuv/include/libyuv/scale_rgb.h +42 -42
  57. package/android/src/main/cpp/libyuv/include/libyuv/scale_row.h +1726 -1726
  58. package/android/src/main/cpp/libyuv/include/libyuv/scale_uv.h +51 -51
  59. package/android/src/main/cpp/libyuv/include/libyuv/version.h +16 -16
  60. package/android/src/main/cpp/libyuv/include/libyuv/video_common.h +222 -222
  61. package/android/src/main/cpp/libyuv/include/libyuv.h +33 -33
  62. package/android/src/main/cpp/libyuv/infra/config/OWNERS +3 -3
  63. package/android/src/main/cpp/libyuv/infra/config/PRESUBMIT.py +17 -17
  64. package/android/src/main/cpp/libyuv/infra/config/README.md +2 -2
  65. package/android/src/main/cpp/libyuv/infra/config/codereview.settings +6 -6
  66. package/android/src/main/cpp/libyuv/infra/config/commit-queue.cfg +144 -144
  67. package/android/src/main/cpp/libyuv/infra/config/cr-buildbucket.cfg +1185 -1185
  68. package/android/src/main/cpp/libyuv/infra/config/luci-logdog.cfg +9 -9
  69. package/android/src/main/cpp/libyuv/infra/config/luci-milo.cfg +246 -246
  70. package/android/src/main/cpp/libyuv/infra/config/luci-scheduler.cfg +385 -385
  71. package/android/src/main/cpp/libyuv/infra/config/main.star +402 -402
  72. package/android/src/main/cpp/libyuv/infra/config/project.cfg +16 -16
  73. package/android/src/main/cpp/libyuv/infra/config/realms.cfg +111 -111
  74. package/android/src/main/cpp/libyuv/libyuv.gni +34 -34
  75. package/android/src/main/cpp/libyuv/libyuv.gyp +149 -149
  76. package/android/src/main/cpp/libyuv/libyuv.gypi +87 -87
  77. package/android/src/main/cpp/libyuv/linux.mk +96 -96
  78. package/android/src/main/cpp/libyuv/public.mk +13 -13
  79. package/android/src/main/cpp/libyuv/pylintrc +49 -49
  80. package/android/src/main/cpp/libyuv/riscv_script/prepare_toolchain_qemu.sh +74 -74
  81. package/android/src/main/cpp/libyuv/riscv_script/riscv-clang.cmake +56 -56
  82. package/android/src/main/cpp/libyuv/riscv_script/run_qemu.sh +15 -15
  83. package/android/src/main/cpp/libyuv/source/compare.cc +435 -435
  84. package/android/src/main/cpp/libyuv/source/compare_common.cc +74 -74
  85. package/android/src/main/cpp/libyuv/source/compare_gcc.cc +362 -362
  86. package/android/src/main/cpp/libyuv/source/compare_neon.cc +96 -96
  87. package/android/src/main/cpp/libyuv/source/compare_neon64.cc +223 -223
  88. package/android/src/main/cpp/libyuv/source/compare_win.cc +241 -241
  89. package/android/src/main/cpp/libyuv/source/convert.cc +4746 -4746
  90. package/android/src/main/cpp/libyuv/source/convert_argb.cc +9179 -9179
  91. package/android/src/main/cpp/libyuv/source/convert_from.cc +866 -866
  92. package/android/src/main/cpp/libyuv/source/convert_from_argb.cc +3671 -3671
  93. package/android/src/main/cpp/libyuv/source/convert_jpeg.cc +602 -602
  94. package/android/src/main/cpp/libyuv/source/convert_to_argb.cc +391 -391
  95. package/android/src/main/cpp/libyuv/source/convert_to_i420.cc +288 -288
  96. package/android/src/main/cpp/libyuv/source/cpu_id.cc +496 -496
  97. package/android/src/main/cpp/libyuv/source/mjpeg_decoder.cc +580 -580
  98. package/android/src/main/cpp/libyuv/source/mjpeg_validate.cc +71 -71
  99. package/android/src/main/cpp/libyuv/source/planar_functions.cc +5663 -5663
  100. package/android/src/main/cpp/libyuv/source/rotate.cc +1241 -1241
  101. package/android/src/main/cpp/libyuv/source/rotate_any.cc +76 -76
  102. package/android/src/main/cpp/libyuv/source/rotate_argb.cc +259 -259
  103. package/android/src/main/cpp/libyuv/source/rotate_common.cc +208 -208
  104. package/android/src/main/cpp/libyuv/source/rotate_gcc.cc +505 -505
  105. package/android/src/main/cpp/libyuv/source/rotate_lsx.cc +233 -233
  106. package/android/src/main/cpp/libyuv/source/rotate_neon.cc +219 -219
  107. package/android/src/main/cpp/libyuv/source/rotate_neon64.cc +273 -273
  108. package/android/src/main/cpp/libyuv/source/rotate_sme.cc +174 -174
  109. package/android/src/main/cpp/libyuv/source/rotate_win.cc +253 -253
  110. package/android/src/main/cpp/libyuv/source/row_any.cc +2519 -2519
  111. package/android/src/main/cpp/libyuv/source/row_common.cc +4461 -4461
  112. package/android/src/main/cpp/libyuv/source/row_gcc.cc +9570 -9570
  113. package/android/src/main/cpp/libyuv/source/row_lasx.cc +2343 -2343
  114. package/android/src/main/cpp/libyuv/source/row_lsx.cc +3030 -3030
  115. package/android/src/main/cpp/libyuv/source/row_neon.cc +4026 -4026
  116. package/android/src/main/cpp/libyuv/source/row_neon64.cc +5617 -5617
  117. package/android/src/main/cpp/libyuv/source/row_rvv.cc +2599 -2599
  118. package/android/src/main/cpp/libyuv/source/row_sme.cc +1183 -1183
  119. package/android/src/main/cpp/libyuv/source/row_sve.cc +1088 -1088
  120. package/android/src/main/cpp/libyuv/source/row_win.cc +6453 -6453
  121. package/android/src/main/cpp/libyuv/source/scale.cc +2710 -2710
  122. package/android/src/main/cpp/libyuv/source/scale_any.cc +991 -991
  123. package/android/src/main/cpp/libyuv/source/scale_argb.cc +1158 -1158
  124. package/android/src/main/cpp/libyuv/source/scale_common.cc +1977 -1977
  125. package/android/src/main/cpp/libyuv/source/scale_gcc.cc +2947 -2947
  126. package/android/src/main/cpp/libyuv/source/scale_lsx.cc +739 -739
  127. package/android/src/main/cpp/libyuv/source/scale_neon.cc +1449 -1449
  128. package/android/src/main/cpp/libyuv/source/scale_neon64.cc +1552 -1552
  129. package/android/src/main/cpp/libyuv/source/scale_rgb.cc +82 -82
  130. package/android/src/main/cpp/libyuv/source/scale_rvv.cc +1971 -1971
  131. package/android/src/main/cpp/libyuv/source/scale_sme.cc +555 -555
  132. package/android/src/main/cpp/libyuv/source/scale_uv.cc +1159 -1159
  133. package/android/src/main/cpp/libyuv/source/scale_win.cc +1392 -1392
  134. package/android/src/main/cpp/libyuv/source/test.sh +35 -35
  135. package/android/src/main/cpp/libyuv/source/video_common.cc +62 -62
  136. package/android/src/main/cpp/libyuv/tools_libyuv/OWNERS +4 -4
  137. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/roll_deps.py +931 -931
  138. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/roll_deps_test.py +164 -164
  139. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS +21 -21
  140. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.new +13 -13
  141. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old +13 -13
  142. package/android/src/main/cpp/libyuv/tools_libyuv/get_landmines.py +38 -38
  143. package/android/src/main/cpp/libyuv/tools_libyuv/msan/OWNERS +3 -3
  144. package/android/src/main/cpp/libyuv/tools_libyuv/msan/blacklist.txt +9 -9
  145. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/OWNERS +3 -3
  146. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/blacklist.txt +15 -15
  147. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/vptr_blacklist.txt +25 -25
  148. package/android/src/main/cpp/libyuv/unit_test/basictypes_test.cc +43 -43
  149. package/android/src/main/cpp/libyuv/unit_test/color_test.cc +848 -848
  150. package/android/src/main/cpp/libyuv/unit_test/compare_test.cc +739 -739
  151. package/android/src/main/cpp/libyuv/unit_test/convert_argb_test.cc +2867 -2867
  152. package/android/src/main/cpp/libyuv/unit_test/convert_test.cc +2133 -2133
  153. package/android/src/main/cpp/libyuv/unit_test/cpu_test.cc +427 -427
  154. package/android/src/main/cpp/libyuv/unit_test/cpu_thread_test.cc +63 -63
  155. package/android/src/main/cpp/libyuv/unit_test/math_test.cc +160 -160
  156. package/android/src/main/cpp/libyuv/unit_test/planar_test.cc +4731 -4731
  157. package/android/src/main/cpp/libyuv/unit_test/rotate_argb_test.cc +334 -334
  158. package/android/src/main/cpp/libyuv/unit_test/rotate_test.cc +962 -962
  159. package/android/src/main/cpp/libyuv/unit_test/scale_argb_test.cc +590 -590
  160. package/android/src/main/cpp/libyuv/unit_test/scale_plane_test.cc +465 -465
  161. package/android/src/main/cpp/libyuv/unit_test/scale_rgb_test.cc +280 -280
  162. package/android/src/main/cpp/libyuv/unit_test/scale_test.cc +1135 -1135
  163. package/android/src/main/cpp/libyuv/unit_test/scale_uv_test.cc +249 -249
  164. package/android/src/main/cpp/libyuv/unit_test/testdata/arm_v7.txt +12 -12
  165. package/android/src/main/cpp/libyuv/unit_test/testdata/mips.txt +7 -7
  166. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson2k.txt +5 -5
  167. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson3.txt +10 -10
  168. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson_mmi.txt +7 -7
  169. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64.txt +3 -3
  170. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv.txt +3 -3
  171. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv_zvfh.txt +3 -3
  172. package/android/src/main/cpp/libyuv/unit_test/testdata/tegra3.txt +23 -23
  173. package/android/src/main/cpp/libyuv/unit_test/unit_test.cc +581 -581
  174. package/android/src/main/cpp/libyuv/unit_test/unit_test.h +232 -232
  175. package/android/src/main/cpp/libyuv/unit_test/video_common_test.cc +112 -112
  176. package/android/src/main/cpp/libyuv/util/Makefile +9 -9
  177. package/android/src/main/cpp/libyuv/util/color.cc +120 -120
  178. package/android/src/main/cpp/libyuv/util/compare.cc +67 -67
  179. package/android/src/main/cpp/libyuv/util/cpuid.c +211 -211
  180. package/android/src/main/cpp/libyuv/util/i444tonv12_eg.cc +27 -27
  181. package/android/src/main/cpp/libyuv/util/psnr.cc +291 -291
  182. package/android/src/main/cpp/libyuv/util/psnr.h +47 -47
  183. package/android/src/main/cpp/libyuv/util/psnr_main.cc +620 -620
  184. package/android/src/main/cpp/libyuv/util/ssim.cc +364 -364
  185. package/android/src/main/cpp/libyuv/util/ssim.h +38 -38
  186. package/android/src/main/cpp/libyuv/util/yuvconstants.c +114 -114
  187. package/android/src/main/cpp/libyuv/util/yuvconvert.cc +367 -367
  188. package/android/src/main/cpp/libyuv/winarm.mk +47 -47
  189. package/package.json +86 -84
  190. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  191. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  192. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  193. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  194. package/android/.gradle/8.9/gc.properties +0 -0
  195. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  196. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  197. package/android/.gradle/vcs-1/gc.properties +0 -0
@@ -1,196 +1,196 @@
1
- # Introduction
2
-
3
- This document discusses the current state of filtering in libyuv. An emphasis on maximum performance while avoiding memory exceptions, and minimal amount of code/complexity. See future work at end.
4
-
5
- # LibYuv Filter Subsampling
6
-
7
- There are 2 challenges with subsampling
8
-
9
- 1. centering of samples, which involves clamping on edges
10
- 2. clipping a source region
11
-
12
- Centering depends on scale factor and filter mode.
13
-
14
- # Down Sampling
15
-
16
- If scaling down, the stepping rate is always src_width / dst_width.
17
-
18
- dx = src_width / dst_width;
19
-
20
- e.g. If scaling from 1280x720 to 640x360, the step thru the source will be 2.0, stepping over 2 pixels of source for each pixel of destination.
21
-
22
- Centering, depends on filter mode.
23
-
24
- *Point* downsampling takes the middle pixel.
25
-
26
- x = dx >> 1;
27
-
28
- For odd scale factors (e.g. 3x down) this is exactly the middle. For even scale factors, this rounds up and takes the pixel to the right of center. e.g. scale of 4x down will take pixel 2.
29
-
30
- **Bilinear** filter, uses the 2x2 pixels in the middle.
31
-
32
- x = dx / 2 - 0.5;
33
-
34
- For odd scale factors (e.g. 3x down) this is exactly the middle, and point sampling is used.
35
- For even scale factors, this evenly filters the middle 2x2 pixels. e.g. 4x down will filter pixels 1,2 at 50% in both directions.
36
-
37
- **Box** filter averages the entire box so sampling starts at 0.
38
-
39
- x = 0;
40
-
41
- For a scale factor of 2x down, this is equivalent to bilinear.
42
-
43
- # Up Sampling
44
-
45
- **Point** upsampling use stepping rate of src_width / dst_width and a starting coordinate of 0.
46
-
47
- x = 0;
48
- dx = src_width / dst_width;
49
-
50
- e.g. If scaling from 640x360 to 1280x720 the step thru the source will be 0.0, stepping half a pixel of source for each pixel of destination. Each pixel is replicated by the scale factor.
51
-
52
- **Bilinear** filter stretches such that the first pixel of source maps to the first pixel of destination, and the last pixel of source maps to the last pixel of destination.
53
-
54
- x = 0;
55
- dx = (src_width - 1) / (dst_width - 1);
56
-
57
- This method is not technically correct, and will likely change in the future.
58
-
59
- * It is inconsistent with the bilinear down sampler. The same method could be used for down sampling, and then it would be more reversible, but that would prevent specialized 2x down sampling.
60
- * Although centered, the image is slightly magnified.
61
- * The filtering was changed in early 2013 - previously it used:
62
-
63
- x = 0;
64
- dx = (src_width - 1) / (dst_width - 1);
65
-
66
- Which is the correct scale factor, but shifted the image left, and extruded the last pixel. The reason for the change was to remove the extruding code from the low level row functions, allowing 3 functions to sshare the same row functions - ARGBScale, I420Scale, and ARGBInterpolate. Then the one function was ported to many cpu variations: SSE2, SSSE3, AVX2, Neon and 'Any' version for any number of pixels and alignment. The function is also specialized for 0,25,50,75%.
67
-
68
- The above goes still has the potential to read the last pixel 100% and last pixel + 1 0%, which may cause a memory exception. So the left pixel goes to a fraction less than the last pixel, but filters in the minimum amount of it, and the maximum of the last pixel.
69
-
70
- dx = FixedDiv((src_width << 16) - 0x00010001, (dst << 16) - 0x00010000);
71
-
72
- **Box** filter for upsampling switches over to Bilinear.
73
-
74
- # Scale snippet:
75
-
76
- #define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
77
- #define FIXEDDIV1(src, dst) FixedDiv((src << 16) - 0x00010001, \
78
- (dst << 16) - 0x00010000);
79
-
80
- // Compute slope values for stepping.
81
- void ScaleSlope(int src_width, int src_height,
82
- int dst_width, int dst_height,
83
- FilterMode filtering,
84
- int* x, int* y, int* dx, int* dy) {
85
- assert(x != NULL);
86
- assert(y != NULL);
87
- assert(dx != NULL);
88
- assert(dy != NULL);
89
- assert(src_width != 0);
90
- assert(src_height != 0);
91
- assert(dst_width > 0);
92
- assert(dst_height > 0);
93
- if (filtering == kFilterBox) {
94
- // Scale step for point sampling duplicates all pixels equally.
95
- *dx = FixedDiv(Abs(src_width), dst_width);
96
- *dy = FixedDiv(src_height, dst_height);
97
- *x = 0;
98
- *y = 0;
99
- } else if (filtering == kFilterBilinear) {
100
- // Scale step for bilinear sampling renders last pixel once for upsample.
101
- if (dst_width <= Abs(src_width)) {
102
- *dx = FixedDiv(Abs(src_width), dst_width);
103
- *x = CENTERSTART(*dx, -32768);
104
- } else if (dst_width > 1) {
105
- *dx = FIXEDDIV1(Abs(src_width), dst_width);
106
- *x = 0;
107
- }
108
- if (dst_height <= src_height) {
109
- *dy = FixedDiv(src_height, dst_height);
110
- *y = CENTERSTART(*dy, -32768); // 32768 = -0.5 to center bilinear.
111
- } else if (dst_height > 1) {
112
- *dy = FIXEDDIV1(src_height, dst_height);
113
- *y = 0;
114
- }
115
- } else if (filtering == kFilterLinear) {
116
- // Scale step for bilinear sampling renders last pixel once for upsample.
117
- if (dst_width <= Abs(src_width)) {
118
- *dx = FixedDiv(Abs(src_width), dst_width);
119
- *x = CENTERSTART(*dx, -32768);
120
- } else if (dst_width > 1) {
121
- *dx = FIXEDDIV1(Abs(src_width), dst_width);
122
- *x = 0;
123
- }
124
- *dy = FixedDiv(src_height, dst_height);
125
- *y = *dy >> 1;
126
- } else {
127
- // Scale step for point sampling duplicates all pixels equally.
128
- *dx = FixedDiv(Abs(src_width), dst_width);
129
- *dy = FixedDiv(src_height, dst_height);
130
- *x = CENTERSTART(*dx, 0);
131
- *y = CENTERSTART(*dy, 0);
132
- }
133
- // Negative src_width means horizontally mirror.
134
- if (src_width < 0) {
135
- *x += (dst_width - 1) * *dx;
136
- *dx = -*dx;
137
- src_width = -src_width;
138
- }
139
- }
140
-
141
- # Future Work
142
-
143
- Point sampling should ideally be the same as bilinear, but pixel by pixel, round to nearest neighbor. But as is, it is reversible and exactly matches ffmpeg at all scale factors, both up and down. The scale factor is
144
-
145
- dx = src_width / dst_width;
146
-
147
- The step value is centered for down sample:
148
-
149
- x = dx / 2;
150
-
151
- Or starts at 0 for upsample.
152
-
153
- x = 0;
154
-
155
- Bilinear filtering is currently correct for down sampling, but not for upsampling.
156
- Upsampling is stretching the first and last pixel of source, to the first and last pixel of destination.
157
-
158
- dx = (src_width - 1) / (dst_width - 1);<br>
159
- x = 0;
160
-
161
- It should be stretching such that the first pixel is centered in the middle of the scale factor, to match the pixel that would be sampled for down sampling by the same amount. And same on last pixel.
162
-
163
- dx = src_width / dst_width;<br>
164
- x = dx / 2 - 0.5;
165
-
166
- This would start at -0.5 and go to last pixel + 0.5, sampling 50% from last pixel + 1.
167
- Then clamping would be needed. On GPUs there are numerous ways to clamp.
168
-
169
- 1. Clamp the coordinate to the edge of the texture, duplicating the first and last pixel.
170
- 2. Blend with a constant color, such as transparent black. Typically best for fonts.
171
- 3. Mirror the UV coordinate, which is similar to clamping. Good for continuous tone images.
172
- 4. Wrap the coordinate, for texture tiling.
173
- 5. Allow the coordinate to index beyond the image, which may be the correct data if sampling a subimage.
174
- 6. Extrapolate the edge based on the previous pixel. pixel -0.5 is computed from slope of pixel 0 and 1.
175
-
176
- Some of these are computational, even for a GPU, which is one reason textures are sometimes limited to power of 2 sizes.
177
- We do care about the clipping case, where allowing coordinates to become negative and index pixels before the image is the correct data. But normally for simple scaling, we want to clamp to the edge pixel. For example, if bilinear scaling from 3x3 to 30x30, we’d essentially want 10 pixels of each of the original 3 pixels. But we want the original pixels to land in the middle of each 10 pixels, at offsets 5, 15 and 25. There would be filtering between 5 and 15 between the original pixels 0 and 1. And filtering between 15 and 25 from original pixels 1 and 2. The first 5 pixels are clamped to pixel 0 and the last 5 pixels are clamped to pixel 2.
178
- The easiest way to implement this is copy the original 3 pixels to a buffer, and duplicate the first and last pixels. 0,1,2 becomes 0, 0,1,2, 2. Then implement a filtering without clamping. We call this source extruding. Its only necessary on up sampling, since down sampler will always have valid surrounding pixels.
179
- Extruding is practical when the image is already copied to a temporary buffer. It could be done to the original image, as long as the original memory is restored, but valgrind and/or memory protection would disallow this, so it requires a memcpy to a temporary buffer, which may hurt performance. The memcpy has a performance advantage, from a cache point of view, that can actually make this technique faster, depending on hardware characteristics.
180
- Vertical extrusion can be done with a memcpy of the first/last row, or clamping a pointer.
181
-
182
-
183
- The other way to implement clamping is handle the edges with a memset. e.g. Read first source pixel and memset the first 5 pixels. Filter pixels 0,1,2 to 5 to 25. Read last pixel and memset the last 5 pixels. Blur is implemented with this method like this, which has 3 loops per row - left, middle and right.
184
-
185
- Box filter is only used for 2x down sample or more. Its based on integer sized boxes. Technically it should be filtered edges, but thats substantially slower (roughly 100x), and at that point you may as well do a cubic filter which is more correct.
186
-
187
- Box filter currently sums rows into a row buffer. It does this with
188
-
189
- Mirroring will use the same slope as normal, but with a negative.
190
- The starting coordinate needs to consider the scale factor and filter. e.g. box filter of 30x30 to 3x3 with mirroring would use -10 for step, but x = 20. width (30) - dx.
191
-
192
- Step needs to be accurate, so it uses an integer divide. This is as much as 5% of the profile. An approximated divide is substantially faster, but the inaccuracy causes stepping beyond the original image boundaries. 3 general solutions:
193
-
194
- 1. copy image to buffer with padding. allows for small errors in stepping.
195
- 2. hash the divide, so common values are quickly found.
196
- 3. change api so caller provides the slope.
1
+ # Introduction
2
+
3
+ This document discusses the current state of filtering in libyuv. An emphasis on maximum performance while avoiding memory exceptions, and minimal amount of code/complexity. See future work at end.
4
+
5
+ # LibYuv Filter Subsampling
6
+
7
+ There are 2 challenges with subsampling
8
+
9
+ 1. centering of samples, which involves clamping on edges
10
+ 2. clipping a source region
11
+
12
+ Centering depends on scale factor and filter mode.
13
+
14
+ # Down Sampling
15
+
16
+ If scaling down, the stepping rate is always src_width / dst_width.
17
+
18
+ dx = src_width / dst_width;
19
+
20
+ e.g. If scaling from 1280x720 to 640x360, the step thru the source will be 2.0, stepping over 2 pixels of source for each pixel of destination.
21
+
22
+ Centering, depends on filter mode.
23
+
24
+ *Point* downsampling takes the middle pixel.
25
+
26
+ x = dx >> 1;
27
+
28
+ For odd scale factors (e.g. 3x down) this is exactly the middle. For even scale factors, this rounds up and takes the pixel to the right of center. e.g. scale of 4x down will take pixel 2.
29
+
30
+ **Bilinear** filter, uses the 2x2 pixels in the middle.
31
+
32
+ x = dx / 2 - 0.5;
33
+
34
+ For odd scale factors (e.g. 3x down) this is exactly the middle, and point sampling is used.
35
+ For even scale factors, this evenly filters the middle 2x2 pixels. e.g. 4x down will filter pixels 1,2 at 50% in both directions.
36
+
37
+ **Box** filter averages the entire box so sampling starts at 0.
38
+
39
+ x = 0;
40
+
41
+ For a scale factor of 2x down, this is equivalent to bilinear.
42
+
43
+ # Up Sampling
44
+
45
+ **Point** upsampling use stepping rate of src_width / dst_width and a starting coordinate of 0.
46
+
47
+ x = 0;
48
+ dx = src_width / dst_width;
49
+
50
+ e.g. If scaling from 640x360 to 1280x720 the step thru the source will be 0.0, stepping half a pixel of source for each pixel of destination. Each pixel is replicated by the scale factor.
51
+
52
+ **Bilinear** filter stretches such that the first pixel of source maps to the first pixel of destination, and the last pixel of source maps to the last pixel of destination.
53
+
54
+ x = 0;
55
+ dx = (src_width - 1) / (dst_width - 1);
56
+
57
+ This method is not technically correct, and will likely change in the future.
58
+
59
+ * It is inconsistent with the bilinear down sampler. The same method could be used for down sampling, and then it would be more reversible, but that would prevent specialized 2x down sampling.
60
+ * Although centered, the image is slightly magnified.
61
+ * The filtering was changed in early 2013 - previously it used:
62
+
63
+ x = 0;
64
+ dx = (src_width - 1) / (dst_width - 1);
65
+
66
+ Which is the correct scale factor, but shifted the image left, and extruded the last pixel. The reason for the change was to remove the extruding code from the low level row functions, allowing 3 functions to sshare the same row functions - ARGBScale, I420Scale, and ARGBInterpolate. Then the one function was ported to many cpu variations: SSE2, SSSE3, AVX2, Neon and 'Any' version for any number of pixels and alignment. The function is also specialized for 0,25,50,75%.
67
+
68
+ The above goes still has the potential to read the last pixel 100% and last pixel + 1 0%, which may cause a memory exception. So the left pixel goes to a fraction less than the last pixel, but filters in the minimum amount of it, and the maximum of the last pixel.
69
+
70
+ dx = FixedDiv((src_width << 16) - 0x00010001, (dst << 16) - 0x00010000);
71
+
72
+ **Box** filter for upsampling switches over to Bilinear.
73
+
74
+ # Scale snippet:
75
+
76
+ #define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
77
+ #define FIXEDDIV1(src, dst) FixedDiv((src << 16) - 0x00010001, \
78
+ (dst << 16) - 0x00010000);
79
+
80
+ // Compute slope values for stepping.
81
+ void ScaleSlope(int src_width, int src_height,
82
+ int dst_width, int dst_height,
83
+ FilterMode filtering,
84
+ int* x, int* y, int* dx, int* dy) {
85
+ assert(x != NULL);
86
+ assert(y != NULL);
87
+ assert(dx != NULL);
88
+ assert(dy != NULL);
89
+ assert(src_width != 0);
90
+ assert(src_height != 0);
91
+ assert(dst_width > 0);
92
+ assert(dst_height > 0);
93
+ if (filtering == kFilterBox) {
94
+ // Scale step for point sampling duplicates all pixels equally.
95
+ *dx = FixedDiv(Abs(src_width), dst_width);
96
+ *dy = FixedDiv(src_height, dst_height);
97
+ *x = 0;
98
+ *y = 0;
99
+ } else if (filtering == kFilterBilinear) {
100
+ // Scale step for bilinear sampling renders last pixel once for upsample.
101
+ if (dst_width <= Abs(src_width)) {
102
+ *dx = FixedDiv(Abs(src_width), dst_width);
103
+ *x = CENTERSTART(*dx, -32768);
104
+ } else if (dst_width > 1) {
105
+ *dx = FIXEDDIV1(Abs(src_width), dst_width);
106
+ *x = 0;
107
+ }
108
+ if (dst_height <= src_height) {
109
+ *dy = FixedDiv(src_height, dst_height);
110
+ *y = CENTERSTART(*dy, -32768); // 32768 = -0.5 to center bilinear.
111
+ } else if (dst_height > 1) {
112
+ *dy = FIXEDDIV1(src_height, dst_height);
113
+ *y = 0;
114
+ }
115
+ } else if (filtering == kFilterLinear) {
116
+ // Scale step for bilinear sampling renders last pixel once for upsample.
117
+ if (dst_width <= Abs(src_width)) {
118
+ *dx = FixedDiv(Abs(src_width), dst_width);
119
+ *x = CENTERSTART(*dx, -32768);
120
+ } else if (dst_width > 1) {
121
+ *dx = FIXEDDIV1(Abs(src_width), dst_width);
122
+ *x = 0;
123
+ }
124
+ *dy = FixedDiv(src_height, dst_height);
125
+ *y = *dy >> 1;
126
+ } else {
127
+ // Scale step for point sampling duplicates all pixels equally.
128
+ *dx = FixedDiv(Abs(src_width), dst_width);
129
+ *dy = FixedDiv(src_height, dst_height);
130
+ *x = CENTERSTART(*dx, 0);
131
+ *y = CENTERSTART(*dy, 0);
132
+ }
133
+ // Negative src_width means horizontally mirror.
134
+ if (src_width < 0) {
135
+ *x += (dst_width - 1) * *dx;
136
+ *dx = -*dx;
137
+ src_width = -src_width;
138
+ }
139
+ }
140
+
141
+ # Future Work
142
+
143
+ Point sampling should ideally be the same as bilinear, but pixel by pixel, round to nearest neighbor. But as is, it is reversible and exactly matches ffmpeg at all scale factors, both up and down. The scale factor is
144
+
145
+ dx = src_width / dst_width;
146
+
147
+ The step value is centered for down sample:
148
+
149
+ x = dx / 2;
150
+
151
+ Or starts at 0 for upsample.
152
+
153
+ x = 0;
154
+
155
+ Bilinear filtering is currently correct for down sampling, but not for upsampling.
156
+ Upsampling is stretching the first and last pixel of source, to the first and last pixel of destination.
157
+
158
+ dx = (src_width - 1) / (dst_width - 1);<br>
159
+ x = 0;
160
+
161
+ It should be stretching such that the first pixel is centered in the middle of the scale factor, to match the pixel that would be sampled for down sampling by the same amount. And same on last pixel.
162
+
163
+ dx = src_width / dst_width;<br>
164
+ x = dx / 2 - 0.5;
165
+
166
+ This would start at -0.5 and go to last pixel + 0.5, sampling 50% from last pixel + 1.
167
+ Then clamping would be needed. On GPUs there are numerous ways to clamp.
168
+
169
+ 1. Clamp the coordinate to the edge of the texture, duplicating the first and last pixel.
170
+ 2. Blend with a constant color, such as transparent black. Typically best for fonts.
171
+ 3. Mirror the UV coordinate, which is similar to clamping. Good for continuous tone images.
172
+ 4. Wrap the coordinate, for texture tiling.
173
+ 5. Allow the coordinate to index beyond the image, which may be the correct data if sampling a subimage.
174
+ 6. Extrapolate the edge based on the previous pixel. pixel -0.5 is computed from slope of pixel 0 and 1.
175
+
176
+ Some of these are computational, even for a GPU, which is one reason textures are sometimes limited to power of 2 sizes.
177
+ We do care about the clipping case, where allowing coordinates to become negative and index pixels before the image is the correct data. But normally for simple scaling, we want to clamp to the edge pixel. For example, if bilinear scaling from 3x3 to 30x30, we’d essentially want 10 pixels of each of the original 3 pixels. But we want the original pixels to land in the middle of each 10 pixels, at offsets 5, 15 and 25. There would be filtering between 5 and 15 between the original pixels 0 and 1. And filtering between 15 and 25 from original pixels 1 and 2. The first 5 pixels are clamped to pixel 0 and the last 5 pixels are clamped to pixel 2.
178
+ The easiest way to implement this is copy the original 3 pixels to a buffer, and duplicate the first and last pixels. 0,1,2 becomes 0, 0,1,2, 2. Then implement a filtering without clamping. We call this source extruding. Its only necessary on up sampling, since down sampler will always have valid surrounding pixels.
179
+ Extruding is practical when the image is already copied to a temporary buffer. It could be done to the original image, as long as the original memory is restored, but valgrind and/or memory protection would disallow this, so it requires a memcpy to a temporary buffer, which may hurt performance. The memcpy has a performance advantage, from a cache point of view, that can actually make this technique faster, depending on hardware characteristics.
180
+ Vertical extrusion can be done with a memcpy of the first/last row, or clamping a pointer.
181
+
182
+
183
+ The other way to implement clamping is handle the edges with a memset. e.g. Read first source pixel and memset the first 5 pixels. Filter pixels 0,1,2 to 5 to 25. Read last pixel and memset the last 5 pixels. Blur is implemented with this method like this, which has 3 loops per row - left, middle and right.
184
+
185
+ Box filter is only used for 2x down sample or more. Its based on integer sized boxes. Technically it should be filtered edges, but thats substantially slower (roughly 100x), and at that point you may as well do a cubic filter which is more correct.
186
+
187
+ Box filter currently sums rows into a row buffer. It does this with
188
+
189
+ Mirroring will use the same slope as normal, but with a negative.
190
+ The starting coordinate needs to consider the scale factor and filter. e.g. box filter of 30x30 to 3x3 with mirroring would use -10 for step, but x = 20. width (30) - dx.
191
+
192
+ Step needs to be accurate, so it uses an integer divide. This is as much as 5% of the profile. An approximated divide is substantially faster, but the inaccuracy causes stepping beyond the original image boundaries. 3 general solutions:
193
+
194
+ 1. copy image to buffer with padding. allows for small errors in stepping.
195
+ 2. hash the divide, so common values are quickly found.
196
+ 3. change api so caller provides the slope.