react-native-vision-camera-spoof-detector 1.0.22 → 1.0.24

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 (206) hide show
  1. package/README.md +442 -442
  2. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  3. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  4. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  5. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  6. package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
  7. package/android/build/reports/problems/problems-report.html +659 -0
  8. package/android/build.gradle +12 -4
  9. package/android/src/main/cpp/CMakeLists.txt +101 -94
  10. package/android/src/main/cpp/libyuv/.clang-format +6 -6
  11. package/android/src/main/cpp/libyuv/.gn +40 -40
  12. package/android/src/main/cpp/libyuv/.vpython3 +410 -410
  13. package/android/src/main/cpp/libyuv/AUTHORS +7 -7
  14. package/android/src/main/cpp/libyuv/Android.bp +202 -202
  15. package/android/src/main/cpp/libyuv/Android.mk +106 -106
  16. package/android/src/main/cpp/libyuv/BUILD.gn +490 -490
  17. package/android/src/main/cpp/libyuv/CM_linux_packages.cmake +70 -70
  18. package/android/src/main/cpp/libyuv/CMakeLists.txt +259 -252
  19. package/android/src/main/cpp/libyuv/DEPS +935 -935
  20. package/android/src/main/cpp/libyuv/DIR_METADATA +3 -3
  21. package/android/src/main/cpp/libyuv/LICENSE +29 -29
  22. package/android/src/main/cpp/libyuv/OWNERS +11 -11
  23. package/android/src/main/cpp/libyuv/PATENTS +23 -23
  24. package/android/src/main/cpp/libyuv/PRESUBMIT.py +65 -65
  25. package/android/src/main/cpp/libyuv/README.chromium +11 -11
  26. package/android/src/main/cpp/libyuv/README.md +19 -19
  27. package/android/src/main/cpp/libyuv/build_overrides/build.gni +60 -60
  28. package/android/src/main/cpp/libyuv/build_overrides/gtest.gni +19 -19
  29. package/android/src/main/cpp/libyuv/build_overrides/partition_alloc.gni +17 -17
  30. package/android/src/main/cpp/libyuv/codereview.settings +5 -5
  31. package/android/src/main/cpp/libyuv/docs/deprecated_builds.md +409 -409
  32. package/android/src/main/cpp/libyuv/docs/environment_variables.md +64 -64
  33. package/android/src/main/cpp/libyuv/docs/feature_detection.md +108 -108
  34. package/android/src/main/cpp/libyuv/docs/filtering.md +196 -196
  35. package/android/src/main/cpp/libyuv/docs/formats.md +208 -208
  36. package/android/src/main/cpp/libyuv/docs/getting_started.md +296 -296
  37. package/android/src/main/cpp/libyuv/docs/rotation.md +107 -107
  38. package/android/src/main/cpp/libyuv/download_vs_toolchain.py +29 -29
  39. package/android/src/main/cpp/libyuv/include/libyuv/basic_types.h +68 -68
  40. package/android/src/main/cpp/libyuv/include/libyuv/compare.h +111 -111
  41. package/android/src/main/cpp/libyuv/include/libyuv/compare_row.h +112 -112
  42. package/android/src/main/cpp/libyuv/include/libyuv/convert.h +1117 -1117
  43. package/android/src/main/cpp/libyuv/include/libyuv/convert_argb.h +2335 -2335
  44. package/android/src/main/cpp/libyuv/include/libyuv/convert_from.h +203 -203
  45. package/android/src/main/cpp/libyuv/include/libyuv/convert_from_argb.h +394 -394
  46. package/android/src/main/cpp/libyuv/include/libyuv/cpu_id.h +147 -147
  47. package/android/src/main/cpp/libyuv/include/libyuv/cpu_support.h +99 -99
  48. package/android/src/main/cpp/libyuv/include/libyuv/loongson_intrinsics.h +1949 -1949
  49. package/android/src/main/cpp/libyuv/include/libyuv/mjpeg_decoder.h +195 -195
  50. package/android/src/main/cpp/libyuv/include/libyuv/planar_functions.h +1131 -1131
  51. package/android/src/main/cpp/libyuv/include/libyuv/rotate.h +296 -296
  52. package/android/src/main/cpp/libyuv/include/libyuv/rotate_argb.h +37 -37
  53. package/android/src/main/cpp/libyuv/include/libyuv/rotate_row.h +265 -265
  54. package/android/src/main/cpp/libyuv/include/libyuv/row.h +6738 -6738
  55. package/android/src/main/cpp/libyuv/include/libyuv/row_sve.h +2154 -2154
  56. package/android/src/main/cpp/libyuv/include/libyuv/scale.h +336 -336
  57. package/android/src/main/cpp/libyuv/include/libyuv/scale_argb.h +76 -76
  58. package/android/src/main/cpp/libyuv/include/libyuv/scale_rgb.h +42 -42
  59. package/android/src/main/cpp/libyuv/include/libyuv/scale_row.h +1726 -1726
  60. package/android/src/main/cpp/libyuv/include/libyuv/scale_uv.h +51 -51
  61. package/android/src/main/cpp/libyuv/include/libyuv/version.h +16 -16
  62. package/android/src/main/cpp/libyuv/include/libyuv/video_common.h +222 -222
  63. package/android/src/main/cpp/libyuv/include/libyuv.h +33 -33
  64. package/android/src/main/cpp/libyuv/infra/config/OWNERS +3 -3
  65. package/android/src/main/cpp/libyuv/infra/config/PRESUBMIT.py +17 -17
  66. package/android/src/main/cpp/libyuv/infra/config/README.md +2 -2
  67. package/android/src/main/cpp/libyuv/infra/config/codereview.settings +6 -6
  68. package/android/src/main/cpp/libyuv/infra/config/commit-queue.cfg +144 -144
  69. package/android/src/main/cpp/libyuv/infra/config/cr-buildbucket.cfg +1185 -1185
  70. package/android/src/main/cpp/libyuv/infra/config/luci-logdog.cfg +9 -9
  71. package/android/src/main/cpp/libyuv/infra/config/luci-milo.cfg +246 -246
  72. package/android/src/main/cpp/libyuv/infra/config/luci-scheduler.cfg +385 -385
  73. package/android/src/main/cpp/libyuv/infra/config/main.star +402 -402
  74. package/android/src/main/cpp/libyuv/infra/config/project.cfg +16 -16
  75. package/android/src/main/cpp/libyuv/infra/config/realms.cfg +111 -111
  76. package/android/src/main/cpp/libyuv/libyuv.gni +34 -34
  77. package/android/src/main/cpp/libyuv/libyuv.gyp +149 -149
  78. package/android/src/main/cpp/libyuv/libyuv.gypi +87 -87
  79. package/android/src/main/cpp/libyuv/linux.mk +96 -96
  80. package/android/src/main/cpp/libyuv/public.mk +13 -13
  81. package/android/src/main/cpp/libyuv/pylintrc +49 -49
  82. package/android/src/main/cpp/libyuv/riscv_script/prepare_toolchain_qemu.sh +74 -74
  83. package/android/src/main/cpp/libyuv/riscv_script/riscv-clang.cmake +56 -56
  84. package/android/src/main/cpp/libyuv/riscv_script/run_qemu.sh +15 -15
  85. package/android/src/main/cpp/libyuv/source/compare.cc +435 -435
  86. package/android/src/main/cpp/libyuv/source/compare_common.cc +74 -74
  87. package/android/src/main/cpp/libyuv/source/compare_gcc.cc +362 -362
  88. package/android/src/main/cpp/libyuv/source/compare_neon.cc +96 -96
  89. package/android/src/main/cpp/libyuv/source/compare_neon64.cc +223 -223
  90. package/android/src/main/cpp/libyuv/source/compare_win.cc +241 -241
  91. package/android/src/main/cpp/libyuv/source/convert.cc +4746 -4746
  92. package/android/src/main/cpp/libyuv/source/convert_argb.cc +9179 -9179
  93. package/android/src/main/cpp/libyuv/source/convert_from.cc +866 -866
  94. package/android/src/main/cpp/libyuv/source/convert_from_argb.cc +3671 -3671
  95. package/android/src/main/cpp/libyuv/source/convert_jpeg.cc +602 -602
  96. package/android/src/main/cpp/libyuv/source/convert_to_argb.cc +391 -391
  97. package/android/src/main/cpp/libyuv/source/convert_to_i420.cc +288 -288
  98. package/android/src/main/cpp/libyuv/source/cpu_id.cc +496 -496
  99. package/android/src/main/cpp/libyuv/source/mjpeg_decoder.cc +580 -580
  100. package/android/src/main/cpp/libyuv/source/mjpeg_validate.cc +71 -71
  101. package/android/src/main/cpp/libyuv/source/planar_functions.cc +5663 -5663
  102. package/android/src/main/cpp/libyuv/source/rotate.cc +1241 -1241
  103. package/android/src/main/cpp/libyuv/source/rotate_any.cc +76 -76
  104. package/android/src/main/cpp/libyuv/source/rotate_argb.cc +259 -259
  105. package/android/src/main/cpp/libyuv/source/rotate_common.cc +208 -208
  106. package/android/src/main/cpp/libyuv/source/rotate_gcc.cc +505 -505
  107. package/android/src/main/cpp/libyuv/source/rotate_lsx.cc +233 -233
  108. package/android/src/main/cpp/libyuv/source/rotate_neon.cc +219 -219
  109. package/android/src/main/cpp/libyuv/source/rotate_neon64.cc +273 -273
  110. package/android/src/main/cpp/libyuv/source/rotate_sme.cc +174 -174
  111. package/android/src/main/cpp/libyuv/source/rotate_win.cc +253 -253
  112. package/android/src/main/cpp/libyuv/source/row_any.cc +2519 -2519
  113. package/android/src/main/cpp/libyuv/source/row_common.cc +4461 -4461
  114. package/android/src/main/cpp/libyuv/source/row_gcc.cc +9570 -9570
  115. package/android/src/main/cpp/libyuv/source/row_lasx.cc +2343 -2343
  116. package/android/src/main/cpp/libyuv/source/row_lsx.cc +3030 -3030
  117. package/android/src/main/cpp/libyuv/source/row_neon.cc +4026 -4026
  118. package/android/src/main/cpp/libyuv/source/row_neon64.cc +5617 -5617
  119. package/android/src/main/cpp/libyuv/source/row_rvv.cc +2599 -2599
  120. package/android/src/main/cpp/libyuv/source/row_sme.cc +1183 -1183
  121. package/android/src/main/cpp/libyuv/source/row_sve.cc +1088 -1088
  122. package/android/src/main/cpp/libyuv/source/row_win.cc +6453 -6453
  123. package/android/src/main/cpp/libyuv/source/scale.cc +2710 -2710
  124. package/android/src/main/cpp/libyuv/source/scale_any.cc +991 -991
  125. package/android/src/main/cpp/libyuv/source/scale_argb.cc +1158 -1158
  126. package/android/src/main/cpp/libyuv/source/scale_common.cc +1977 -1977
  127. package/android/src/main/cpp/libyuv/source/scale_gcc.cc +2947 -2947
  128. package/android/src/main/cpp/libyuv/source/scale_lsx.cc +739 -739
  129. package/android/src/main/cpp/libyuv/source/scale_neon.cc +1449 -1449
  130. package/android/src/main/cpp/libyuv/source/scale_neon64.cc +1552 -1552
  131. package/android/src/main/cpp/libyuv/source/scale_rgb.cc +82 -82
  132. package/android/src/main/cpp/libyuv/source/scale_rvv.cc +1971 -1971
  133. package/android/src/main/cpp/libyuv/source/scale_sme.cc +555 -555
  134. package/android/src/main/cpp/libyuv/source/scale_uv.cc +1159 -1159
  135. package/android/src/main/cpp/libyuv/source/scale_win.cc +1392 -1392
  136. package/android/src/main/cpp/libyuv/source/test.sh +35 -35
  137. package/android/src/main/cpp/libyuv/source/video_common.cc +62 -62
  138. package/android/src/main/cpp/libyuv/tools_libyuv/OWNERS +4 -4
  139. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/roll_deps.py +931 -931
  140. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/roll_deps_test.py +164 -164
  141. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS +21 -21
  142. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.new +13 -13
  143. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old +13 -13
  144. package/android/src/main/cpp/libyuv/tools_libyuv/get_landmines.py +38 -38
  145. package/android/src/main/cpp/libyuv/tools_libyuv/msan/OWNERS +3 -3
  146. package/android/src/main/cpp/libyuv/tools_libyuv/msan/blacklist.txt +9 -9
  147. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/OWNERS +3 -3
  148. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/blacklist.txt +15 -15
  149. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/vptr_blacklist.txt +25 -25
  150. package/android/src/main/cpp/libyuv/unit_test/basictypes_test.cc +43 -43
  151. package/android/src/main/cpp/libyuv/unit_test/color_test.cc +848 -848
  152. package/android/src/main/cpp/libyuv/unit_test/compare_test.cc +739 -739
  153. package/android/src/main/cpp/libyuv/unit_test/convert_argb_test.cc +2867 -2867
  154. package/android/src/main/cpp/libyuv/unit_test/convert_test.cc +2133 -2133
  155. package/android/src/main/cpp/libyuv/unit_test/cpu_test.cc +427 -427
  156. package/android/src/main/cpp/libyuv/unit_test/cpu_thread_test.cc +63 -63
  157. package/android/src/main/cpp/libyuv/unit_test/math_test.cc +160 -160
  158. package/android/src/main/cpp/libyuv/unit_test/planar_test.cc +4731 -4731
  159. package/android/src/main/cpp/libyuv/unit_test/rotate_argb_test.cc +334 -334
  160. package/android/src/main/cpp/libyuv/unit_test/rotate_test.cc +962 -962
  161. package/android/src/main/cpp/libyuv/unit_test/scale_argb_test.cc +590 -590
  162. package/android/src/main/cpp/libyuv/unit_test/scale_plane_test.cc +465 -465
  163. package/android/src/main/cpp/libyuv/unit_test/scale_rgb_test.cc +280 -280
  164. package/android/src/main/cpp/libyuv/unit_test/scale_test.cc +1135 -1135
  165. package/android/src/main/cpp/libyuv/unit_test/scale_uv_test.cc +249 -249
  166. package/android/src/main/cpp/libyuv/unit_test/testdata/arm_v7.txt +12 -12
  167. package/android/src/main/cpp/libyuv/unit_test/testdata/mips.txt +7 -7
  168. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson2k.txt +5 -5
  169. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson3.txt +10 -10
  170. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson_mmi.txt +7 -7
  171. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64.txt +3 -3
  172. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv.txt +3 -3
  173. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv_zvfh.txt +3 -3
  174. package/android/src/main/cpp/libyuv/unit_test/testdata/tegra3.txt +23 -23
  175. package/android/src/main/cpp/libyuv/unit_test/unit_test.cc +581 -581
  176. package/android/src/main/cpp/libyuv/unit_test/unit_test.h +232 -232
  177. package/android/src/main/cpp/libyuv/unit_test/video_common_test.cc +112 -112
  178. package/android/src/main/cpp/libyuv/util/Makefile +9 -9
  179. package/android/src/main/cpp/libyuv/util/color.cc +120 -120
  180. package/android/src/main/cpp/libyuv/util/compare.cc +67 -67
  181. package/android/src/main/cpp/libyuv/util/cpuid.c +211 -211
  182. package/android/src/main/cpp/libyuv/util/i444tonv12_eg.cc +27 -27
  183. package/android/src/main/cpp/libyuv/util/psnr.cc +291 -291
  184. package/android/src/main/cpp/libyuv/util/psnr.h +47 -47
  185. package/android/src/main/cpp/libyuv/util/psnr_main.cc +620 -620
  186. package/android/src/main/cpp/libyuv/util/ssim.cc +364 -364
  187. package/android/src/main/cpp/libyuv/util/ssim.h +38 -38
  188. package/android/src/main/cpp/libyuv/util/yuvconstants.c +114 -114
  189. package/android/src/main/cpp/libyuv/util/yuvconvert.cc +367 -367
  190. package/android/src/main/cpp/libyuv/winarm.mk +47 -47
  191. package/index.js +17 -1
  192. package/ios/FaceAntiSpoofFrameProcessor.swift +283 -0
  193. package/ios/FaceAntiSpoofJSI.h +12 -0
  194. package/ios/FaceAntiSpoofJSI.mm +92 -0
  195. package/ios/FaceAntiSpoofManager.swift +63 -0
  196. package/ios/FaceAntiSpoofModule.m +191 -0
  197. package/ios/FaceAntiSpoofPluginRegister.m +42 -0
  198. package/ios/models/FaceAntiSpoofing.tflite +0 -0
  199. package/ios/models/model_spec.json +16 -0
  200. package/package.json +87 -86
  201. package/.gitignore +0 -27
  202. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  203. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  204. package/android/.gradle/8.9/gc.properties +0 -0
  205. /package/android/.gradle/{8.9 → 9.2.0}/fileChanges/last-build.bin +0 -0
  206. /package/android/.gradle/{8.9/dependencies-accessors → 9.2.0}/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.